51单片机的机器周期是晶振的12分频的倒数。所以你24Mhz的机器周期是T=12/12M=0.5us。
假设你要定时的数是M,则初值等于M/机器周期(表示执行多少个机器周期)。
若初值小于65536
TH0=(65536-初值)%256
TL0=(65536-初值)/256
51在24MHZ的最大定时是65536*T=0.032768s,远小于一小时。
所以为了方便计算,我们假设定时0.01s,然后执行3600/0.01次。
M=0.01/T=20000
TH0=(65536-初值)%256=0xB1
TL0=(65536-初值)/256=0x7F
用这个数一次定时精确值是0.0100485s。执行360000次精确值是3617.46s。
中断程序是:
timer0() interrupt 1
{
TR0=0;
ET0=0;
TH0=0xB1;
TL0=0x7F;
if(delay_1hour)
{
if(j) //如果j大于0
{
TR0=1;j--; //说明还没到3600次
}
else
{
if(i) 就算j等于0了,i大于0,说明还没到100次
{
TR=1;j=3600;
}
else
{
flag_1hour=0; //循环了3600000次10ms,关闭延时标志位。。
}
}
}
ET0=1;
}
调用程序:
void delay1hour()
{
delay_1hour=1;i=100;j=3600;TR0=1;
}//在任意你想开始延时一小时的地方加这个函数。
在延时期间,单片机还可以干其他指令。
这个纯粹靠寄存器的级联
定义定时器定时方式1,(16位)模式,因为你24M晶振,所以定时值最大也就30几毫秒。所以你定时值可以选为25ms,然后定义个MS寄存器每40次中断对应1秒
在定义个SEC每60次为1分钟,定义一个MIN 每60次为1小时,定义个HOU,这个就看你延时几个小时了。这些定义放在主程序前面,为全局变量8位的即可
unsigned char MS,SEC,MIN,HOU;
然后定时器中断加入以下代码
{
MS++;
if(MS==40)
{
MS=0;
SEC++;
if(SEC==60)
{
SEC=0;
MIN++;
if(MIN==60)
{
MIN=0; //其实到这就已经是1小时了
HOU++;这个就是看您计数到几个小时了,8位寄存器最大255你懂的)
}
}
}
添加#include "intrins.h"
然后#define Nop() _nop_()
在程序中就可以直接用Nop();进行一个机器周期的延时了。
--------------------------------------------------------------------------------
刚刚看错了不好意思,同意楼上的观点,用定时器来做,添加几个定时变量,当计到的总数达到1个小时时就执行对应的操作即可。也可以使用外部的带中断输出的RTC来完成,精度更高点。
使用定时器啊,设置一个标志位,1小时候取反就行了
void delay(uchar ms)//延时1ms
{
uchar i,j;
for(i=ms;i--;i>0)
for(j=110;j--;j>0);
}
delay(60000);//1h=1*60*1000=60000;