一.前言
本文基于【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?p=17&vd_source=e0a0e92e7fbcb4d0ff760d75fb57a403,是对于整个视频的个人性总结。
二.定时器框架
定时器主要分为三个大板块:
①时钟:将晶振频率转化为稳定的电脉冲,提供计数单位的时钟脉冲。
②计数单元:控制定时器开关,当时钟计数值溢出,溢出位TF0为1,申请中断。
③中断系统:CPU从当前程序跳转至中断,根据中断源的轻重缓急优先级执行下一步。
三.四种工作模式
定时器工作原理及其应用,跳转至http://t.csdnimg.cn/uzQvl
-
模式1:13位向上计数定时器;
-
模式2:16位向上计数定时器;
-
模式3:8位向上计数寄存器,并指定重装值;
-
模式4:独立的2个8位向上计数定时器。
我们一般平常用的是模式2,所以重点讲模式2(如下图)。
四.模式2
THx和TLx是Tx的两个寄存器,用来存放计数单元数值。而模式2是16位向上计数定时器,说明左右THx,TLx各8位(一位就是一个二进制),那么这两个寄存器就可以存放,即65536个计数单元数值。
打个比方,把定时器比作沙漏,那么计数单元数值就是一粒沙子(一般为1us,一个机器周期)。那么这一个沙漏就可以放65536粒沙子,每隔1us就落下一粒沙子。等到65536粒沙子都落下,那么时间就到了,标志位溢出,跳入中断。
五.配置
tips:下文文字颜色配合上图框框颜色
1.SYSclk(系统时钟)输出稳定的电脉冲,而框1表示分频(一种是12分频,一种是6分频)晶振频率为12MHZ,12分频则为1MHZ(1us),相当于一个机器周期。
关于机器周期,跳转至时钟周期/机器周期/指令周期/12M晶振和1us有啥关系-电子发烧友网 (elecfans.com)
系统时钟SYSCLK详解,跳转至http://t.csdnimg.cn/vwKZJ
2.框2就用到了TMOD定时器模式寄存器中的C/T,它的功能是用来决定T0是当定时器还是当计数器。如果C/T=0,则系统时钟为输出端,T0为定时器;若C/T=1,则T0 Pin为输出端,接收外部电脉冲,T0为计数器。(一般平常用的是定时器模式)
1.GATE决定T0的启动是由TR0直接控制还是由TR0和INT0一起控制。框1是非门。
逻辑门图解—非门,或门,与门http://t.csdnimg.cn/gANkc
2.INT0是外部引脚。框2是或门
3.TR0是根据GATE配置的,若GATE为0,则TR0为1时,T0开始计数;若GATE为1,TR0为0,则INTO输入高电平时,T0开始计数。框3为与门。
1.TF0为T0溢出中断标志,程序自动查询。TH0为高八位,TL0为低八位,用来存储计数单元。
【【51单片机入门教程】51单片机定时器工作原理及流水灯的实现,溢出、初值计算】https://www.bilibili.com/video/BV1k84y1v7q9?vd_source=e0a0e92e7fbcb4d0ff760d75fb57a403
1.m1,m0决定定时器的工作模式。
六.定时器和中断系统(部分)
1.EA总中断开关决定整个中断系统的开关,ET0溢出中断允许位决定T0中断系统的开关。
2.由PT0,PT0H共同完成对中端优先级的设置。
七.代码
51单片机-定时器,跳转至这是普中51单片机开发板,也可以相互对比着看
/*蓝桥杯代码 AUXR*/
void vTimer2_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0x18; //设置定时初值
T2H = 0xFC; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //开定时器2中断
EA = 1; //开启总中断
}
void main(void)
{
vTimer2_Init();
while(1)
{
}
}
//中断服务程序
void vTimer2_ISR() interrupt 12 //中断入口
{
/* 写法1: 根据时间段*/
// cnt_buzzer++;
// if(cnt_buzzer<=200) // 0 ~ 200ms的时候响 , 每1ms都会执行if里面的函数
// {
// buzzer_ctrl.b.b6 = 1;
// vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
// }
// else if(cnt_buzzer<=400) // 200 ~ 400ms的时候不响
// {
// buzzer_ctrl.b.b6 = 0;
// vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
// }
// else // 超过400ms,需要清0,重新从0计数
// cnt_buzzer=0;
/* 写法2: 根据时间点*/
cnt_buzzer++;
if(cnt_buzzer==200) // 200ms执行一次这个函数
{
cnt_buzzer=0;
buzzer_ctrl.b.b6 = ~buzzer_ctrl.b.b6; // "~"是按位取反,“!”是取非
vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
}
}
关于AUXR辅助寄存器,跳至【LQB单片机】https://www.bilibili.com/video/BV1ig411i73n?p=37&vd_source=e0a0e92e7fbcb4d0ff760d75fb57a403