一、定時器原理
????????F28335 城市的三座時鐘塔(Timer0、Timer1、Timer2)是城市時間管理的核心設施,每座均為32位精度,依靠城市能源脈沖(系統時鐘 SYSCLKOUT,典型頻率為150 MHz)驅動。它們由兩個核心模塊組成:節奏調節站(預分頻模塊)和計時核心站(定時/計數模塊),協同工作以實現精確計時。
節奏調節站(預分頻模塊):
- 節奏分頻器(16位定時器分頻寄存器 TDDRH:TDDR):決定城市能源脈沖的“放慢”倍數。例如,若 TDDR=9,則每10個脈沖(從0到9)產生一次有效信號,相當于將脈沖頻率除以10。
- 節奏計數器(16位預定標計數器 PSCH:PSC):記錄收到的脈沖數。每次脈沖到來,PSC 減1;當 PSC 減到0時,觸發“下溢”,向計時核心站發送信號,并重新裝載 TDDR 的值,開始下一輪計數。
計時核心站(定時/計數模塊):
- 周期藍圖(32位周期寄存器 PRDH:PRD):定義一次完整計時周期的長度,決定時鐘塔多久敲響一次“鐘聲”。
- 計時器(32位計數寄存器 TIMH:TIM):記錄當前計時進度。每次從節奏調節站收到信號,TIM 減1;當 TIM 減到0時,觸發“下溢”,產生“鐘聲”(中斷信號),并重新裝載 PRD 的值。
工作流程如下:
- 城市能源脈沖(SYSCLKOUT)每跳動一次,節奏計數器(PSC)減1。
- 當 PSC 減到0,觸發下溢,向計時器(TIM)發送信號,TIM 減1,同時 PSC 重新裝載 TDDR 的值。
- 當 TIM 減到0,觸發下溢,產生中斷信號(TINT0、TINT1 或 TINT2),通知中央政府(CPU),并重新裝載 PRD 的值,循環往復。
????????時鐘塔的“鐘聲”通過城市通信網絡(PIE 中斷系統)傳遞,Timer0 的中斷(TINT0)屬于第一組第七個小信號(PIEIER1.bit.INTx7)。中斷信號經過 PIE 模塊處理后到達中央政府,確保任務按時執行。
周期計算公式:
定時周期 = (PRD + 1) × (TDDR + 1) × (1 / SYSCLKOUT)
例如,若 SYSCLKOUT=150 MHz(周期6.67 ns),PRD=14999999,TDDR=9,則定時周期為:
(14999999 + 1) × (9 + 1) × 6.67 ns = 15000000 × 10 × 6.67 ns = 1秒。
二、具體代碼
2.1?ConfigCpuTimer 函數
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{Uint32 temp;// Initialize timer period:Timer->CPUFreqInMHz = Freq;Timer->PeriodInUSec = Period;temp = (long)(Freq * Period);Timer->RegsAddr->PRD.all = temp;// Set pre-scale counter to divide by 1 (SYSCLKOUT):Timer->RegsAddr->TPR.all = 0;Timer->RegsAddr->TPRH.all = 0;// Initialize timer control register:Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart TimerTimer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timerTimer->RegsAddr->TCR.bit.SOFT = 0;Timer->RegsAddr->TCR.bit.FREE = 0; // Timer Free Run DisabledTimer->RegsAddr->TCR.bit.TIE = 1; // 0 = Disable/ 1 = Enable Timer Interrupt// Reset interrupt counter:Timer->InterruptCount = 0;
}
功能概述
ConfigCpuTimer
是城市提供的一套標準管理工具(庫函數),用于配置任意一座時鐘塔(Timer0、Timer1 或 Timer2)的運行參數。根據城市需求調整時鐘塔的節奏和計時周期,確保其“鐘聲”(中斷信號)按預期時間響起。該函數接受三個參數:
- Timer:指向時鐘塔管理結構(
CPUTIMER_VARS
)的指針,包含時鐘塔的寄存器地址、頻率、周期等信息。 - Freq:城市能源脈沖頻率(單位:MHz,例如 150 MHz)。
- Period:期望的計時周期(單位:微秒,例如 500000 表示 500ms)。
詳細分析
參數存儲:
Timer->CPUFreqInMHz = Freq;
Timer->PeriodInUSec = Period;
- 將輸入的頻率和周期存儲到?
Timer
?結構中,便于后續管理和調試。 - 例如,若 Freq=150,Period=500000,則記錄 CPU 頻率為 150 MHz,周期為 500ms。
- 將輸入的頻率和周期存儲到?
計算周期藍圖(PRD 值):
temp = (long)(Freq * Period);
Timer->RegsAddr->PRD.all = temp;
- 計算周期寄存器(PRD)的值,決定時鐘塔敲響“鐘聲”的時間間隔。
- 公式:
PRD = Freq * Period
,其中 Freq(MHz)× Period(微秒)= 周期脈沖數。 - 示例:若 Freq=150 MHz,Period=500000 微秒(500ms),則:
PRD = 150 * 500000 = 75000000
- 表示時鐘塔需要計數 75000000 個脈沖(每個脈沖 6.67 ns,150 MHz 的倒數),對應 500ms。
- 注意:實際硬件實現中,PRD 寄存器從 0 計數到 PRD 值(含 0,共 PRD+1 次),但此處代碼直接使用?
Freq * Period
,未減 1,可能導致周期略偏,實際周期為 (PRD+1) × (1/SYSCLKOUT)。開發者需根據硬件手冊驗證是否需要調整。
設置節奏調節站(TPR/TPRH):
Timer->RegsAddr->TPR.all = 0;
Timer->RegsAddr->TPRH.all = 0;
- 將預定標寄存器(TPR/TPRH)清零,表示不使用分頻(TDDR=0,PSC=0)。
- 此時,SYSCLKOUT 的每個脈沖直接驅動 TIM 計數器減 1,分頻系數為 1。
- 公式:定時周期 = (PRD+1) × (TDDR+1) × (1/SYSCLKOUT),由于 TDDR=0,周期簡化為:
定時周期 = (PRD+1) × (1/SYSCLKOUT)
示例:PRD=75000000,SYSCLKOUT=150 MHz(周期 6.67 ns),則:
定時周期 = (75000000+1) × 6.67 ns ≈ 500000006.67 ns ≈ 500ms
4.配置時鐘塔控制面板(TCR):
Timer->RegsAddr->TCR.bit.TSS = 1; // 停止時鐘塔
Timer->RegsAddr->TCR.bit.TRB = 1; // 啟用重載
Timer->RegsAddr->TCR.bit.SOFT = 0; // 非軟啟動
Timer->RegsAddr->TCR.bit.FREE = 0; // 非自由運行
Timer->RegsAddr->TCR.bit.TIE = 1; // 啟用中斷
- TSS=1:停止時鐘塔(Timer Stop Status),確保在配置期間不運行。
- TRB=1:啟用重載(Timer Reload Bit),當 TIM 計數器歸零時,自動從 PRD 重新裝載值。
- SOFT=0, FREE=0:禁用軟啟動和自由運行模式,確保時鐘塔在調試時暫停,適合精確控制。
- TIE=1:啟用中斷(Timer Interrupt Enable),允許時鐘塔在 TIM 歸零時產生“鐘聲”(中斷信號)。
5.重置中斷計數:
Timer->InterruptCount = 0;
- 清零中斷計數器,記錄時鐘塔觸發的中斷次數(用于調試或統計)。
2.2?TIM0_Init 函數
void TIM0_Init(float Freq, float Period)
{EALLOW;SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0EDIS;EALLOW;PieVectTable.TINT0 = &TIM0_IRQn;EDIS;CpuTimer0.RegsAddr = &CpuTimer0Regs;CpuTimer0Regs.PRD.all = 0xFFFFFFFF;CpuTimer0Regs.TPR.all = 0;CpuTimer0Regs.TPRH.all = 0;CpuTimer0Regs.TCR.bit.TSS = 1;CpuTimer0Regs.TCR.bit.TRB = 1;CpuTimer0.InterruptCount = 0;ConfigCpuTimer(&CpuTimer0, Freq, Period);CpuTimer0Regs.TCR.bit.TSS = 0;IER |= M_INT1;PieCtrlRegs.PIEIER1.bit.INTx7 = 1;EINT;ERTM;
}
詳細分析
啟動能源供應:
EALLOW; SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; EDIS;
- 打開 Timer0 的能源開關(PCLKCR3.bit.CPUTIMER0ENCLK=1),連接城市電力網絡(SYSCLKOUT)。
- EALLOW 和 EDIS 用于解除和恢復寄存器寫保護,確保安全操作。
設置中斷通信地址:
EALLOW; PieVectTable.TINT0 = &TIM0_IRQn; EDIS;
- 將 Timer0 的“鐘聲”(TINT0 中斷)映射到中斷服務函數?
TIM0_IRQn
?的地址(中斷向量表 INT1)。 - 確保中央政府(CPU)在收到 TINT0 信號時調用正確的響應程序。
- 將 Timer0 的“鐘聲”(TINT0 中斷)映射到中斷服務函數?
初始化 Timer0 寄存器:
CpuTimer0.RegsAddr = &CpuTimer0Regs; CpuTimer0Regs.PRD.all = 0xFFFFFFFF; CpuTimer0Regs.TPR.all = 0; CpuTimer0Regs.TPRH.all = 0; CpuTimer0Regs.TCR.bit.TSS = 1; CpuTimer0Regs.TCR.bit.TRB = 1; CpuTimer0.InterruptCount = 0;
- CpuTimer0.RegsAddr:指定 Timer0 的寄存器地址,綁定管理結構。
- PRD.all = 0xFFFFFFFF:初始化周期藍圖為最大值(32位全1),為后續配置留空間。
- TPR.all = 0, TPRH.all = 0:清零節奏調節站(TDDR 和 PSC),默認不分頻。
- TCR.bit.TSS = 1:停止時鐘塔,確保配置期間不運行。
- TCR.bit.TRB = 1:啟用重載功能。
- InterruptCount = 0:清零中斷計數。
調用 ConfigCpuTimer:
ConfigCpuTimer(&CpuTimer0, Freq, Period);
- 調用?
ConfigCpuTimer
?設置 Timer0 的周期(PRD = Freq × Period)和運行參數(TCR、TPR/TPRH)。 - 示例:Freq=150 MHz,Period=500000 微秒,PRD=75000000,對應 500ms。
- 調用?
啟動時鐘塔并啟用中斷:
CpuTimer0Regs.TCR.bit.TSS = 0; IER |= M_INT1; PieCtrlRegs.PIEIER1.bit.INTx7 = 1; EINT; ERTM;
- TCR.bit.TSS = 0:啟動 Timer0 時鐘塔,開始計數。
- IER |= M_INT1:啟用 CPU 第一組中斷(INT1,包含 TINT0)。
- PieCtrlRegs.PIEIER1.bit.INTx7 = 1:啟用 PIE 第一組第七小中斷(TINT0)。
- EINT:啟用全局中斷。
- ERTM:啟用實時中斷模式,確保中斷處理不被調試暫停。
3. TIM0_IRQn 中斷
interrupt void TIM0_IRQn(void)
{EALLOW;LED2_TOGGLE;PieCtrlRegs.PIEACK.bit.ACK1 = 1;EDIS;
}
TIM0_IRQn
是 Timer0 的中斷服務函數(ISR),相當于時鐘塔敲響“鐘聲”時中央政府的響應程序。它在 Timer0 計數器(TIM)歸零時觸發,負責翻轉 D2 信號燈狀態并清除中斷標志,確保下次“鐘聲”正常觸發。
詳細分析
解除寫保護:
EALLOW;
- 解除寄存器寫保護,允許操作 PIE 寄存器。
翻轉 D2 信號燈:
LED2_TOGGLE;
- 調用宏?
LED2_TOGGLE
,翻轉 D2 信號燈的電平(高變低,低變高)。 - 實現效果:每次中斷觸發,D2 信號燈狀態切換,周期為 500ms(由?
ConfigCpuTimer
?設置),即每 500ms 點亮或熄滅。
- 調用宏?
清除中斷標志:
PieCtrlRegs.PIEACK.bit.ACK1 = 1;
- 清除 PIE 第一組中斷的確認標志(ACK1),通知通信網絡(PIE)已處理本次中斷。
- 若不清除,PIE 將阻止下一次 TINT0 中斷觸發,導致時鐘塔“鐘聲”失效。
恢復寫保護:
EDIS;
- 恢復寄存器寫保護,確保系統安全。
TIM0_IRQn
是 Timer0 中斷的響應核心,簡潔高效地處理 D2 信號燈的閃爍任務,并通過清除標志位保證中斷系統的正常運行。其執行時間需盡量短,以避免影響其他任務。
綜合流程:
初始化(TIM0_Init):
- 打開 Timer0 能源(PCLKCR3),設置中斷地址(TINT0 → TIM0_IRQn)。
- 初始化寄存器(PRD=0xFFFFFFFF,TPR/TPRH=0,TSS=1,TRB=1)。
- 調用?
ConfigCpuTimer
?設置 PRD=75000000(500ms),啟用中斷(TIE=1)。 - 啟動 Timer0(TSS=0),啟用 PIE 中斷(INT1、INTx7)和全局中斷。
運行:
- Timer0 接收 SYSCLKOUT 脈沖(150 MHz),TIM 計數器從 75000000 減到 0。
- 每 500ms(75000001 × 6.67 ns),TIM 歸零,觸發 TINT0 中斷。
中斷處理(TIM0_IRQn):
- 翻轉 D2 信號燈狀態。
- 清除 PIEACK 標志,準備下次中斷。