标题: 51单片机调用两个子程序,为什么只能运行其中一个程序。 [打印本页]

作者: zqy181818    时间: 2020-2-29 00:50
标题: 51单片机调用两个子程序,为什么只能运行其中一个程序。
一个是中断,一个是蓝牙。就只能运行放其中第一个。第二个就沒反应。调一下位置还一样效果.有那位工程师遇到过这样的问题。请求解答一下。谢谢!

作者: csmyldl    时间: 2020-2-29 02:04
如果设置了中断,且中断服务程序设置了向量地址,该函数是不需要被主程序调 用的,只要达到中断的条件就能运行,与你所说的“蓝牙”程序调用不是一回事,你提到只运行一个,是不是只运行中断程序呢?中断程序当然与你设置的调用顺序无关
作者: zqy181818    时间: 2020-2-29 14:00
它是调用中断功能主程序,并不是中断函数,本来两功可以独立运行,我将它们原本两个主程序改成函数方式调用合在一块的,內部while循环没有改,可能是程序运第一个while ,就不往下运行了。
作者: zqy181818    时间: 2020-2-29 16:11
csmyldl 发表于 2020-2-29 02:04
如果设置了中断,且中断服务程序设置了向量地址,该函数是不需要被主程序调 用的,只要达到中断的条件就能 ...

没有直接调用该中断函数。请看楼下我的描述。
作者: csmyldl    时间: 2020-2-29 17:49
zqy181818 发表于 2020-2-29 16:11
没有直接调用该中断函数。请看楼下我的描述。

那得看你具体的代码,你这样描述是想象不到的
作者: zqy181818    时间: 2020-2-29 20:04
csmyldl 发表于 2020-2-29 17:49
那得看你具体的代码,你这样描述是想象不到的

#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
uchar buf[10]=0;  //接收缓存数组
uchar  r_x=0;//接收计数
uchar  r_flag=0;//接收成功标志
uchar tt=0;//定时器变量
uchar num=0;//定时的计时变量
uchar flag=0;//标志位
sbit DA =  P0^1;//上一曲
sbit DB =  P0^2;//下一曲
sbit DC =  P0^3;//单曲&循环
sbit DD =  P0^4;//播放&暂停
sbit DE =  P0^5;//播放第一首且不可触发
sbit DF =  P0^6;//布防  (允许红外信号接入)
void lanya();
void  bufang();

uchar read_data(void)//读取接收数据
{

   uchar tep = 0;
   if(r_flag == 1)
   {
    r_flag = 0;
    tep = buf[2];

        }      
   return tep;
}
void uart_init()
{
  TMOD=0x20;
  TH1=0xfd;          //波特率9600
  TL1=0xfA;
  TR1=1;
  SM0=0;
  SM1=1;
  REN=1;
  EA=1;
  ES=1;
}
void main()
  {
  DA=1;
  DB=1;                                                                                                                                                                                                                                                  
  DC=1;
  DD=1;
  DE=1;
  DF=1;
  
             while(1)
           {
                 lanya();  
         bufang();
                 }
                 
                    
         
         }
          



void lanya()   //手机蓝牙控制
{
  uchar key=0;
  uart_init(); //串口初始化
  
   
//  SPK=1;//蜂鸣器关
  DA=1;
  DB=1;
  DC=1;
  DD=1;
  DE=1;
  DF=1;
     while(1)
         {
          key = read_data();//读取接收数据
        if(key == 'A') DA =0;//打开
        else if(key == 'B') DA =1;//关闭
        else if(key == 'C') DB =0;//打开
        else if(key == 'D') DB =1;//关闭
        else if(key == 'E') DC =0;//打开
        else if(key == 'F') DC =1;//关闭
        else if(key == 'G') DD =0;//打开
        else if(key == 'H') DD =1;//关闭
        else if(key == 'J') DE =0;//打开                                                                                            
        else if(key == 'K') DE =1;//关闭
        else if(key == 'M') DF =0;//打开
        else if(key == 'N') DF =1;//关闭
  }
  
}       
void ser()interrupt 4  //接收中断
{
   RI=0; //清除接收标志
   buf[r_x] = SBUF;//接收数据至缓存区
   r_x++;
   if(buf[0]!='O'){r_x=0;}
   if(r_x == 3)        //接收完成
   {
    r_x=0;
        r_flag=1;
   }

}
   /********************************************************************
                            定时器1函数
*********************************************************************/
void timer1init(void)//定时器1,16位方式2
{        EA=0;
    TMOD=0x11;//设置定时器0为工作方式1
        TH0=(65536-10000)/256;
        TL0=(65536-10000)%256;
        ET0=1;//开定时器0中断
        TR0=1;//启动定时器0
        tt=0;//
        EA=0;//关总中断
}       
   /********************************************************************
                         中断函数   
*********************************************************************/
void time0() interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        tt++;
        if(tt==10)
          {tt=0; num++;
          }
        if((flag==2)&&(num==30))//布防时间,num=30即15秒,可以更改此实现布防延迟时间
           flag=4;

          
}
void  bufang()//布防函数     
{            
   timer1init();//初始化定时器
   DE =1;
   
                           while(1)
                        {
                    if(flag==4)//如果布防时间到
                          {
                           tt=0;//清计数为0
                           EA=0;//关中断
                           num=0;//记的秒数清零
                           flag=5;//flag等于5

                          }       
                        if(DF)//如果感应到人
                       
                         DE =0;         //        播放第一首且不可触发
                          else DE =1;
                       
                        if(flag==5)//如果flag等于5
                           {
                             if(DF)//如果感应到人
                                   {
                                     DE =0;
                                      EA=1;//开中断
                                         

                                    }
                           }
        }          
         
   }
       
/********************************************************************
                              结束
*********************************************************************/
作者: 之一知足    时间: 2020-3-1 09:56
你两个子函数里都带着while(1),当然只能执行一个了,while(1)都没法跳出去,他只会按照默认顺序走第一个
作者: zqy181818    时间: 2020-3-1 15:03
之一知足 发表于 2020-3-1 09:56
你两个子函数里都带着while(1),当然只能执行一个了,while(1)都没法跳出去,他只会按照默认顺序走第一 ...

你有什么好的建义。说说看看。如果没有while功能没有了。更别说运行一个。
作者: csmyldl    时间: 2020-3-1 17:23
zqy181818 发表于 2020-3-1 15:03
你有什么好的建义。说说看看。如果没有while功能没有了。更别说运行一个。

被调用的子函数里均不能有while(1)无限循环,如果要有,可以加上时间的与,如while(time--),事先给time一个合适的值
作者: angmall    时间: 2020-3-1 18:22
给你改了,对比一下就知道哪里改了。

  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint  unsigned int
  4. uchar buf[10]=0;  //接收缓存数组
  5. uchar  r_x=0;//接收计数
  6. uchar  r_flag=0;//接收成功标志
  7. uchar tt=0;//定时器变量
  8. uchar num=0;//定时的计时变量
  9. uchar flag=0;//标志位
  10. sbit DA =  P0^1;//上一曲
  11. sbit DB =  P0^2;//下一曲
  12. sbit DC =  P0^3;//单曲&循环
  13. sbit DD =  P0^4;//播放&暂停
  14. sbit DE =  P0^5;//播放第一首且不可触发
  15. sbit DF =  P0^6;//布防  (允许红外信号接入)
  16. void lanya();
  17. void  bufang();

  18. uchar read_data(void)//读取接收数据
  19. {

  20.         uchar tep = 0;
  21.         if(r_flag == 1)
  22.         {
  23.                 r_flag = 0;
  24.                 tep = buf[2];

  25.         }      
  26.         return tep;
  27. }
  28. void uart_init()
  29. {
  30.         TMOD=0x20;
  31.         TH1=0xfd;          //波特率9600
  32.         TL1=0xfA;
  33.         TR1=1;
  34.         SM0=0;
  35.         SM1=1;
  36.         REN=1;
  37.         EA=1;
  38.         ES=1;
  39. }
  40. void main()
  41. {
  42.         uchar key=0;
  43.         uart_init(); //串口初始化


  44.         //  SPK=1;//蜂鸣器关
  45.         DA=1;
  46.         DB=1;
  47.         DC=1;
  48.         DD=1;
  49.         DE=1;
  50.         DF=1;
  51.         DA=1;
  52.         DB=1;
  53.        
  54.         DC=1;
  55.         DD=1;
  56.         DE=1;
  57.         DF=1;
  58.        
  59.         timer1init();//初始化定时器
  60.         DE =1;

  61.         while(1)
  62.         {
  63.                 lanya();  
  64.                 bufang();
  65.         }
  66.        
  67. }




  68. void lanya()   //手机蓝牙控制
  69. {

  70. //        while(1)
  71. //        {
  72.                 key = read_data();//读取接收数据
  73.                 if(key == 'A') DA =0;//打开
  74.                 else if(key == 'B') DA =1;//关闭
  75.                 else if(key == 'C') DB =0;//打开
  76.                 else if(key == 'D') DB =1;//关闭
  77.                 else if(key == 'E') DC =0;//打开
  78.                 else if(key == 'F') DC =1;//关闭
  79.                 else if(key == 'G') DD =0;//打开
  80.                 else if(key == 'H') DD =1;//关闭
  81.                 else if(key == 'J') DE =0;//打开                                                                                            
  82.                 else if(key == 'K') DE =1;//关闭
  83.                 else if(key == 'M') DF =0;//打开
  84.                 else if(key == 'N') DF =1;//关闭
  85. //        }

  86. }      
  87. void ser()interrupt 4  //接收中断
  88. {
  89.         RI=0; //清除接收标志
  90.         buf[r_x] = SBUF;//接收数据至缓存区
  91.         r_x++;
  92.         if(buf[0]!='O'){r_x=0;}
  93.         if(r_x == 3)        //接收完成
  94.         {
  95.                 r_x=0;
  96.                 r_flag=1;
  97.         }

  98. }
  99. /********************************************************************
  100.                                                         定时器1函数
  101. *********************************************************************/
  102. void timer1init(void)//定时器1,16位方式2
  103. {        EA=0;
  104.         TMOD=0x11;//设置定时器0为工作方式1
  105.         TH0=(65536-10000)/256;
  106.         TL0=(65536-10000)%256;
  107.         ET0=1;//开定时器0中断
  108.         TR0=1;//启动定时器0
  109.         tt=0;//
  110.         EA=0;//关总中断
  111. }      
  112. /********************************************************************
  113.                                                 中断函数   
  114. *********************************************************************/
  115. void time0() interrupt 1
  116. {
  117.         TH0=(65536-50000)/256;
  118.         TL0=(65536-50000)%256;
  119.         tt++;
  120.         if(tt==10)
  121.         {tt=0; num++;
  122.         }
  123.         if((flag==2)&&(num==30))//布防时间,num=30即15秒,可以更改此实现布防延迟时间
  124.         flag=4;

  125.        
  126. }
  127. void  bufang()//布防函数     
  128. {            

  129. //        while(1)
  130. //        {
  131.                 if(flag==4)//如果布防时间到
  132.                 {
  133.                         tt=0;//清计数为0
  134.                         EA=0;//关中断
  135.                         num=0;//记的秒数清零
  136.                         flag=5;//flag等于5

  137.                 }      
  138.                 if(DF)//如果感应到人
  139.                
  140.                 DE =0;         //        播放第一首且不可触发
  141.                 else DE =1;
  142.                
  143.                 if(flag==5)//如果flag等于5
  144.                 {
  145.                         if(DF)//如果感应到人
  146.                         {
  147.                                 DE =0;
  148.                                 EA=1;//开中断

  149.                         }
  150.                 }
  151. //        }         
  152.        
  153. }

  154. /********************************************************************
  155.                                                         结束
  156. *********************************************************************/

复制代码


作者: lyl44    时间: 2020-3-1 18:22
死循环啊,当然不行
作者: lyl44    时间: 2020-3-1 18:24
把两个while都去掉
作者: lovexulu    时间: 2020-3-1 20:36
两个子函数中的while都去掉吧,三个while(1)!!
作者: zqy181818    时间: 2020-3-1 21:29
angmall 发表于 2020-3-1 18:22
给你改了,对比一下就知道哪里改了。

怎么不知道啊,那样不行的,你自己编译一下。
作者: zqy181818    时间: 2020-3-1 23:59
csmyldl 发表于 2020-3-1 17:23
被调用的子函数里均不能有while(1)无限循环,如果要有,可以加上时间的与,如while(time--),事先给time一个 ...

理论可行,可是蓝牙又不干事了。只有中断在努力。不知道是量沒给够还是什么。
作者: yxh1999    时间: 2020-3-2 09:01
void lanya()   //手机蓝牙控制这个函数不能要,把蓝牙的处理加在void ser()interrupt 4  中断函数里面。
void ser()interrupt 4  //½óêÕÖD¶Ï
{
   RI=0; //Çå3y½óêÕ±êÖ¾
   buf[r_x] = SBUF;//½óêÕêy¾YÖá»o′æÇø
   r_x++;
   if(buf[0]!='O'){r_x=0;}
   if(r_x == 3)        //½óêÕíê3é
   {
    r_x=0;
        r_flag=1;
   }
   if(r_flag==1)
   {
        r_flag=0;
        if(buf[2] == 'A') DA =0;//′ò¿a
        else if(buf[2] == 'B') DA =1;//1رÕ
        else if(buf[2] == 'C') DB =0;//′ò¿a
        else if(buf[2] == 'D') DB =1;//1رÕ
        else if(buf[2] == 'E') DC =0;//′ò¿a
        else if(buf[2] == 'F') DC =1;//1رÕ
        else if(buf[2] == 'G') DD =0;//′ò¿a
        else if(buf[2] == 'H') DD =1;//1رÕ
        else if(buf[2] == 'J') DE =0;//′ò¿a                                                                                            
        else if(buf[2] == 'K') DE =1;//1رÕ
        else if(buf[2] == 'M') DF =0;//′ò¿a
        else if(buf[2] == 'N') DF =1;//1رÕ
      
   }
}
蓝牙的功能,中断就处理完了。不需要在主函数里面去循环的查找
void lanya()   //êÖ»úà¶Ñà¿ØÖÆ
{
  uchar key=0;
  uart_init(); //′®¿ú3õê¼»ˉ
  
   
//  SPK=1;//·äÃùÆ÷1Ø
  DA=1;
  DB=1;
  DC=1;
  DD=1;
  DE=1;
  DF=1;
  
  
  void main()
  {
  DA=1;
  DB=1;                                                                                                                                                                                                                                                  
  DC=1;
  DD=1;
  DE=1;
  DF=1;
  uart_init();
             while(1)
           {
              //   lanya();  
         bufang();
                 }
                 
                    
         
         }
主函数去掉蓝牙检测函数。你这样去测试下,应该问题不大了。
作者: zqy181818    时间: 2020-3-3 00:06
lyl44 发表于 2020-3-1 18:22
死循环啊,当然不行

理解的
作者: zqy181818    时间: 2020-3-3 00:07
之一知足 发表于 2020-3-1 09:56
你两个子函数里都带着while(1),当然只能执行一个了,while(1)都没法跳出去,他只会按照默认顺序走第一 ...

你说的很对!
作者: zqy181818    时间: 2020-3-3 00:11
lyl44 发表于 2020-3-1 18:24
把两个while都去掉

直接去了是不行的
作者: zqy181818    时间: 2020-3-3 18:09
yxh1999 发表于 2020-3-2 09:01
void lanya()   //手机蓝牙控制这个函数不能要,把蓝牙的处理加在void ser()interrupt 4  中断函数里面。
...

你把蓝牙改了!,单独使用都成问题啊。更别说配合  bufang()运行了。
作者: yxh1999    时间: 2020-3-4 09:40
谢谢回复。又仔细看了下你的代码,觉得问题还是很多的。uchar flag=0;//这个变量你怎么处理的,没有哪里在自加跟自减,赋值0,时间中断里面等2的时候赋值4, bufang();函数里面判断4跟5,感觉你的 bufang();函数永远都不会起作用啊,因为这个变量一直都是0啊。我的解决思路就是串口判断你放在中断里面去执行, bufang();你放在主循环里面,这样 while(1)没啥关系。你要注意中断的开关, EA=0;//关中断关了后,你的串口中断也关闭了。串口中断你可以一直打开。时间中断你按自己的需要开关。
作者: zqy181818    时间: 2020-3-4 14:49
yxh1999 发表于 2020-3-4 09:40
谢谢回复。又仔细看了下你的代码,觉得问题还是很多的。uchar flag=0;//这个变量你怎么处理的,没有哪里在 ...

首先谢谢你!这么热情的回复。bufang();单独使用是可以用的。flag是个标志。4跟5放在程序,时间段的标志而已。判断就可以知道时间到哪了。不用自加跟自减的。《你要注意中断的开关, EA=0;//关中断关了后,你的串口中断也关闭了。》这句你说对了。。。bufang();调用是要注意 EA=0.l因为共用会有影响。
作者: haierzaifei11    时间: 2020-3-4 15:03
如果没有while功能没有了。更别说运行一个。
作者: yxh1999    时间: 2020-3-5 09:24
主要是我没有明白flag这个变量是怎么变化的。
    if((flag==2)&&(num==30))//布防时间,num=30即15秒,可以更改此实现布防延迟时间
           flag=4;
可以理解为flag等于2了才能触发flag等于4,后面的函数里面flag等于4了才能得到flag等于5.那flag怎么得到2的。那是不是说flag相关的代码都是没有用的了。是不是可以这样理解。
作者: zqy181818    时间: 2020-3-5 15:12
yxh1999 发表于 2020-3-5 09:24
主要是我没有明白flag这个变量是怎么变化的。
    if((flag==2)&&(num==30))//布防时间,num=30即15秒,可 ...

可以的。你明白就好。一时大意没有查到这个放标志程序没有复制过去。当时做程序要求上电就可以运行。后来才加上这个控件的,想在手机上控制的。合成后一直在考虑while问题。没有在意这个。现在主要问题是如何让他们同时运行。
作者: 萌新求带10086    时间: 2020-6-2 18:55
大佬可不可以分享一下电子幸运转盘的单片机程序阿 供学习使用




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1