4. 定时器定时翻转LED
任务说明
本案例基于中微CMS32系列车规MCU,使用定时器(以TIM0为例)产生周期性中断,在中断服务函数中翻转LED引脚电平,实现精确的定时翻转效果。通过本案例,掌握定时器初始化、中断配置及中断服务函数的编写方法。
硬件连接
LED阳极通过限流电阻(约330Ω)连接至PB0引脚,阴极接地。当PB0输出高电平时LED点亮,输出低电平时熄灭。
代码实现
#include "CMS32L051.h"
/* 定时器中断周期:100ms(系统时钟24MHz,预分频24000,计数100) */
#define TIMER_PRESCALER 24000
#define TIMER_PERIOD 100
volatile uint32_t led_toggle_count = 0;
/* TIM0中断服务函数 */
void TIM0_IRQHandler(void)
{
if (TIM0->INTF & TIM_INTF_C0IF) {
TIM0->INTF &= ~TIM_INTF_C0IF; /* 清除中断标志 */
led_toggle_count++;
if (led_toggle_count >= 5) { /* 每5次中断翻转一次,即500ms翻转 */
led_toggle_count = 0;
GPIO->PBOD ^= (1 << 0); /* 翻转PB0 */
}
}
}
void TIM0_Init(void)
{
/* 使能TIM0时钟 */
SYS->CLKEN |= SYS_CLKEN_TIM0;
/* 复位TIM0 */
SYS->RSTEN |= SYS_RSTEN_TIM0;
SYS->RSTEN &= ~SYS_RSTEN_TIM0;
/* 配置TIM0为定时器模式,向上计数 */
TIM0->CR0 = 0x0000; /* 停止计数,边沿计数模式 */
TIM0->CR1 = 0x0000; /* 定时器模式,向上计数 */
/* 设置预分频值 */
TIM0->PR = TIMER_PRESCALER - 1;
/* 设置比较值 */
TIM0->C0 = TIMER_PERIOD - 1;
/* 使能比较匹配中断 */
TIM0->INTE |= TIM_INTE_C0IE;
/* 配置NVIC */
NVIC_EnableIRQ(TIM0_IRQn);
NVIC_SetPriority(TIM0_IRQn, 2);
}
void GPIO_Init(void)
{
/* 使能GPIO时钟 */
SYS->CLKEN |= SYS_CLKEN_GPIO;
/* 配置PB0为推挽输出 */
GPIO->PB0CR = 0x01; /* 输出模式 */
GPIO->PBOD &= ~(1 << 0); /* 初始输出低电平 */
}
int main(void)
{
GPIO_Init();
TIM0_Init();
/* 启动TIM0 */
TIM0->CR0 |= 0x0001; /* 启动计数 */
while (1) {
/* 主循环空操作,LED翻转由中断完成 */
__NOP();
}
}
定时器工作原理
TIM0配置为定时器模式,系统时钟24MHz经预分频器24000分频后得到1kHz计数时钟。计数器从0向上计数至比较值100时产生中断请求,即每100ms触发一次中断。中断服务函数中每累计5次中断(500ms)翻转一次PB0引脚电平,实现LED以1Hz频率闪烁。
SVG时序图
编译与烧录
使用中微官方CMS32L051芯片支持包创建工程,将上述代码保存为main.c并加入工程。编译配置选择芯片型号CMS32L051,优化级别建议O0便于调试。编译成功后通过CMS-ICE仿真器连接目标板,使用官方烧录工具下载hex文件至芯片。
验证方法
将程序烧录至开发板后,观察PB0引脚连接的LED状态。预期现象:LED以约1Hz频率(每500ms翻转一次)持续闪烁。使用示波器测量PB0引脚波形,可观察到周期约为1s的方波信号,高电平持续500ms,低电平持续500ms。若LED不闪烁或闪烁频率异常,检查晶振频率配置、预分频值及比较值是否与系统时钟匹配。