07 51单片机之定时器
文章目录
- 1、前言
- 2、定时器
- 3、STC89C52定时器资源
- 3-1、定时器/计数器(T0/T1)
- 3-2、定时器框图
- 3-3、定时器/计数器0和1的相关寄存器
- 3-3-1、定时器/计数器控制寄存器TCON
- 3-3-2、定时器/计数器工作模式寄存器TMOD
- 3-4、模式1:16位定时器/计数器(常用)
- 4、中断系统
- 4-1、概念介绍
- 4-2、中断系统结构
- 4-3、中断系统寄存器
- 4-3-1、中断允许寄存器IE
- 4-3-2、中断允许寄存器XICON
- 4-3-3、中断优先级控制寄存器IP/XICON和IPH
- 4-3-4、定时器/计数器0/1控制寄存器TCON
- 4-3-5、串行口控制寄存器SCON
- 4-3-6、定时器/计数器2控制寄存器T2CON
- 5、工程编码
- 5-1、点亮一个LED(Timer0)
- 5-2、以1s间隔点亮LED(Timer0)
- 5-3、STC_ISP生成定时器配置代码
- 5-4、流水灯LED
- 5-5、实验现象
- 5-6、时钟显示
- 5-7、实验现象
1、前言
在前面的文章中介绍了51单片机之矩阵键盘,今天介绍单片机的定时器。
2、定时器
- 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。
- 定时器作用:
- 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。
- 替代长时间的Delay,提高CPU的运行效率和处理速度。
- 操作系统多任务的切换等等(参考STM模块)。
3、STC89C52定时器资源
- 定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源;
- 注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的。
3-1、定时器/计数器(T0/T1)
- STC89C52系列单片机的定时器0和定时器1,与传统8051的的定时器完全兼容,当在定时器1做波特率发生器时,定时器0可以当两个8位定时器用。
- STC89C52系列单片机内部设置的两个16位定时器/计数器T0和T1都具有计数方式和定时方式两种工作方式。对每个定时器/计数器(T0和T1),在特殊殊功能寄存器TMOD中都有一控制位一C/T来选择T0或T1为定时器还是计数器。定时器/计数器的核心部件是一个加法(也有减法)的计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:如果计数脉冲来自系统时钟,则为定时方式,此时定时器/计数器每12个时钟或者每6个时钟得到一个计数脉冲,计数值加1;如果计数脉冲来自单片机外部引脚(T0为P3.4,T1为P3.5),则为计数方式,每来一个脉冲加1。
- 当定时器/计数器工作在定时模式时,可在烧录用户程序时在STC-ISP编程器中设置(如下图所示)是系统时钟÷12还是系统时钟÷6后让T0和T1过进行计数。当定时器/计数器工作在计数模式时,对外部脉冲计数不分频。
- 定时器/计数器0有4种工作模式:模式0(13位定时器/计数器),模式1(16位定时器/计数器模式),模式2(8位自动重装模式),模式3(两个8位定时器/计数器)。定时器/计数器1除模式3外,其他工作模式与定时器/计数器0相同,T1在模式3时无效,停止计数。
3-2、定时器框图
定时器在单片机内部就像一个小闹钟一样,根据时钟的输出言号,每隔"一秒",计数单元的数值就增加一,当计数单元数值增加到"设定的闹钟提醒时间"时,计数单元就会向中断系统发出中断申请,产生"响铃提醒",使程序跳转到中断服务函数中执行。
3-3、定时器/计数器0和1的相关寄存器
3-3-1、定时器/计数器控制寄存器TCON
TCON为定时器/计数器T0、 T1的控制寄存器,同时也锁存T0、 T1溢出中断源和外部请求中断源等, TCON格式如下:
3-3-2、定时器/计数器工作模式寄存器TMOD
定时和计数功能由特殊功能寄存器TMOD的控制位C/\T进行选择,TMOD寄存器的各位信息如下表所列。可以看出,2个定时/计数器有4种操作模式,通过TMOD的M1和M0选择。2个定时/计数器的模式0、1和2都相同,模式3不同,各模式下的功能如下所述。
3-4、模式1:16位定时器/计数器(常用)
由于STC89C52的T0和T1均有四种工作模式。模式0:13位定时器/计数器;模式1:16位定时器/计数器;模式2:8位自动重装模式;模式3:两个8位计数器。其中模式1最为常用。模式1除了使用了TH0及TL0全部16位外,其他与模式0完全相同。即此模式下定时器/计数器0作为16位定时器/计数器,如Figure5. 定时器/计数器0的模式1:16位定时器/计数器所示为工作模式1的框图。
- 此模式下,定时器配置为16位定时器/计数器,由TL0的8位和TH0的8位所构成。TL0的8位溢出向TH0进位,TH0计数溢出置位TCON中的溢出标志位TF0。TL最大值是65535,然后就给TF0置位,触发中断操作。
- SYSclk:系统时钟,即晶振周期,本开发板上的晶振为12MHz。
- 当GATE=0(TMOD.3)时,如TRO=1,则定时器计数。GATE=1时,允许由外部输入INTO控制定时器0,这样可实现脉宽测量。TR0为TCON寄存器内的控制位,TCON寄存器各位的具体功能描述见上节TCON寄存器的介绍。
- 当C/ \T=0时,多路开关连接到系统时钟的分频输出,T0对时钟周期计数,T0工作在定时方式。当C/ \T=1时,多路开关连接到外部脉冲输入P3.4/T0,即T0工作在计数方式。
- STC89C52系列单片机的定时器有两种计数速率:一种是12T模式,每12个时钟加1,与传统8051单片机相同;另外一种是6T模式,每6个时钟加1,速度是传统8051单片机的2倍。T0的速率在烧录用户程序时在STC-ISP编程器中设置。
4、中断系统
4-1、概念介绍
- 中断系统是为使CPU具有对外界紧急事件的实时处理能力而可设置的。
- 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。CPU总是先响应优先级别最高的中断请求。
- 当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比它还高的中断源请求。如果CPU能够暂停对原来可中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程称为中断嵌套。这样的中断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。
- STC89C52系列单片机提供了8个中断请求源,它们分别是:外部中断0(\INT0)、定时器0中断、外部中断1(\INTI)、定时器1中断、串口(UART)中断、定时器2中断、外部中断2(\INT2)、外部中断3(\INT3)。所有的中断都具有4个中断优先级。用户可以用用关总中断允许位(EA/IE.7)或相应中断的允许位来屏蔽所有的中断请求,也可以用打开相应的中断允许位来使CPU响应相应的中断申请:每一个中断源可以用软件独立地控制为开中断或关中断状态:每一个中断的优先级别均可用软件设置。高优先级的中断请求可以打断低优先先级的中断,反之,低优先级的中断请求不可以打断高优先级及同优先级的中断。当两个相同优先级的中断同时产生时,将由查询次序来决定系统先响应哪个中断。
通过设置新增加的特殊功能寄存器IPH中的相应位,可将中断优先级设为四级,如果只设置IP或XICON,那么中断优先级就只有两级,与传统80511单片机两级中断优先级完全兼容。如果使用C语言编程,中断查询次序号就是中断号,例如:
void | 中断函数接口 | 中断号 |
---|---|---|
void | Int0_Routine(void) | interrupt 0; |
void | Timer0_Rountine(void) | interrupt 1; |
void | Int1_Routine(void) | interrupt 2; |
void | Timer1_Rountine(void) | interrupt 3; |
void | UART_Routine(void) | interrupt 4; |
void | Timer2_Routine(void) | interrupt 5; |
void | Int2_Routine(void) | interrupt 6; |
void | Int3_Routine(void) | interrupt 7; |
4-2、中断系统结构
4-3、中断系统寄存器
寄存器是连接软硬件的媒介。在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式。寄存器相当于一个复杂机器的"操作按钮"。
4-3-1、中断允许寄存器IE
4-3-2、中断允许寄存器XICON
4-3-3、中断优先级控制寄存器IP/XICON和IPH
4-3-4、定时器/计数器0/1控制寄存器TCON
4-3-5、串行口控制寄存器SCON
4-3-6、定时器/计数器2控制寄存器T2CON
5、工程编码
5-1、点亮一个LED(Timer0)
#include <REGX52.H>void Timer0_Init()
{/* 1.set timer0 as mode1 (16-bit). M1 = 0, M0 = 1. */TMOD = 0x01; /* 2.TF0 = 0 */TF0 = 0;/* 3.timer0 start running. */TR0 = 1;/* 4.0~65535 每隔1us计数加一, 总共定时时间65535us. 64535离计数器溢出差值1000, 所以计时时间为1ms. *//* 4-1.initial timer0 low byte. */TH0 = 64535 / 256; // 0xFC17 / 0x100/* 4-2.initial timer0 high byte. */TL0 = 64535 % 256; // 0xFC17 % 0x100/* 5.enable timer0 interrupt. */ET0 = 1;/* 6.open global interrupt switch. */EA = 1;/* 7. */PT0 = 0;}void main()
{Timer0_Init();//loopwhile(1){}
}void Timer0_Routine() interrupt 1
{P2_0 = 0;
}
5-2、以1s间隔点亮LED(Timer0)
#include <REGX52.H>void Timer0_Init()
{/* 1.set timer0 as mode1 (16-bit). M1 = 0, M0 = 1. */TMOD = 0x01; /* 2.TF0 = 0 */TF0 = 0;/* 3.timer0 start running. */TR0 = 1;/* 4.0~65535 每隔1us计数加一, 总共定时时间65535us. 64535离计数器溢出差值1000, 所以计时时间为1ms. *//* 4-1.initial timer0 low byte. */TH0 = 64535 / 256; // 0xFC17 / 0x100/* 4-2.initial timer0 high byte. */TL0 = 64535 % 256; // 0xFC17 % 0x100/* 5.enable timer0 interrupt. */ET0 = 1;/* 6.open global interrupt switch. */EA = 1;/* 7. */PT0 = 0;
}void main()
{Timer0_Init();//loopwhile(1){}
}unsigned int T0Cnt;void Timer0_Routine() interrupt 1
{/* Inhibit timer0 count overflow. *//* 4-1.initial timer0 low byte. */TH0 = 64535 / 256; // 0xFC17 / 0x100/* 4-2.initial timer0 high byte. */TL0 = 64535 % 256; // 0xFC17 % 0x100T0Cnt++;if(T0Cnt >= 1000) //1s = 1000ms{T0Cnt = 0;P2_0 = ~P2_0;}
}
5-3、STC_ISP生成定时器配置代码
void Timer0_Isr(void) interrupt 1
{TL0 = 0x18; //设置定时初始值TH0 = 0xFC; //设置定时初始值
}void Timer0_Init(void) //1毫秒@12.000MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式TL0 = 0x18; //设置定时初始值TH0 = 0xFC; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1; //使能定时器0中断
}
5-4、流水灯LED
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>unsigned char KeyNum,LEDMode;void main(void)
{P2 = 0xFE;Timer0_Init();//loopwhile(1){KeyNum = Key();if(KeyNum){if(1 == KeyNum){LEDMode++;if(LEDMode >= 2){LEDMode = 0;}}}}
}void Timer0_Isr(void) interrupt 1
{static unsigned int T0Cnt;/* Inhibit timer0 count overflow. */TL0 = 0x18; //设置定时初始值TH0 = 0xFC; //设置定时初始值T0Cnt++;if(T0Cnt >= 500) //0.5s = 500ms{T0Cnt = 0;if(LEDMode == 0)P2 = _crol_(P2,1);if(LEDMode == 1)P2 = _cror_(P2,1);}
}
5-5、实验现象
流水灯LED
5-6、时钟显示
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
#include "LCD1602.h"unsigned char KeyNum,LEDMode,Sec,Mins,Hour;void main(void)
{LCD_Init();Timer0_Init();P2 = 0xFE;LCD_ShowString(1,1,"GalaxyClock:");LCD_ShowString(2,1,"S:");LCD_ShowString(2,6,"M:");LCD_ShowString(2,11,"H:");//loopwhile(1){KeyNum = Key();if(KeyNum){if(1 == KeyNum){LEDMode++;if(LEDMode >= 2){LEDMode = 0;}}}LCD_ShowNum(2,3,Sec,2);LCD_ShowNum(2,8,Mins,2);LCD_ShowNum(2,13,Hour,2);}
}void Timer0_Isr(void) interrupt 1
{static unsigned int T0Cnt0,T0Cnt1;/* Inhibit timer0 count overflow. */TL0 = 0x18; //设置定时初始值TH0 = 0xFC; //设置定时初始值T0Cnt0++;T0Cnt1++;
// if(T0Cnt0 >= 500) //0.5s = 500ms
// {
// T0Cnt0 = 0;
// if(LEDMode == 0)
// P2 = _crol_(P2,1);
// if(LEDMode == 1)
// P2 = _cror_(P2,1);
// }if(T0Cnt1 >= 1000) //1s = 1000ms{T0Cnt1 = 0;Sec++;if(Sec >= 60){Sec = 0;Mins++;if(Mins >= 60){Mins = 0;Hour++;if(Hour >= 24){Hour = 0;}}}}
}
5-7、实验现象
时钟显示