标题: 二个很菜的单片机中断延时计数问题请高手指教修正 [打印本页]
作者: xmcai 时间: 2020-4-8 20:21
标题: 二个很菜的单片机中断延时计数问题请高手指教修正
在一段中断计数延时的单片机程序设计中,被二个很菜的问题困扰着,请高手师傅指教改正。
1、 利用中断计数设计一段8小时的长时间延时程序,计数满8小时后继电器自动接通工作5分钟,然后重新进入8小时延时程序,如此循环,直至外部打断使flag_5计时标志为0止。测试时,每个计数节用(20*60)*2时(即2分钟),9节共18分钟,可以正常接通继电器,然后5分钟后断开,程序正常执行。但当每个计数节用(20*60)*54时(即54分钟,最大也只能设定为54分钟,因为最大计数为65536),按理应该在8.1小时后继电器接通,但实际却执行不了,继电器始终不接通,不知问题出在哪?请高手指教改正。
if( flag_5==1 ) //如果计时标志5为1,进入下面8小时延时
{
temp_5++; //中断计数变时5自+1
if(temp_5>=(20*60)*54) //(20*60)为延时1分钟基数,*54可延时54分钟
{
temp_6++;
if(temp_6>=(20*60)*54)
{
temp_7++;
if(temp_7>=(20*60)*54)
{
temp_8++;
if(temp_8>=(20*60)*54)
{
temp_9++;
if(temp_9>=(20*60)*54)
{
temp_10++;
if(temp_10>=(20*60)*54)
{
temp_11++;
if(temp_11>=(20*60)*54)
{
temp_12++;
if(temp_12>=(20*60)*54)
{
temp_13++;
if(temp_13>=(20*60)*54)
{
Relay=1; //上面计数延时满山8小时,继电器接通
temp_4=0;
temp_5=0;
temp_6=0;
temp_7=0;
temp_8=0;
temp_9=0;
temp_10=0;
temp_11=0;
temp_12=0;
temp_13=0;
flag_5=0;
flag_6=1;
}
}
}
}
}
}
}
}
}
}
if(flag_6==1) //如果计时标位flag_6=1
{
temp_6++; //中断变量temp_6+1
if(temp_6>=(20*60)*54) //(20*60)为延时1分钟,*5可延时5分钟
{
Relay=0; //继电器断开
temp_6=0;
flag_6=0; //计时标志6清零
flag_5=1; //计时标志5为1,重新进入上面的循环
}
}
2、用一段do-while的循环程序替代上面的九节计数环节,却延时不了,错在何处,也请高手师傅指教一下。
if( flag_5==1) //如果计数标志为1,进入下面的循环环节
{
temp_5=0;
temp_6=0;
do
{
temp_5++;
if(temp_5>=(20*60)*54)
{
temp_5=0;
temp_6=temp_6+1;
}
}
while(temp_6<=9);
}
if(temp_6>=9)
{
Relay0=1; //继电器接通
flag_5=0;
flag_6=1;
}
作者: hujj 时间: 2020-4-8 22:29
既然项目最小的计时单位是5分钟,为什么不设置一个5分钟的变量,每隔5分钟这个变量增1,这样整个处理过程应该会简化很多。
作者: f556 时间: 2020-4-9 01:30
1、把主频分频降低,据各种MCU,有128分频,设寄存器就行了
2、用一个变量计中断次数,不行设个unsigned long变量,几个小时不成问题
作者: wulin 时间: 2020-4-9 08:12
给你一个示例,定时精度取决于晶振精度。未经实物验证,只是供参考。如果加上数码管显示和进一步优化可以做成倒计时显示并使计时误差控制在1秒内。
- #include <reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit key=P1^0;
- sbit LED=P1^6;
- sbit OUT=P1^7;
- uchar Cnt50ms=0;sec=0;//50毫秒、秒变量
- uint min=0;//分变量
- bit flag_5=0;//计时标志
- void Timer0Init() //50毫秒@12.000MHz
- {
- TMOD= 0x01; //设置定时器模式
- TL0 = 0xB0; //设置定时初值
- TH0 = 0x3C; //设置定时初值
- TR0 = 1; //定时器0开始计时
- EA = 1; //开总中断
- ET0= 1; //开定时器0中断
- }
- void keyscan()
- {
- static bit key_sign=0;//按键自锁标志变量
- static uchar count=0; //消抖计数变量
- if(!key)
- {
- if(++count>=100 && key_sign==0)
- {
- key_sign=1;//自锁
- flag_5=~flag_5;//取反
- if(flag_5==0)
- LED=1;//灯熄 定时器停止工作
- else
- LED=0;//灯亮 定时器工作中
- //清0 为重新计时准备
- Cnt50ms=0;
- sec=0;
- min=0;
- }
- }
- else//松手
- {
- count=0;//消抖计数变量清0
- key_sign=0;//自锁标志清0
- }
- }
- void main()
- {
- OUT=0; //初始化输出端口
- Timer0Init();//初始化定时器
- while(1)
- {
- keyscan();//按键扫描
- }
- }
- /**************中断服务程序*****************/
- void timer0() interrupt 1
- {
- TL0 = 0xB0; //重装定时初值
- TH0 = 0x3C; //重装定时初值
- if(flag_5==1)
- {
- Cnt50ms++; //中断变量Cnt50ms自+1
- if(Cnt50ms>=20) //1秒
- {
- Cnt50ms=0;
- sec++;
- if(sec>=60) //1分
- {
- sec=0; //秒计数
- min++;
- }
- }
- if(min<480) //8小时
- OUT=0;
- if(min>=480||min<485) //8小时与8小时零5分之间
- OUT=1;
- if(min>=485) //8小时零5分时间到
- {//全部清0
- OUT=0;
- Cnt50ms=0;
- sec=0;
- min=0;
- // flag_5=0;//不重复循环
- }
- }
- }
复制代码
作者: 黄youhui 时间: 2020-4-9 08:46
看着代码好费劲啊,你就不能将你的temp_5++ temp_6++封装个函数调用一下吗
作者: xmcai 时间: 2020-4-9 12:15
非常感谢wulin师傅的无私指导,您已多次指导,受您启发,多次受益,均已成功,谢谢您!!
作者: game灬boy 时间: 2020-4-9 13:14
你的测试5分钟可行对吧;然后在5分钟的基础上再定义1个变量 分钟m;
假设你的5分钟技数count=50时为5分钟
8小时60*8=480分钟480/5=96
m=96时;继电器使能;m=97时;继电器关闭使能;
if (count==50)
{
m++;
if(m==96)
使能flag=1;
if(m==97)
{
使能flag=0;
m=0;
}
count=0;
}
作者: xmcai 时间: 2020-4-9 21:38
谢谢指导!
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |