🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
* 导师视频讲解:[**去听课**](https://www.bilibili.com/video/BV1k34y1D7Vz?p=12) >[success] **技术支持说明:** >**1**.一般以自主学习为主 > **2**.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/zigbee) > **3**.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解! <br/> 本节将使用CC2530内部的定时器1对LED等进行定时的开关控制,从而实现闪烁LED的效果。 <br/> ## **定时器基础理论** * **系统时钟频率**:时钟发生器会以恒定的时间间隔产生脉冲,这个间歇性的脉冲可以形象理解为芯片的心跳,时钟频率则是用来描述这个心跳的速率。大家通常用1s内时钟发生器产生的脉冲数量来描述时钟频率,例如“时钟频率10 MHz”表示1s内的心跳次数为10 000 000次。CC2530有两种时钟频率可供开发者使用:32MHz和16MHz。 ### * **分频系数**:分频是指将时钟频率降低为原来的1/N,也称为N分频。比如当时钟频率是16MHz的时候,那么2分频是8MHz。分频系数则是用1/N来表示,比如2分频的分频系数为:1/2。 ### * **系统时钟周期**:周期和频率的关系可以用公式表示: T = 1 / f,其中T为时钟周期,f为时钟频率。时钟周期和时钟频率成倒数关系。举个例子说明一下,时钟频率为16MHz时表示在1s内时钟发生器可以产生16 000 000个脉冲,而时钟周期则可以表示产生一个脉冲所需要的时间,即1 / 160 000 00s。 ### * **计数器**:计数器是定时器的核心,用于记录时钟发生器产生的脉冲数量。由于脉冲的时钟周期是恒定的,因此计算定时时间的公式是:t=nT,其中t为定时时间,n为计数次数,T为时钟周期 ### * **溢出**:由于计数器的范围是有限的,当计数次数超过最大值时就会产生溢出。例如当计数器的大小是16位时,那么计数范围是0~65535,因此计数次数超过65535后计数器就会产生溢出。在产生溢出后,计算器的值会从最大值变为0。 <br/> ## **定时原理** 我们利用公式对频率和周期的关系作进一步的解释。 我们利用f表示时钟频率,T来表示时钟周期,那么可以用此关系式来表示它们的关系: * T = 1 / f (1) 我们计时t秒后,假设此时计数器从0开始计数了N次(假设此时计数器没有溢出)。前面已经讲解过,时钟周期T表示心跳1次所需要时间,因此t与N的关系如下: * t = N × T (2) 接着,我们可以推导出: * N = t / T (3) <br/> CC2530的默认系统时钟频率是16MHz(16000000Hz),其定时器1使用128分频,因此定时器的时钟频率是 16000000 / 128 Hz。 ### * 根据公式(1)T = 1 / f 可以算出定时器1时钟周期为T = 128/16000000 秒。 * 在定时5秒的情况下(即t=5秒),根据公式(2)N = t / T,计数器的计数值N = 5 / (128/16000000) = 625000。 ### ### **处理溢出** &emsp;&emsp;当定时器溢出时会发生中断,此时寄存器IRCON的Bit1位会由原先的0被设置为1,因此我们只需要检测这个标志位即可判断是否发生了溢出。 >[info] 具体的相关寄存器说明,请阅读下文的说明 &emsp;&emsp;定时器1是一个16位定时器,每溢出一次计数65536次,所以定时5秒后将会溢出: 625000 / 65536 = 9.54,取整数,即9次。反过来,如果溢出了9次,我们可以大约第认为时间过了5秒。 <br/> ## **相关寄存器** ![](https://img.kancloud.cn/86/5d/865d48b7de54066667b3ab2ee7c81044_886x830.png =600x) ![](https://img.kancloud.cn/9b/af/9baf0b9af0615ed85ac7a270b4b92978_878x708.png =600x) <br/> ## **寄存器配置** * 定时器1是一个16位的定时器,也就是说计数器能从0~65535进行计数。 * 定时器1支持5个通道 ``` 1.T1CTL = 0x0D; // 0000 1101:128分频,自由计数(从0~65535)   2.T1STAT= 0x21; // bit0写1,清空通道0中断状态位   3. // bit5写1,清空计数器中断状态位 ``` <br/> ## **程序说明** 主函数: ``` void main() { uint8_t Counter = 0; initLed(); initTimer1(); while(1) { if (!(IRCON & 0x02)) continue; // Timer1 interrupt not pending IRCON &= ~(0x02); // Clear timer1 interrupt flag if (++Counter < 9) continue; // ~5 second else Counter = 0; DEBUG_LOG("~5 Second.\r\n"); LED = (LED == LED_ON)?LED_OFF : LED_ON; } /* while */ } ``` ### &emsp;&emsp;主函数定义了一个计数器,用来记录定时器溢出的次数。前面我们已经算出了定时5秒后会溢出9次。每当定时器溢出后都需要清除溢出标志位。溢出9次后我们需要把计数器归0,重新计数。这样,我们就实现了每隔5秒中打印输出相应提示,并翻转LED灯的亮灭状态。 <br/> ## **仿真调试** >[danger] 在学习本节课前,需要先掌握基本的程序下载及仿真操作,参考:[程序下载及仿真](2482302) 把开发板连接仿真器,进入仿真模式: ![](https://img.kancloud.cn/1d/15/1d1558cd149452fda895264e0a215aac_354x384.png =300x) ### 可以看到,每隔大概5秒打印出信息,并且LED灯翻转。 <br/> <br/> ## **项目定制** * 如需项目定制开发,可扫码添加项目经理好友(注明“**项目定制**”) * 定制范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等IoT技术方案 * 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/) ![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =200x) * 非项目定制**勿扰**,此处**非**技术支持