前言
在实时控制系统中,经常需要定时时钟以实现精准延时、定时,也经常需要计数功能以实现对外界脉冲进行计数, 本节,我们开始学习51单片机的定时器,然后开启一个定时器,实现1S翻转一次电平,控制LED灯亮灭。
一、基础知识
1.定时器简介
51单片机的定时器有两个,分别是T0和T1,它们可以用于定时或者对外部脉冲(事件)计数,还可以作为串行口的波特率发生器使用,定时器裸机结构图如下所示
定时器工作在定时方式时候,计数器对内部时钟机器周期数进行计数,每个机器周期等于12个晶体震荡周期,定时器工作在计数方式时候,计数脉冲来自外部输入引脚P3.4、P3.5,当外部输入信号从1到0跳变时,计数器的值加一。
2.定时器相关寄存器
(1) 控制寄存器TCON(88H)
TCON用于控制定时器的启动、停止、溢出标志和外部中断信号触发方式。
(2) 方式控制寄存器TMOD(89H)
从上图中可知,GATE为0时候,定时器由TR0或TR1控制启动,为1的时候,只有在外部中断引脚为高电平时候,TR0或者TR1才可以控制启动,对于T1,有3种工作方式,而T0有四种工作方式;
3.定时器工作方式
定时器工作方式如下
(1) 工作方式0
方式0为13位计数器,由TLi的低5位和THi的8位组成,当GATE为1的时候,取反为0,定时器启动需要外部中断i引脚为1,然后置位TRi启动定时器,当外部中断i引脚变为0时候,定时器停止计数,这种方式可用来测试外部中断引脚正脉冲的宽度,当处于计数模式时,计数脉冲是Ti引脚上的外部脉冲。
定时模式初值:
X = 2的13次方 - f/12 * T (其中X为计数器初值, f为时钟频率,T为定时时间)
计数模式初值:
X = 2的13次方 - 计数值
(2) 工作方式1
方式1和方式0结构几乎完全相同,唯一区别是计数器的长度不同,方式1定时器长度为16位定时模式初值:
X = 2的16次方 - f/12 * T (其中X为计数器初值, f为时钟频率,T为定时时间)
计数模式初值:
X = 2的16次方 - 计数值
(3) 工作方式2
方式2是能自动重装载计数初值的8位计数器, TLi用作计数器,THi保存计数初值,当TLi计数溢出时,将TFi位置1,同时又将保存在高8位中的计数初值重新装入低8位计数器中。
定时模式初值:
X = 2的8次方 - f/12 * T (其中X为计数器初值, f为时钟频率,T为定时时间)
计数模式初值:
X = 2的8次方 - 计数值
(4) 工作方式3
方式3只有T0支持,T1不支持,若将T1设置为方式3,T1会立即停止计数,且方式3相比其他几种方式,方式3只用了TL0计数器,其他操作和方式0、方式1相同。
注意:通常定时器中定时使用方式1,串口通信使用方式2
二、实例
1.创建工程
将上一节工程复制出来,并修改名字为07-timer
2.程序
我们使用定时器T0的方式1实现一个20ms的中断,中断服务程序中软件计数,当达到50次,总计1S时候,翻转LED引脚电平
首先,计算初值X
X = 2的16次方 - f/12 * T (其中X为计数器初值, f为11.0592MHZ,T为0.02S)
X = 47104 = 0xB800
然后初始化定时器
void tiemr_init(void)
{
TMOD = 0x01; //使用模式1,16位定时器
TH0 = 0xB8;
TL0 = 0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
中断服务子程序
void timer0_func() interrupt 1
{
TH0 = 0xB8;
TL0 = 0x00;
if (count >50)
{
LED = ~LED;
count = 0;
}
count ++;
}
完整代码
/*------------------------------------------------------
*店铺网址:https://shop321633213.taobao.com/?spm=a1z10.3-c.0.0.33816af5iLgN2F
*适用于A08开发板
*实验现象:定时器中断实现LED 1S亮灭
*QQ群:906015840
-------------------------------------------------------*/
#include #include #define uchar unsigned char #define uint unsigned int sbit LED = P1^0; int count = 0; void tiemr_init(void) { TMOD = 0x01; //使用模式1,16位定时器 TH0 = 0xB8; // 20ms中断,初值0xB800 TL0 = 0x00; EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 } void main(void) //主函数 { tiemr_init(); while(1); } // 20ms进入一次中断,计数50次为一秒 void timer0_func() interrupt 1 { TH0 = 0xB8; TL0 = 0x00; if (count >50) { LED = ~LED; count = 0; } count ++; } 注意:中断子程序中需要重新装载计数器初值 三、运行 将上述程序生成的hex文件烧录到板子中,可以看到P1^0对应LED灯每隔1秒亮灭一次,说明进入定时器中断程序执行成功。
上一篇:51单片机玩转物联网基础篇09-串口通信
下一篇:51单片机玩转物联网基础篇07-外部中断
推荐阅读






实战 培训 开发板 精华推荐
最新视频课程更多
- EEWORLD月度问答榜(第2期)
- 免费体验业界最快编译速度&最好性能 Quartus II v15.0网页版下载有礼!
- 【EEWORLD第二十七届】2011年06月社区明星人物揭晓!
- 感恩季 送礼季!EEWORLD陪你玩着游戏奔新年
- 遇见春天,“愚”你同乐 快来与keysight一起学习 光通信测试测量解决方案 下载赢好礼!
- USB Tybe-C 知识大考问
- “USB 3.1 规范及重要测试需考虑的因素”江湖令,一起在吐槽中成长
- 观视频,奖礼品 Fluke多功能多产品系列校准器
- 5G来袭 TE Connectivity 助你抢占消费电子市场先机
- TI|痛点解锁机:你的电源设计痛点,我们懂!解锁、评论赢好礼!