1、实验目的
(1)使用定时器来完成LED闪烁。
(2)使用定时器来定一个时间(比如0.5S),在这个定时器定时时间内CPU还可以去做主任务(main函数中的循环体),定时时间到产生中断,在中断处理程序中让LED闪烁。
2、定时器最多定时时长
(1)当外部晶振位12MHz,工作在12T模式下,也就是内部进行12分频。这时CPU的工作频率为1MHz(CPU实际工作频率为时钟周期)。
(2)51单片机中定时器工作频率等于CPU工作频率。
(3)时钟周期为:1/12M秒 = 1uS。16位定时器最多计数65535,也就是说最大定时时间为:
65535*1uS = 65535uS = 65.353mS。
(4)如果要定一个比较长的时间(譬如2S),定时器是不能直接满足的,解决办法是多次定时后加起来构成一个长时间。
3、计算TL0、TH0
(1)确定自己定时时长,例如50mS。
(2)确定时钟周期。因为外部晶振12MHz,12T模式,所以为1uS。
(3)定时器计数个数是:50mS / 1uS = 50 000
(5)51单片机是加法定时器,也就是从初始值加到超过65535(16位定时器)就产生中断。
(6)十进制:6 5535 - 50 000 + 1(溢出才产生中断) = 15536
15536转换为16进制为: 0x3CB0
TL0 = 15536 & 0x00ff = 0xB0; //设置定时初始值
TH0 = 15536 >> 8 = 0x3C; //设置定时初始值
4、实验代码
/*
*功能:使用定时器让LED闪烁
*定时器:使用定时器0
*单片机型号:STC89C516
*/
#include <reg52.h>
sbit LED = P0^0;
unsigned int count;
/*函数声明*/
void Timer0Init(void); /*定时器0初始化,50mS*/
void main()
{
count = 0;
Timer0Init();
ET0 = 1; //打开T0溢出中断
EA = 1; //打开总中断
while(1)
{
}
}
/*
*功能: 定时器0初始化,50mS
*/
void Timer0Init(void) //50毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式,16位定时器/计数器,TL0、TH0全用,工作在定时器模式下
TMOD |= 0x01; //设置定时器模式
TL0 = 0xB0; //设置定时初始值
TH0 = 0x3C; //设置定时初始值
TF0 = 0; //定时器溢出标志,清除TF0标志,
TR0 = 1; //定时器运行控制位,定时器0开始计数
}
/*
*功能:定时器0中断处理函数
*/
void tm0_isr() interrupt 1 using 1
{
TL0 = 0xB0; /*手工重载计数值*/
TH0 = 0x3C;
count++;
if(count == 10) /*500mS到了*/
{
LED = !LED;
count = 0;
}
}
5、补充
5.1、加法定时器和减法定时器
(1)定时器的原理就是计数器,加法定时器计数方法是从我们给定的值开始计数,直到溢出(譬如16位定时器最大值是0xffff,也就是65535,计数值超过这个值就溢出了)。减法定时器是从我们给定的值开始减1,减到小于0就溢出了。
(2)实例来看,譬如16位定时器,需要的计数个数为1000。
如果是减法定时器那么计数寄存器初始值就是1000 - 1;
如果是加法定时器那么计数寄存器初始值就是65535-1000 + 1=64535 + 1。
(3)51单片机就是典型的加法定时器。
(4)现代的单片机或者嵌入式soc,一般常用的都是减法定时器了。虽然加法定时器和减法定时器都能实现功能,但是明显减法定时器更加直观。
(5)51单片机可以用STC-ISP软件来辅助计算定时时间。
5.2、中断处理程序中using关键字
(1)在写中断处理函数时候,有时候会发现关键字using 。
例如: void Timer0Rountine(void) interrupt 1 using 1
(2)using 1 可有可无。
(3)51单片机中using使用在C51编程中,用来在中断函数中指定工作寄存器区,工作寄存器共有4个区,分别代表R0~R7地址是:
第0工作区:00H~07H
第1工作区:08H~0FH
第2工作区:10H~17H
第3工作区:18H~1FH
using n,那么n就是第几区,使用方法如下:
void exterint0() interrupt 0 using 1
这表示外部中断0使用第1工作区地址。
详细理解可能需要学习汇编