4. 定时器中断与精确定时
任务目标
在ADI SHARC处理器上配置定时器,产生周期性中断,并在中断服务程序中翻转LED状态,实现1Hz精确闪烁(亮500ms、灭500ms)。通过示波器测量或观察LED实际闪烁周期验证定时精度。
硬件与依赖
- ADI SHARC评估板(如ADSP-SC589 EZ-BOARD)
- 板上LED连接至GPIO(本例使用PA0,对应LED0)
- CrossCore Embedded Studio (CCES) 开发环境
- VDSP++ 或 CCES 自带SHARC芯片支持包
实现原理
SHARC处理器内置定时器(Timer0)工作在PWM模式,通过设置周期寄存器和脉宽寄存器产生固定频率中断。定时器时钟源为内核时钟(CCLK)的分频值。本例配置定时器产生2Hz中断频率(周期500ms),每次中断翻转LED状态,从而得到1Hz闪烁效果。
关键完整代码
/* timer_led.c - SHARC定时器中断实现1Hz LED闪烁 */
#include <def21369.h> /* 处理器寄存器定义 */
#include <intrinsic.h>
/* 中断服务函数声明 */
EX_INTERRUPT_HANDLER(Timer0_ISR);
/* 全局LED状态 */
volatile int led_state = 0;
/* 定时器周期值计算:
CCLK = 400MHz, TMR0_CLK = CCLK/4 = 100MHz
周期 = 100MHz × 0.5s = 50,000,000 = 0x2FAF080
脉宽 = 周期/2 = 25,000,000 = 0x17D7840 */
#define TIMER0_PERIOD 0x2FAF080uL
#define TIMER0_PULSE 0x17D7840uL
/* LED控制宏 - 使用PA0 */
#define LED_ON() (*pREG_GPIOA_SET = 0x0001)
#define LED_OFF() (*pREG_GPIOA_CLR = 0x0001)
/* 定时器0中断服务程序 */
EX_INTERRUPT_HANDLER(Timer0_ISR)
{
/* 清除中断标志 */
*pREG_TMR0_STAT = 0x2;
/* 翻转LED状态 */
if (led_state) {
LED_OFF();
led_state = 0;
} else {
LED_ON();
led_state = 1;
}
}
/* 主函数 */
int main(void)
{
/* 配置GPIO PA0为输出 */
*pREG_GPIOA_DIR = 0x0001; /* PA0设为输出 */
*pREG_GPIOA_IE = 0x0000; /* 禁止输入使能 */
/* 初始关闭LED */
LED_OFF();
/* 配置定时器0 */
*pREG_TMR0_CFG = 0x00000000; /* 停止定时器并复位 */
*pREG_TMR0_PER = TIMER0_PERIOD; /* 设置周期 */
*pREG_TMR0_PW = TIMER0_PULSE; /* 设置脉宽 */
/* 注册中断服务程序 */
register_handler(IN_TIMER0, Timer0_ISR);
/* 使能定时器0中断 */
*pREG_TMR0_CFG = 0x00000007; /* 使能定时器,PWM模式,中断使能 */
/* 全局中断使能 */
asm("bit set MODE1 IRPTEN;");
/* 主循环 - 空操作,等待中断 */
while (1) {
/* 可在此添加低优先级任务 */
}
return 0;
}
编译与运行
- 在CCES中新建SHARC工程,将上述代码保存为
timer_led.c并添加到工程。 - 根据实际处理器型号调整
def21369.h头文件(若使用其他SHARC型号,替换为对应头文件)。 - 确认CCLK频率为400MHz。若不同,按公式重新计算
TIMER0_PERIOD和TIMER0_PULSE:
周期值 = (CCLK/4) × 0.5秒,脉宽值 = 周期值/2。 - 编译工程,通过仿真器下载到目标板。
- 运行程序,观察LED0闪烁。
验证方法
- 目视检查:LED0应以约1Hz频率闪烁(亮约0.5秒,灭约0.5秒),周期稳定无漂移。
- 示波器测量:将示波器探头连接至PA0引脚,测量波形周期应为1.000s±5%,高电平宽度约500ms。
- 中断频率验证:在
Timer0_ISR中设置断点,观察每秒应触发约2次中断。
常见问题
- LED不闪烁:检查GPIO方向寄存器配置是否正确,确认PA0对应板上LED实际连接引脚。
- 闪烁频率偏差大:确认CCLK实际频率与计算值一致;检查定时器时钟分频配置。
- 中断不触发:确认
register_handler参数正确,且全局中断已使能(IRPTEN置位)。