什么是定时器/计数器? --- 既可以定时,也能计数的一种单片机内部资源,主要用于软件计时和软件延时等场合。但同一时刻只能使用其中一种功能。
定时器的核心功能简单一句话说就是“启动定时器后,每个机器周期到来,初值寄存器自动加1,直到计满溢出”。
定时器的工作流程:
那么如果要定时50ms,该如何实现呢?
首先要进行初值计算:
定时时长:65536us,计算机周期个数:65536个;
定时时长:50000us,计算机周期个数:50000个;
计算方法为:初值X=65536-50000=15536;
15536换算为16进制为3Cb0H;
即初值为:TH0=0x3c; TL0=0xb0;
TH0存放的是256取整;TL0存放的是小于256的余数;
所以可以写成:TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
以上就解决了初值计算的问题,假设需要定时大于65536的时间,比如1秒,则需要再程序内部加循环,1s=50ms×20次;或者10ms×100次;
定时器的编程实现步骤:
1.报备---2.置初值---3.启动---4.等待---5.重置初值---6.清溢出
1.报备
TMOD (89H) |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
工作模式寄存器 |
GATE |
C/T |
M1 |
M0 |
GATE |
C/T |
M1 |
M0 |
T1字段 |
T0字段 |
GATE:门控位,为0时,将TR0=1,则启动定时器。 为1时,TR0=1还需要加上外部中断引脚INT0共同启动。
C/T:0定时;1计数;
M1/M0(工作方式):00:方式0; 01:方式1; 10:方式2; 11:方式3; 最后得到TMOD的值:0000 0001;0x01;
2.置初值
50ms为例: TH0=0x3c; TL0=0xb0;
3.启动
TR0=1; 启动
TR0=0; 停止
TCON(88H) |
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
4.等待
TF0溢出位,溢出自动置1;
为了保证下一次溢出时能够正常置1;需要将TF0手动清0;TF0=0;
while(TF0==0); 查询TF0是否为1,来判断溢出;为1就是时间到了,溢出了;
5.重置初值
如果定时1s就需要50ms×20次,在溢出后要重置初值并循环20次
6.清溢出
溢出后TF0=1;为了保证下次溢出正常计数,需要手动置0:TF0=0;
中断的基本知识
中断源 |
中断允许标志位 |
中断请求形式 |
中断请求标志位 |
中断号 |
外部中断INT0 |
EX0 |
低电平 |
IE0 |
0 |
定时器T0 |
ET0 |
溢出 |
TF0 |
1 |
外部中断INT1 |
EX1 |
低电平 |
IE1 |
2 |
定时器T1 |
ET1 |
溢出 |
TF1 |
3 |
串口 |
ES |
接收或发送结束 |
TX/RX |
4 |
IE寄存器 中断允许寄存器 |
|||||||
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
EA |
X |
X |
ES |
ET1 |
EX1 |
ET0 |
EX0 |
EA:总中断允许标志位
中断流程:
中断源---中断允许---中断请求---中断响应---断点---中断号---中断返回
中断服务程序示例:
timer0:函数名字可以随便取; interrupt:中断关键字; 1:中断号;
void timer0 () interrupt 1
{
}
中断演示--定时50ms,循环2次,即100ms,LED灯循环左移一次
代码分为两部分:1.主函数部分;2.中断服务程序部分
uchar k = 0; //由于K将要在中断服务函数中调用,所以K需要定义为全局变量
void main()
{
uchar n = 0; i = 0;
TMOD=0x01; //工作模式
TH0=(65536-50000)/256; //定时器置初值
TL0=(65536-50000)%256; //定时器置初值
EA=1; //中断总开关
ET0=1; //中断允许标志位
TR0=1; //启动计时器
while(1)
{
n=0x01;
for(i=0;i<8;i++) //循环8次
{
P0=~n; //进入第一次循环,并点亮第一颗灯
while(k<2); //等待,等待时间到来,然后进入中断
k=0; //中断服务程序中的内容执行完以后,K置0重新计数;
n=n<<1; //LED灯左移一位
}
}
}
中断服务程序
//定时器T0中断服务程序
void timer0 () interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
K++;
}