前面的篇章我们都是在普及知识,真正使用好定时器还是需要重新拟定新的书写方案的,我们参考了宋老师的书写方式,在他的代码基础上我们进行小修改成就实用的工程代码。
1.代码解析
void ConfigTimer0(unsigned int ms) { unsigned long tmp; //临时变量 tmp = 11059200 / 12; //定时器计数频率 tmp = (tmp * ms) / 1000; //计算所需的计数值 tmp = 65536 - tmp; //计算定时器重载值 tmp = tmp + 13; //补偿中断响应延时造成的误差 T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节 T0RL = (unsigned char)tmp; TMOD &= 0xF0; //清零T0的控制位 TMOD |= 0x01; //配置T0为模式1 TH0 = T0RH; //加载T0重载值 TL0 = T0RL; ET0 = 1; //使能T0中断 TR0 = 1; //启动T0 }
我们先一句句分析宋老师为何是这样一步步书写,首先我们知道,定时器的寄存器计数,每加1计数就是经过(12/11059200)秒。那么计数了11059200次就是经过12秒了。经过1秒计数就是(11059200/12)=921600。这样我们就明白了第一条语句的意思。
那么我们想定时1ms,需要的计数就是(921600/1000)=921.6,需要定时xms就是需要计数921.6x。
如果我们想定时5ms,那么需要的计数值就是921.6*5=4608
填充给TH0和TL0的初始值就是
TH0=(65536-4608)/256
TL0=(65536-4608)%256
当然也可以这样表达,两种书写方式的功能作用都一样
TH0= (unsigned char)(65536-4608)>>8;
TL0= (unsigned char)(65536-4608);
T0RH,T0RL是两个全局变量,为的是在中断函数中可以重新赋初值给寄存器TH0和TL0。
由于中断函数的执行有时需要消耗不同的时间,所以定时时间会有误差导致进入中断函数时会产生与设想时的时间不同,所以需要调整计数值,也就是上面代码中的tmp需要微调节成一个合适的数,上面是固定加了13这个数,但是有时需要灵活改变这个微调值,所以我们改为传入不同的参数来改变这个微调值。
2.我们的代码
我们知道宋老师的代码定时的最小单位为1ms,下一章由于我们要学舵机,需要定时的最小单位是0.1ms,所以我们的代码定时的最小单位必须是0.1ms,也就是100us。看到我们的代码
void TIM0_Init(u32 us,int trim)//trim:微调 { u32 tmp; //临时变量 tmp = 11059200 / 12; //定时器计数频率 tmp = ( tmp * (us/100) )/10000; //计算所需的计数值 tmp = 65536 - tmp; //计算定时器重载值 tmp = tmp+trim; //微调计数值使其定时更精确到我们想要的定时时间 T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节 T0RL = (unsigned char)tmp; TMOD &= 0xF0; //清0低四位 TMOD |= 0x01; //设置定时器0为工作模式1 TH0 = T0RH; //加载T0重载值 TL0 = T0RL; ET0 = 1; //闭合定时器0中断的开关 TR0 = 1; //启动定时器0 }
要想定时2ms,传入的参数就是2000,我们的参数是us数,如果传入的是2000,第二条语句就是“(tmp*2)/1000”,与宋老师的代码原理一样。不过需要记住的是我们不能定时小于100us的时间,最低单位只能是100us。
下一讲我们讲解学会如何微调定时时间。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程