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;
}

编译与运行

  1. 在CCES中新建SHARC工程,将上述代码保存为timer_led.c并添加到工程。
  2. 根据实际处理器型号调整def21369.h头文件(若使用其他SHARC型号,替换为对应头文件)。
  3. 确认CCLK频率为400MHz。若不同,按公式重新计算TIMER0_PERIOD和TIMER0_PULSE:
    周期值 = (CCLK/4) × 0.5秒,脉宽值 = 周期值/2。
  4. 编译工程,通过仿真器下载到目标板。
  5. 运行程序,观察LED0闪烁。

验证方法

  • 目视检查:LED0应以约1Hz频率闪烁(亮约0.5秒,灭约0.5秒),周期稳定无漂移。
  • 示波器测量:将示波器探头连接至PA0引脚,测量波形周期应为1.000s±5%,高电平宽度约500ms。
  • 中断频率验证:在Timer0_ISR中设置断点,观察每秒应触发约2次中断。

常见问题

  • LED不闪烁:检查GPIO方向寄存器配置是否正确,确认PA0对应板上LED实际连接引脚。
  • 闪烁频率偏差大:确认CCLK实际频率与计算值一致;检查定时器时钟分频配置。
  • 中断不触发:确认register_handler参数正确,且全局中断已使能(IRPTEN置位)。