在讲定时器之前,我们先提一下晶振的概念:单片机想要正常运行,需要有一个频率,而晶振就是给单片机提供一个时钟频率的器件,时钟频率越快,运行的速度就越快;
cc2530有一个32MHZ的外部晶振,在默认情况下,外部晶振到单片机分频模块就自动2分频,即为16MHZ;16MHZ的含义是每秒产生16M次脉冲,对定时器来说,高电平到低电平就计数一次,当定时器的存储空间计满后就产生中断,将中断标志位(IRCON) 置1,;我们可以通过查询IRCON的方式判断存储空间是否计满,也可以通过执行中断服务函数来实现程序效果;
对于CC2530来说,有高速模块和低速模块,而低速模块可能只需要1MHZ就可以正常工作,这时我们的分频模块就会对频率源进行分频操作,将分频后的频率给模块;
定时器中断的配置方法:
- 设置定时器分频方式
- 设置定时器技术方式
- 开启溢出中断
- 开启总中断
- 开启定时器中断使能
- 启动定时器
下面我们通过程序先来看一下怎样通过查询的方式进行处理:
#include <ioCC2530.h>
//端口定义
#define led P1_0
/********************************************************
* function name : LedInit
* function : 配置led相关寄存器并设置led初始状态
* prarmeter : 无
* returned value: 无
********************************************************/
void LedInit(void)
{
P1DIR |= 0X01; //P1_0设置为输出模式
P1SEL &= ~0X01; //P1_0设置为通用IO
led = 1; //初始状态为熄灭
}
/*******************************************************
* function name : Timer1Init
* function : 配置timer1相关寄存器
* prarmeter : 无
* returned value: 无
*******************************************************/
void Timer1Init(void)
{
T1CTL = 0X0D; //设置定时器1为128分频,计数模式为0X0000~0xFFFF反复计数
T1STAT= 0X21; //设置通道0,中断有效
}
/***********************************************
* function name : main
* function : 初始化LED和TIMER,实现LED每一秒改变一次状态
* prarmeter : 无
* returned value: 无
************************************************/
void main(void)
{
LedInit();
Timer1Init();
int i = 0;
while(1)
{
//查询方式
if(IRCON > 0)
{
IRCON=0; //清除中断标志位
if(++i > 1)
{
led = ~led;
i = 0;
}
}
}
}
上图是定时器1的相关寄存器参数配置图,通过程序和数据手册我们可以知道,在此程序中定时器1设置的是128分频,采用从0X0000~0XFFFF的计数模式;由128分频我们可得(16MHZ / 128=131072)每秒产生131072次脉冲,即每秒计数131072次;由从0X0000~0XFFFF的计数模式我们可知,要想产生中断需要计数65535次,两者结合看,我们可以得出,我们一秒可以产生两次中断;
下面我们看看通过中断的方式我们要怎样处理:
#include <ioCC2530.h>
//端口定义
#define led P1_0
/********************************************************
* function name : LedInit
* function : 配置led相关寄存器并设置led初始状态
* prarmeter : 无
* returned value: 无
********************************************************/
void LedInit(void)
{
P1DIR |= 0x01; //P1_0设置为输出模式
P1SEL &= ~0x01; //P1_0设置为通用IO
led = 1; //初始状态为熄灭
}
/*******************************************************
* function name : TimerInit
* function : 配置timer3相关寄存器,实现更改led状态的效果
* prarmeter : n_ms 用于设置延时的时间,单位为毫秒
* returned value: 无
*******************************************************/
unsigned int ms_count = 0; //计数累加
unsigned int ms_value = 0; //用于存储延时的时间
void Timer3Init(unsigned int n_ms)
{
ms_value = n_ms;
T3CTL |= 0xC0; //设置定时器为64分频
T3CTL &= ~0x03; //设置计数模式为 0X0000~0XFFFF
T3CTL |= 0x08 ; //开启溢出中断
EA = 1; //开启总中断
T3IE = 1; //IEN1的第三位,置1开启定时器3中断使能
T3CTL |= 0x10; //启动定时器
}
//中断服务函数,实现效果
#pragma vector = T3_VECTOR
__interrupt void T3_ISR(void)
{
ms_count++; //开始计数
if(ms_count >= ms_value) //如果超过所设置的时间则实现效果
{
ms_count = 0; //计数清零
led = ~led; //更改led状态
}
}
/***********************************************
* function name : main
* function : 初始化LED和TIMER,实现LED每一秒改变一次状态
* prarmeter : 无
* returned value: 无
************************************************/
void main(void)
{
LedInit();
Timer3Init(1000);
while(1)
{
}
}
相信看完程序你们心里有个疑问,你怎么就知道这样就是延时了1秒呢?这中间又有什么不为人知的秘密嘛?我们来分析一下:
我们之前设置的定时器分频模式是64分频,前面我们也讲了,CC2530外接的是32MHZ的晶振,到单片机内部自动2分频,再64分频后每秒可以产生262144次脉冲,即计时器每秒可以计数262144次,每毫秒可以计数262次;通过0X0000~0XFFFF的计数模式我们可以得出,每秒我们可以将计数空间计满256次;这里我们可以看见262是近似于256的,在毫秒级别,这点误差我们基本可以忽略不计,所以延时效果就是这么来的;