我們?cè)贕PIO和外部中斷的基礎(chǔ)功能測(cè)試的基礎(chǔ)上進(jìn)行定時(shí)器功能的測(cè)試。在GPIO和外部中斷我們實(shí)現(xiàn)的按鍵中斷的采集以及LED的控制,在次基礎(chǔ)上加入定時(shí)器功能會(huì)擦出怎么樣的火花呢?是的,第一個(gè)就是LED的閃爍,在定時(shí)器中斷中進(jìn)行LED的翻轉(zhuǎn)。
我們先了解一下MAX78000的定時(shí)器:
MAX78000具有32位定時(shí)器/計(jì)數(shù)器/PWM (TMR, LPTMR),通用的32位定時(shí)器提供定時(shí)、捕獲/比較或脈寬調(diào)制(PWM)信號(hào)的生成。定時(shí)器提供以下功能:
●32位向上/向下自動(dòng)重新加載
●可編程預(yù)分頻器
●PWM輸出產(chǎn)生
●捕獲、比較和捕獲/比較能力
●外部引腳與GPIO復(fù)用,用于定時(shí)器輸入,時(shí)鐘門控,或捕獲
●計(jì)時(shí)器輸出管腳
●TMR0-TMR3可配置為2 × 16位通用定時(shí)器
●定時(shí)器中斷
MAX78000一共提供6個(gè)32位定時(shí)器(TMR0、TMR1、TMR2、TMR3、LPTMR0和LPTMR1)。LPTMR0和LPTMR1可以在SLEEP、LOW POWER和MICRO POWER模式下運(yùn)行。所有計(jì)時(shí)器都支持I/O功能。請(qǐng)注意,端口的功能可以與其他功能進(jìn)行復(fù)用在GPIO引腳上。(在max78000.h中,6個(gè)定時(shí)器被描述為MXC_TMR0~MXC_TMR5)。
每一個(gè)定時(shí)器能夠?qū)崿F(xiàn)的功能如下:
在這里我們就要考慮一下本章節(jié)測(cè)試需要使用哪個(gè)定時(shí)器呢?基本定時(shí)功能基本上都能實(shí)現(xiàn),那么PWM的展現(xiàn)可能需要與LED相結(jié)合。我們首先實(shí)現(xiàn)基礎(chǔ)定時(shí)器功能,通過定時(shí)器中斷中實(shí)現(xiàn)LED的翻轉(zhuǎn)。
基礎(chǔ)定時(shí)功能:
要想實(shí)現(xiàn)LED是連續(xù)翻轉(zhuǎn),我們需要選擇定時(shí)器為Counter Mode。
為此我們參考例程定時(shí)器初始化內(nèi)容如下:
#define Basic_CLOCK_SOURCE MXC_TMR_8M_CLK
#define Basic_FREQ 2// (Hz)
#define Basic_TIMER MXC_TMR3
void BasicTimerInit()
{
mxc_tmr_cfg_t tmr;
uint32_t periodTicks = MXC_TMR_GetPeriod(Basic_TIMER, Basic_CLOCK_SOURCE, 128, Basic_FREQ);
MXC_TMR_Shutdown(Basic_TIMER);
tmr.pres = TMR_PRES_128;
tmr.mode = TMR_MODE_CONTINUOUS;
tmr.bitMode = TMR_BIT_MODE_16B;
tmr.clock = Basic_CLOCK_SOURCE;
tmr.cmp_cnt = periodTicks; //SystemCoreClock*(1/interval_time);
tmr.pol = 0;
if (MXC_TMR_Init(Basic_TIMER, &tmr, true) != E_NO_ERROR) {
printf("Failed Continuous timer Initialization.\n");
return;
}
MXC_NVIC_SetVector(TMR3_IRQn, BasicTimerHandler);
NVIC_EnableIRQ(TMR3_IRQn);
printf("Continuous timer started.\n");
MXC_TMR_Start(Basic_TIMER);
}
我們創(chuàng)建中斷并編寫中斷程序:
void BasicTimerHandler()
{
MXC_TMR_ClearFlags(Basic_TIMER);
LED_Toggle(LEDSt);
}
以上代碼測(cè)試開始后出現(xiàn)了異常,我們經(jīng)過定位發(fā)現(xiàn)程序卡在了while (!(tmr->ctrl1 & MXC_F_TMR_REVB_CTRL1_CLKEN_A)),也就是說定時(shí)器開啟使能失敗了,通過
MXC_SYS_IsClockEnabled(MXC_SYS_PERIPH_CLOCK_TMR1)檢查時(shí)鐘發(fā)現(xiàn)已經(jīng)開啟了。嘗試重新加載例程看一下,同樣的問題。、
通過不斷的測(cè)試目前的的現(xiàn)象更傾向于無限進(jìn)入中斷,都不用開啟定時(shí)器計(jì)數(shù),只要定時(shí)器初始化完成就開啟潘多拉魔盒,計(jì)數(shù)就開始亂跳了。進(jìn)行深層的挖掘發(fā)現(xiàn)在tmr_revb.c中的void MXC_TMR_RevB_ConfigGeneric函數(shù)(定時(shí)器初始化的底層函數(shù))中,如果tmr.bitMode = TMR_BIT_MODE_16B則直接啟動(dòng)中斷和定時(shí)器,到這里看似已經(jīng)慢慢的揭開了這個(gè)異常的面紗。不過我準(zhǔn)備放棄了,另尋途徑,既然tmr.bitMode = TMR_BIT_MODE_16B會(huì)造成這種不可接受的異常,那么配置TMR_BIT_MODE_16A試一下,修改代碼如下:
void BasicTimerInit()
{
mxc_tmr_cfg_t tmr;
uint32_t periodTicks = MXC_TMR_GetPeriod(Basic_TIMER, Basic_CLOCK_SOURCE, 128, Basic_FREQ);
MXC_TMR_Shutdown(Basic_TIMER);
tmr.pres = TMR_PRES_128;
tmr.mode = TMR_MODE_CONTINUOUS;
tmr.bitMode = TMR_BIT_MODE_16A;
tmr.clock = Basic_CLOCK_SOURCE;
tmr.cmp_cnt = periodTicks; //SystemCoreClock*(1/interval_time);
tmr.pol = 0;
if (MXC_TMR_Init(Basic_TIMER, &tmr, false) != E_NO_ERROR) {
printf("Failed Continuous timer Initialization.\n");
return;
}
MXC_NVIC_SetVector(TMR3_IRQn, BasicTimerHandler);
NVIC_EnableIRQ(TMR3_IRQn);
MXC_TMR_EnableInt(Basic_TIMER);
printf("Continuous timer started.\n");
MXC_TMR_Start(Basic_TIMER);
}
柳暗花明啊,這是一個(gè)bitMode引發(fā)的慘案,不過結(jié)果是好,使用TMR_BIT_MODE_16A后,可以正常進(jìn)入中斷了,程序正常運(yùn)行了,也算達(dá)到了預(yù)期。
PWM輸出功能:
在PWM模式下,定時(shí)器使用定時(shí)器的輸出信號(hào)發(fā)送PWM輸出。計(jì)時(shí)器首先計(jì)數(shù)到匹配值存儲(chǔ)在TMRn_PWM.pwm寄存器中。在循環(huán)結(jié)束時(shí),TMRn_CNT值與TMRn_PWM.pwm比較,定時(shí)器輸出信號(hào)切換狀態(tài)。計(jì)時(shí)器繼續(xù)計(jì)數(shù),直到到達(dá)TMRn_CMP值。
定時(shí)器周期在TMRn_CNT = TMRn_CMP之后的fCNT_CLK上升沿結(jié)束。計(jì)時(shí)器外設(shè)在計(jì)時(shí)器周期結(jié)束時(shí)自動(dòng)執(zhí)行以下動(dòng)作:
•TMRn_CNT復(fù)位為0x0000 0001,定時(shí)器恢復(fù)計(jì)數(shù)。
•定時(shí)器輸出信號(hào)切換。
•對(duì)應(yīng)的TMRn_INTFL.irq字段設(shè)置為1,表示發(fā)生了定時(shí)器中斷事件。
當(dāng)TMRn_CTRL0.pol = 0,時(shí),定時(shí)器輸出信號(hào)從低開始,到TMRn_CNT值時(shí)變?yōu)楦咂ヅ銽MRn_PWM值。定時(shí)器輸出信號(hào)保持高電平,直到TMRn_CNT值達(dá)到TMRn_CMP,導(dǎo)致定時(shí)器輸出信號(hào)變低,TMRn_CNT值復(fù)位為0x0000 0001。
當(dāng)TMRn_CTRL0.pol = 1,時(shí),定時(shí)器輸出信號(hào)高起始,當(dāng)TMRn_CNT值與TMRn_PWM值,定時(shí)器輸出信號(hào)保持低電平,直到TMRn_CNT值達(dá)到TMRn_CMP,導(dǎo)致定時(shí)器輸出信號(hào)轉(zhuǎn)高,TMRn_CNT值復(fù)位為0x0000 0001。
測(cè)試代碼如下:
#define PWM_CLOCK_SOURCE MXC_TMR_32K_CLK
#define FREQ 10 // (Hz)
#define DUTY_CYCLE 50 // (%)
#define PWM_TIMER MXC_TMR4
void PWMTimer()
{
mxc_tmr_cfg_t tmr; // to configure timer
unsigned int periodTicks = MXC_TMR_GetPeriod(PWM_TIMER, PWM_CLOCK_SOURCE, 16, FREQ);
unsigned int dutyTicks = periodTicks * DUTY_CYCLE / 100;
MXC_TMR_Shutdown(PWM_TIMER);
tmr.pres = TMR_PRES_16;
tmr.mode = TMR_MODE_PWM;
tmr.bitMode = TMR_BIT_MODE_32;
tmr.clock = PWM_CLOCK_SOURCE;
tmr.cmp_cnt = periodTicks;
tmr.pol = 1;
if (MXC_TMR_Init(PWM_TIMER, &tmr, true) != E_NO_ERROR) {
printf("Failed PWM timer Initialization.\n");
return;
}
if (MXC_TMR_SetPWM(PWM_TIMER, dutyTicks) != E_NO_ERROR) {
printf("Failed TMR_PWMConfig.\n");
return;
}
MXC_TMR_Start(PWM_TIMER);
printf("PWM started.\n\n");
}
效果如下:
精彩視頻分享:
串口接收情況(定時(shí)器基礎(chǔ)定時(shí)測(cè)試)
定時(shí)器基礎(chǔ)定時(shí)測(cè)試效果展示
定時(shí)器PWM測(cè)試效果展示