一、定时器原理
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 标志,准备下次中断。