采用12Mhz晶振的51单片机,软件如下(调试通过)
#include
#define PERIODH (65536l-50000l)/0X100 //设50ms中断1次TH1初值
#define PERIODL (65536l-50000l)%0X100 //设50ms中断1次TL1初值
//如果需要极精确的延时,应根据实际编译后的产生的汇编指令,扣除掉中断响应中重装所占用的时间
unsigned int count;//延时时间变量
void timer1() interrupt 3 using 1
{//定时器每0.05秒一次中断
TH1 = PERIODH;
TL1 = PERIODL;
if(count)
{//计数未到0,则保持定时器运行,计数器-1
count--;
}
else
{//计数到0,关定时器
TR1 =0; //stop timer 1
}
}
//以秒为基本定时单位的子程序
void Delay1S(unsigned char x)
{
TH1 =PERIODH;
TL1 =PERIODL;
TR1 = 1;//此时定时开始
count = 20*x;//因50ms中断1次,故乘20
while(count);
}
main()
{
TMOD = 0X10;//方式1
EA = 1;//总中断允许
ET1 = 1;//定时器1中断允许
while(1)
{
Delay1S(1);//延时1秒
Delay1S(2);//延时2秒
Delay1S(3);//延时3秒
Delay1S(4);//延时4秒
}
}
Delay1S函数是调用时才开始计时,根据需要的定时长度到时停止计时。如果定时精度要求不高,可以不用在中段服务程序中关闭定时器,每次调用误差也就在50ms。
可以用KEIL仿真看一下实际时间
#include
unsigned char i;
void main()
{
TMOD=0x10;
TH1=0x3c;
TL1=0xb0;
EA=1;
ET1=1;
TR1=1;
while(1)
{
if(i==20)
{
i=0;
//下面写你要处理的的其他程序,你只要了定时1s。
}
}
}
void a(void) interrupt 3
{
unsigned char i;
TH1=0x3c;
TL1=0xb0;
i++;
}
12Mhz的51单片机,经过12分频后为1MHz,则一个指令周期为1/1Mhz = 1us.
则定时50ms为 0xffff - 0x3cb0,即65535 - 15535 = 50000us = 50ms,则20次的定时:20×50ms=1s。
明白了吗?怪简单的问题……
祝你顺利哦!
这个太简单了,给你个方法,你自己弄吧,不会多看看书。
1 使能定时器
2 使能定时器中断
3 编写中断程序
我估计你是觉得1秒的时间,定时器达不到,你可以在中断里面再自己写个计数,或者开启计数器2,这样两两相乘,时间就能到1秒钟了。
要做到精确的定时,就要用计数器2,然后在Keil里可以看到时间,再对定时器进行微调就好了。
void sheding()
{
TMOD=0x10;//定时器/计数器工作方式寄存器的设定
TH1=(65536-50000)/256;
TL1=(65536-50000)%265;
//定时器/计数器控制寄存器设定
EA=1; //全局中断允许位
ET1=1; //打开定时器/计数器1
TR1=1;
}
void zhongduan() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
k++;
if(k==20)
{
k=0;
shu++;
if(shu==86400)
shu=0;
}
}
#include
unsigned int num ;
void InitTimer1(void)
{
TMOD = 0x10;
TH1 = 0x3C; //50ms定时
TL1 = 0x0B0;
EA = 1;
ET1 = 1;
TR1 = 1;
}
void main(void)
{
InitTimer1();
}
void Timer1Interrupt(void) interrupt 3
{
TH1 = 0x3C;
TL1 = 0x0B0;
num++;
if(num==20){ ;} //1S时间到。
}