4. 定时器0定时中断

任务说明

本案例使用CC2530的定时器0(Timer 0)产生周期性定时中断,在中断服务函数中翻转LED1(P1_0)状态,实现LED以固定频率闪烁。通过该案例掌握定时器0的寄存器配置、中断使能及中断服务函数的编写方法。

硬件连接

LED1阳极通过限流电阻接至CC2530的P1_0引脚,阴极接地。当P1_0输出高电平时LED点亮,输出低电平时熄灭。

定时器0工作原理

CC2530定时器0为16位定时器,支持自由运行、模模式、正计数/倒计数三种工作模式。本案例使用模模式(Mode=1),定时器从0x0000计数至T1CC0设定的值后溢出并产生中断,同时计数器清零重新开始计数,从而实现周期性中断。

代码实现


#include <ioCC2530.h>

#define LED1 P1_0

/* 时钟频率32MHz,定时器分频128,定时周期0.5s */
/* 计数时钟 = 32MHz / 128 = 250kHz,周期4us */
/* 计数值 = 0.5s / 4us = 125000 = 0x1E848,超出16位范围 */
/* 改用分频8:计数时钟=4MHz,周期0.25us */
/* 计数值 = 0.5s / 0.25us = 2000000,仍超出16位范围 */
/* 采用分频1:计数时钟=32MHz,周期31.25ns */
/* 计数值 = 0.5s / 31.25ns = 16000000,超出16位 */
/* 因此采用定时器溢出+软件计数方式: */
/* 定时器0每1ms中断一次,软件累计500次后翻转LED */

volatile unsigned int timer0_count = 0;

void delay(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 535; j++);
}

void init_timer0(void)
{
    /* 使用系统时钟32MHz,不分频 */
    CLKCONCMD &= ~0x40;   /* 选择32MHz晶振 */
    while (CLKCONSTA & 0x40);
    
    T1CTL = 0x0A;         /* 模模式,分频1,32MHz计数 */
    T1CC0 = 31999;        /* 计数值:1ms = 32000个时钟周期 */
    T1CCTL0 = 0x04;       /* 通道0比较匹配中断使能 */
    
    T1IE = 1;             /* 定时器1中断总使能(T1对应Timer1) */
    /* 注意:CC2530的Timer0对应中断使能位为T1IE */
    EA = 1;               /* 全局中断使能 */
}

#pragma vector = T1_VECTOR
__interrupt void timer1_isr(void)
{
    if (T1STAT & 0x01)    /* 通道0比较标志 */
    {
        T1STAT &= ~0x01;  /* 清除中断标志 */
        timer0_count++;
        if (timer0_count >= 500)  /* 累计500ms */
        {
            timer0_count = 0;
            LED1 = ~LED1;         /* 翻转LED */
        }
    }
}

void main(void)
{
    P1SEL &= ~0x01;       /* P1_0设为普通IO */
    P1DIR |= 0x01;        /* P1_0设为输出 */
    LED1 = 0;             /* 初始熄灭 */
    
    init_timer0();
    
    while (1)
    {
        /* 主循环空操作,等待中断 */
    }
}

代码说明

CC2530的定时器0在头文件中对应中断向量为T1_VECTOR,中断使能位为T1IE。定时器配置为模模式,T1CC0设为31999,计数时钟为32MHz,因此每32000个时钟周期(1ms)产生一次比较匹配中断。在中断服务函数中,软件计数器timer0_count累加,每累计500次(即500ms)翻转一次LED1,实现周期为1s的闪烁效果(亮0.5s,灭0.5s)。

SVG:定时器中断时序与寄存器配置

定时器0模模式中断时序图 计数值 0x7CFF 0x7CFF 0x7CFF 0x7CFF 0ms 1ms 2ms 3ms 4ms 中断标志 T1STAT.0 置1 清0 置1 清0 LED1 低电平(灭) 高电平(亮) 灭 软件计数 timer0_count: 0→1→2→...→499→0 关键寄存器配置: T1CTL = 0x0A(模模式,分频1) | T1CC0 = 31999(1ms周期) | T1CCTL0 = 0x04(比较中断使能) T1IE = 1(定时器中断使能) | EA = 1(全局中断) | 中断向量:T1_VECTOR

编译与下载

使用IAR Embedded Workbench for 8051创建工程,将上述代码保存为main.c并加入工程。工程选项需设置芯片型号为CC2530,编译器优化级别建议设为Low或None以保证中断时序正确。编译通过后,通过CC Debugger下载至目标板。

验证方法

下载程序后,观察LED1是否以约1秒周期闪烁(亮0.5秒,灭0.5秒)。若LED不闪烁,检查以下要点:

  • P1_0是否被其他外设功能占用(P1SEL需清零)
  • 定时器中断标志是否在中断服务函数中正确清除
  • 系统时钟是否已切换至32MHz晶振

判定标准:LED1持续以固定周期闪烁,周期误差在允许范围内(晶振精度决定),即表示定时器0定时中断功能实现正确。