Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说51单片机的定时器/计数器及编程「终于解决」,希望能够帮助你!!!。
本文简单阐述了怎么使用51的定时器/计数器。
如果不在意细节,可以直接看“五、应用实例”。
定时器/计数器实质是加1计数器,该计数器由两个寄存器存储着计数的值(每一个有8位),将其称之为高8位、低8位寄存器;意即高8位、低8位的数值总和即为计数总和。
当高8位、低8位寄存器全满时(即16位全为1,等同于216),若再计数一次,定时器/计数器会产生一次“溢出”,将高8位、低8位寄存器清0,并向单片机发生中断请求。所以只要设定了寄存器的初值,就可以控制啥时候溢出了。
然而,什么时候计数一次呢?脉冲下降沿。而脉冲有两个来源:一是系统的时钟振荡器,二是T0或T1引脚输入的外部脉冲源。一般情况下,使用系统的时钟源即可满足需求。
1.控制寄存器TCON
| 位: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| 字节地址:88H | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
各标志位功能如下:(仅讲4位与定时器有关的)
2.工作方式寄存器TMOD
| 位: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| 字节地址:89H | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
各标志位功能如下:(低4位控制T0,高4位控制T1;此处仅以高4位为例)
3.加1计数器的寄存器THx和TLx
由于常使用工作方式1,所以下面以T0为例,展示在工作方式1的情况下如何设定初值。
计数器模式:
设初值为X、计算次数为M,则
X = 65536 − M X=65536-M X=65536−M
定时器模式:
设初值为X、定时为t微秒,时钟频率为f MHz、时钟周期为T微秒(12分频后,T=12/f),则
X = 65536 − t / T = 65536 − t ∗ f / 12 X=65536-t/T=65536-t*f/12 X=65536−t/T=65536−t∗f/12
//提示:2的8次方等于256
TH0=X/256;
TL0=X%256;
//使用T1
TMOD=0x10; //GATE=0,C/T=0,工作方式为1
//想要计数50000次,则设定初值为15536
TH1=15536/256;
TL1=15536%256;
EA=1; //总中断
EX0=1; //开定时器中断
TR1=1; //使能定时器
void time() interrupt 1 //1是定时器T0中断序号
{
write something
}
利用中断、定时器,实现精准延时1s和延时t s,让LED每2s取反一次:
/*功能:通过中断延时,令LED1的闪烁间隔为2s。(使用T0)*/
#include <reg52.h>
#define uint unsigned int
sbit led1=P1^0;
uint num=0;
/**函数功能:精准延时1s**/
void delay_1s(){
while(num<=20);
num=0;
}
/**函数功能:精准延时。单位:s**/
void delay(uint t){
while(num<=20*t);
num=0;
}
/**函数功能:初始化T0**/
void init_T0(){
TMOD=0x01; //受TR0控制、定时器、方式1
//想要计数50000次,则设定初值为19456(f=11.059)
TH0=19456/256;
TL0=19456%256;
}
void main()
{
init_T0();
led1=0;
EA=1; //开总中断
ET0=1; //开定时器中断
TR0=1; //使能定时器
while(1){
delay(1);
delay_1s();
led1=~led1;
}
}
void time() interrupt 1 //T0中断序号为1
{
num++;
}
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章