找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1254|回复: 7
打印 上一主题 下一主题
收起左侧

二个很菜的单片机中断延时计数问题请高手指教修正

[复制链接]
跳转到指定楼层
楼主
ID:280226 发表于 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;

                   }

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:116773 发表于 2020-4-8 22:29 | 只看该作者
既然项目最小的计时单位是5分钟,为什么不设置一个5分钟的变量,每隔5分钟这个变量增1,这样整个处理过程应该会简化很多。
回复

使用道具 举报

板凳
ID:282850 发表于 2020-4-9 01:30 | 只看该作者
1、把主频分频降低,据各种MCU,有128分频,设寄存器就行了
2、用一个变量计中断次数,不行设个unsigned long变量,几个小时不成问题
回复

使用道具 举报

地板
ID:213173 发表于 2020-4-9 08:12 | 只看该作者
给你一个示例,定时精度取决于晶振精度。未经实物验证,只是供参考。如果加上数码管显示和进一步优化可以做成倒计时显示并使计时误差控制在1秒内。
  1. #include <reg51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. sbit key=P1^0;
  5. sbit LED=P1^6;
  6. sbit OUT=P1^7;

  7. uchar Cnt50ms=0;sec=0;//50毫秒、秒变量
  8. uint min=0;//分变量
  9. bit flag_5=0;//计时标志

  10. void Timer0Init()        //50毫秒@12.000MHz
  11. {
  12.         TMOD= 0x01;                //设置定时器模式
  13.         TL0 = 0xB0;                //设置定时初值
  14.         TH0 = 0x3C;                //设置定时初值
  15.         TR0 = 1;                //定时器0开始计时
  16.         EA = 1;                //开总中断
  17.         ET0= 1;                //开定时器0中断
  18. }
  19. void keyscan()
  20. {
  21.         static bit key_sign=0;//按键自锁标志变量
  22.         static uchar count=0;  //消抖计数变量               
  23.         if(!key)
  24.         {
  25.                 if(++count>=100 && key_sign==0)
  26.                 {
  27.                         key_sign=1;//自锁
  28.                         flag_5=~flag_5;//取反
  29.                         if(flag_5==0)
  30.                                 LED=1;//灯熄 定时器停止工作
  31.                         else
  32.                                 LED=0;//灯亮 定时器工作中
  33.                         //清0 为重新计时准备
  34.                         Cnt50ms=0;
  35.                         sec=0;
  36.                         min=0;
  37.                 }
  38.         }
  39.         else//松手
  40.         {
  41.                 count=0;//消抖计数变量清0
  42.                 key_sign=0;//自锁标志清0
  43.         }
  44. }

  45. void main()
  46. {
  47.         OUT=0;                 //初始化输出端口
  48.         Timer0Init();//初始化定时器
  49.         while(1)
  50.         {
  51.                 keyscan();//按键扫描
  52.         }
  53. }
  54. /**************中断服务程序*****************/
  55. void timer0() interrupt        1
  56. {
  57.         TL0 = 0xB0;                //重装定时初值
  58.         TH0 = 0x3C;                //重装定时初值

  59.         if(flag_5==1)
  60.         {
  61.                 Cnt50ms++;                                        //中断变量Cnt50ms自+1
  62.                 if(Cnt50ms>=20)                                //1秒
  63.                 {
  64.                         Cnt50ms=0;
  65.                         sec++;
  66.                         if(sec>=60)                                //1分
  67.                         {
  68.                                 sec=0;                                //秒计数
  69.                                 min++;
  70.                         }
  71.                 }
  72.                 if(min<480)                                        //8小时
  73.                         OUT=0;       
  74.                 if(min>=480||min<485)        //8小时与8小时零5分之间
  75.                         OUT=1;       
  76.                 if(min>=485)                                //8小时零5分时间到
  77.                 {//全部清0
  78.                         OUT=0;       
  79.                         Cnt50ms=0;
  80.                         sec=0;
  81.                         min=0;
  82. //                        flag_5=0;//不重复循环
  83.                 }
  84.         }
  85. }
复制代码
回复

使用道具 举报

5#
ID:592807 发表于 2020-4-9 08:46 | 只看该作者
看着代码好费劲啊,你就不能将你的temp_5++   temp_6++封装个函数调用一下吗
回复

使用道具 举报

6#
ID:280226 发表于 2020-4-9 12:15 | 只看该作者
wulin 发表于 2020-4-9 08:12
给你一个示例,定时精度取决于晶振精度。未经实物验证,只是供参考。如果加上数码管显示和进一步优化可以做 ...

非常感谢wulin师傅的无私指导,您已多次指导,受您启发,多次受益,均已成功,谢谢您!!
回复

使用道具 举报

7#
ID:367369 发表于 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;

}

回复

使用道具 举报

8#
ID:280226 发表于 2020-4-9 21:38 | 只看该作者
game灬boy 发表于 2020-4-9 13:14
你的测试5分钟可行对吧;然后在5分钟的基础上再定义1个变量    分钟m;
假设你的5分钟技数count=50时为5分 ...

谢谢指导!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表