找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2970|回复: 13
收起左侧

单片机储物箱检测程序中断嵌套程序 请高手帮改一下

[复制链接]
ID:280226 发表于 2018-2-12 22:42 | 显示全部楼层 |阅读模式
写了一个储物箱检测程序,思路是当物品放置时,压下微动开关,进入中断程序,继电器接通设定的时间;这部分程序测试正常,但现在有个问题搞不定,就是当进入中断程序后,如果拿开物品,中断程序还得继续完成,如何在中断程序中嵌入一个判断程序,在K开关复位后自动退出中断程序回到主程序?谢谢!
  1. #include <reg52.h>
  2. typedef unsigned int u16;
  3. typedef unsigned char u8;
  4. unsigned int s;
  5. sbit k=P1^0;          //微动开关
  6. sbit Relay1 =P0^0;   //继电器端口
  7. sbit Relay2 =P0^1;
  8. bit  fir=0;           //物品存在标志位
  9. /***********************************************
  10. 定时函数
  11. ************************************************/
  12. void Timer0Init(void)
  13. {
  14.          
  15.          TMOD = 0x01;            
  16.          TL0 = 0xB0;               
  17.          TH0 = 0x3C;               
  18.          EA=1;
  19.          ET0=1;
  20.          TR0 = 1;               
  21. }
  22. /***********************************************
  23. 主函数
  24. ************************************************/
  25. int main()
  26. {
  27.          Relay1=1;
  28.         Relay2=1;
  29.         Timer0Init();
  30.          while(1)
  31. {  
  32.   if((k==1)&&(fir==0))
  33.   {
  34.        TR0=1;                 //有物品时开始计时
  35.        Relay1=0;              //继电器通电
  36.        Relay2=0;  
  37.                  }
  38.         }
  39. }
  40. /***********************************************
  41. 中断函数
  42. ************************************************/
  43. void Timer0() interrupt 1   
  44. {
  45.         u16 temp;
  46.         s=1;      //改变S可改变定时时间
  47.          TL0 = 0xB0;               
  48.          TH0 = 0x3C;               
  49.          temp++;
  50.          if(temp==(20*60)*s)      
  51.          {
  52.                  temp=0;
  53.                  Relay1=1;   //继电器断电
  54.                  Relay2=1;
  55.                  fir=1;        //标志位置1
  56.            }
  57. }
复制代码


回复

使用道具 举报

ID:273292 发表于 2018-2-13 08:57 | 显示全部楼层
你这箱子压下去的开关本来就是中断触发的信号,如这个信号没了自然就没法继续在中断呆着了,不知道有没有高手
回复

使用道具 举报

ID:282439 发表于 2018-2-13 09:09 | 显示全部楼层
你需要将TEMP声明为全局变量。因为TIMER0是中断程序。退出后不能保持TEMP的数值了。
回复

使用道具 举报

ID:280226 发表于 2018-2-13 09:45 | 显示全部楼层
希望高手能直接在程序中帮修改一下,这样对照就能知道程序缺陷在哪了,谢谢!
回复

使用道具 举报

ID:280226 发表于 2018-2-13 10:31 | 显示全部楼层
第一个程序有个缺陷,就是把物品拿开后再进入,因为物品标志位为1,就再进不了中断程序。现又把程序完善了一下,在物品拿开后标志位置0,这样在物品离开再进入时就可以再进入中断程序了。现在就是在中断过程中如果物品拿开,无法立即退出中断程序,这个求教高手。
#include <reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
unsigned int s;
sbit k=P1^0;          //微动开关
sbit Relay1 =P0^0;   //继电器端口
sbit Relay2 =P0^1;
bit  fir=0;           //物品存在标志位
/***********************************************
定时函数
************************************************/
void Timer0Init(void)
{
         
         TMOD = 0x01;            
         TL0 = 0xB0;               
         TH0 = 0x3C;               
         EA=1;
         ET0=1;
         TR0 = 1;               
}
/***********************************************
主函数
************************************************/
int main()
{
         Relay1=1;
        Relay2=1;
        Timer0Init();
         while(1)
{  
  if((k==1)&&(fir==0))
  {
       TR0=1;                 //有物品时开始计时
       Relay1=0;              //继电器通电
       Relay2=0;  
                 }
    if((k==0)$$(fir==1))
  {
   fir=0;
   }
        }
}
/***********************************************
中断函数
************************************************/
void Timer0() interrupt 1   
{
        u16 temp;
        s=5;      //改变S可改变定时时间
         TL0 = 0xB0;               
         TH0 = 0x3C;               
         temp++;
         if(temp==(20*60)*s)      
         {
                 temp=0;
                 Relay1=1;   //继电器断电
                 Relay2=1;
                 fir=1;        //标志位置1
           }
}
回复

使用道具 举报

ID:213173 发表于 2018-2-13 19:38 | 显示全部楼层
xmcai 发表于 2018-2-13 10:31
第一个程序有个缺陷,就是把物品拿开后再进入,因为物品标志位为1,就再进不了中断程序。现又把程序完善了 ...

参看我在“请问怎么写这个10s灯灭的语句 帮下忙解解惑”http://www.51hei.com/bbs/dpj-107271-1.html中的回复,程序逻辑功能几乎完全一致。
回复

使用道具 举报

ID:280226 发表于 2018-2-14 11:32 | 显示全部楼层
wulin 发表于 2018-2-13 19:38
参看我在“请问怎么写这个10s灯灭的语句 帮下忙解解惑”http://www.51hei.com/bbs/dpj-107271-1.html中的 ...

试了您的程序,时间长了就不行了,我需要有个15分钟左右的时间。
回复

使用道具 举报

ID:280226 发表于 2018-2-14 12:29 | 显示全部楼层
wulin 发表于 2018-2-13 19:38
参看我在“请问怎么写这个10s灯灭的语句 帮下忙解解惑”http://www.51hei.com/bbs/dpj-107271-1.html中的 ...

参考您的程序,再修改了中断程序,现在完美解决了,可以延时任意时间了。谢谢解答。
回复

使用道具 举报

ID:213173 发表于 2018-2-14 14:09 | 显示全部楼层
xmcai 发表于 2018-2-14 11:32
试了您的程序,时间长了就不行了,我需要有个15分钟左右的时间。

我是说这个程序逻辑功能几乎与你的要求完全一致,至于定时时间的长短是可以任意设定的。改成定时15分钟:
#include <AT89X52.H>
#define uint unsigned int
#define uchar unsigned char
sbit key=P3^4;          //按键端口定义        
sbit LED=P1^0;          //发光管端口定义
uchar Cnt50ms=0;        //中断计数变量
uint Cnt1s=0;           //中断计数变量
void Timer0Init()       //50毫秒@12.000MHz
{
        TMOD= 0x01;          //设置定时器模式
        TL0 = 0xB0;          //设置定时初值
        TH0 = 0x3C;          //设置定时初值
//  TF0 = 0;            //清除TF0标志
//  TR0 = 1;            //定时器0开始计时
        EA=1;                //开总中断
        ET0=1;               //开定时器0中断        
}
void keyscan()
{
        static bit key_sign=0;        //按键有效标志
        static uint  count=0;        //计数变量                        
        if(key==0)                    //检测按键如果为0
        {
                count++;                 //消抖计数
                if((count>=500)&&(key_sign==0))
                {                        
                        key_sign=1;           //按键有效标志置1
                        Cnt50ms=0;            //中断计数变量清0
                        Cnt1s=0;              //中断计数变量清0
                        TR0 = 1;              //启动定时器
                        LED=0;                //发光管亮
                }
        }
        else                          //按键抬起
        {
                key_sign=0;               //按键有效标志清0
                count=0;                  //消抖计数清0
                LED=1;                    //发光管灭
                TR0=0;                    //关闭定时器
        }
}
void main()
{
        Timer0Init();              //定时器0初始化
        while(1)
        {
                keyscan();             //按键扫描
        }
}
void timer0() interrupt 1        //定时器0中断
{
        TL0 = 0xB0;                 //设置定时初值
        TH0 = 0x3C;                  //设置定时初值
        Cnt50ms++;
        if(Cnt50ms>=20)             //1秒
        {
                Cnt50ms=0;
                Cnt1s++;
                if(Cnt1s>=900)                        //15分钟
                {
                        Cnt1s=0;
                        LED=1;           //发光管灭
                        TR0=0;           //关闭定时器
                }
        }
}

评分

参与人数 1黑币 +100 收起 理由
admin + 100 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:280226 发表于 2018-2-14 14:41 | 显示全部楼层
wulin 发表于 2018-2-14 14:09
我是说这个程序逻辑功能几乎与你的要求完全一致,至于定时时间的长短是可以任意设定的。改成定时15分钟: ...

谢谢您的帮忙,已完美解决。
回复

使用道具 举报

ID:280226 发表于 2018-2-14 16:19 | 显示全部楼层
wulin 发表于 2018-2-14 14:09
我是说这个程序逻辑功能几乎与你的要求完全一致,至于定时时间的长短是可以任意设定的。改成定时15分钟: ...

在此基础上,如果用三个按键分别控制三个LED,能否共用一个中断程序各自定时15分钟?
回复

使用道具 举报

ID:123289 发表于 2018-2-14 16:49 | 显示全部楼层
没有真正的理解或认识,单片机中断是干什么用的。中断的流程是什么?先补一下课,再做。
回复

使用道具 举报

ID:213173 发表于 2018-2-15 08:59 | 显示全部楼层
xmcai 发表于 2018-2-14 16:19
在此基础上,如果用三个按键分别控制三个LED,能否共用一个中断程序各自定时15分钟?

当然可以!定时器只是一个时基,可以提供N个定时服务,即可以是相同的定时时间,也可以是不同的定时时间。虽然新型单片机内置多个定时器,但只要规划得合理,一个定时器几乎可以完成所有定时任务。如果使用多个定时器且规划失当,定时中断间相互干扰是不容忽视的问题。
回复

使用道具 举报

ID:280226 发表于 2018-2-15 15:37 | 显示全部楼层
wulin 发表于 2018-2-15 08:59
当然可以!定时器只是一个时基,可以提供N个定时服务,即可以是相同的定时时间,也可以是不同的定时时间 ...

您的编程思路和方法值得学习和借鉴,谢谢解答!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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