找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机开发板串行中断if语句无法执行问题(看起来很简单,但程序怎么也调不过去)

[复制链接]
跳转到指定楼层
楼主
碰到一个看起来很简单的51单片机串行通信的问题,但折腾了两天了,怎么也调试不过去

1.目的:
使用郭天祥的开发版,实现串口送入0x01情况下,led灯闪烁的效果


2.代码如下:
void Usart() interrupt 4
{
unsigned char receiveData;
receiveData=SBUF;//出去接收到的数据
RI = 0;//清除接收中断标志位

//ledFlash();//放在外面单片机能够指挥外部小灯闪烁
if(receiveData==0x01)
{
ledFlash();
}

SBUF=receiveData;//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}


3.问题:
1)将实现led闪烁的函数 ledFlash()放在if语句之外直接执行,可以实现当字节到达时,直接闪烁的效果
2)但是,当将ledFlash()移到if 语句中,不知为什么,下载到单片机就无法实现小灯闪烁效果了,但是后面发送到stc-isp的缓冲区的程序仍然正常。如下图

4.尝试:
使用keil串口仿真调试,则当发送0x01时,能够进入 if 语句,正常执行ledFlash(),如图


请教大家,这个到底是怎么回事的,问题该如何解决啊

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

使用道具 举报

沙发
ID:781832 发表于 2022-12-5 12:00 | 只看该作者
连续发 0x01 看看是否能闪烁
回复

使用道具 举报

板凳
ID:1055764 发表于 2022-12-5 14:05 | 只看该作者
和楼上观点一样:连续发 0x01,看是否闪烁。
回复

使用道具 举报

地板
ID:30063 发表于 2022-12-5 16:27 | 只看该作者
连续发了,不闪烁
回复

使用道具 举报

5#
ID:30063 发表于 2022-12-5 19:17 | 只看该作者
northroom 发表于 2022-12-5 12:00
连续发 0x01 看看是否能闪烁

连续发了,还是不行
回复

使用道具 举报

6#
ID:301191 发表于 2022-12-6 05:48 | 只看该作者
顶一下
回复

使用道具 举报

7#
ID:213173 发表于 2022-12-6 07:27 | 只看该作者
问题当然在出在ledFlash()函数。放在串口中断里,每发生一次中断,if判断真后 ledFlash()函数只执行一次。放在主循环中就不同了,if判断真后只要receiveData没有变化, ledFlash()函数永久重复执行。
回复

使用道具 举报

8#
ID:308903 发表于 2022-12-6 08:37 | 只看该作者
if(receiveData==0x01)
{
ledFlash();
}
放到 while(!TI); //等待发送数据完成里面呢?
回复

使用道具 举报

9#
ID:384109 发表于 2022-12-6 08:42 | 只看该作者
代码不全,这类处理最好是放在主程序处理,而不是在中断里处理
回复

使用道具 举报

10#
ID:77589 发表于 2022-12-6 09:22 | 只看该作者
我严重怀疑,你是串口调试助手使用问题,可能选择了ASCII发送(这种情况下,单片机永远收不到0x01)。
应该切换到十六进制发送。
回复

使用道具 举报

11#
ID:30063 发表于 2022-12-7 10:05 | 只看该作者
wulin 发表于 2022-12-6 07:27
问题当然在出在ledFlash()函数。放在串口中断里,每发生一次中断,if判断真后 ledFlash()函数只执行一次。 ...

你好,抱歉,没大看明白,能否解释一下呢

另外,说一下项目的情况,我是想实现双机通信,另外一个设备通过串口发送信息,这台设备通过出口得到信息后进行动作(现在使用的ledFlash()就是这个简单效果,这个函数在主函数跑以及在没有if判断的这个串行接收中断函数中跑,都正常使得外部led闪烁,但是放到if语句就不执行了,感觉 if 语句中的布尔逻辑是TRUE,不知为什么)
回复

使用道具 举报

12#
ID:30063 发表于 2022-12-7 10:31 | 只看该作者
  1. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器

  2. typedef unsigned int u16;          //对数据类型进行声明定义
  3. typedef unsigned char u8;



  4. sbit led=P1^0;                 //将单片机的P2.0端口定义为led


  5. sbit beep=P2^3;         //蜂鸣器引脚


  6. /*******************************************************************************
  7. * 函 数 名         : delay
  8. * 函数功能                   : 延时函数,i=1时,大约延时10us
  9. *******************************************************************************/
  10. void delay(u16 i)
  11. {
  12.         while(i--);       
  13. }

  14. void ledFlash()
  15. {
  16.         int i=3;
  17.         while(i--)
  18.         {
  19.                 led=0;
  20.                 delay(50000); //大约延时450ms
  21.                 led=1;
  22.                 delay(50000); //大约延时450ms       
  23.         }               
  24. }


  25. void UsartInit()
  26. {
  27.         SCON=0X50;                        //设置为工作方式1
  28.         TMOD=0X20;                        //设置计数器工作方式2
  29.         PCON=0X80;                        //波特率加倍
  30.         TH1=0XF3;                                //计数器初始值设置,注意波特率是4800的
  31.         TL1=0XF3;
  32.         ES=1;                                                //打开接收中断
  33.         EA=1;                                                //打开总中断
  34.         TR1=1;                                        //打开计数器
  35. }


  36. void main()
  37. {       
  38.         UsartInit();  //        串口初始化
  39.         while(1);               
  40. }


  41. void Usart() interrupt 4
  42. {
  43.         u8 receiveData;
  44.         if(RI)
  45.         {
  46.          
  47.         receiveData=SBUF;//出去接收到的数据       
  48.         {
  49.          ledFlash();//
  50.         }
  51.         while(receiveData==0x01)
  52.        

  53.         RI = 0;//清除接收中断标志位

  54.   }
  55. }
复制代码

C:\Users\DELL\Pictures\3.png
这个可以执行,不知道为什么?
但是同时出现了2个问题:
1.是ledFlash()函数只让led闪烁3次,但是在这个函数执行过程中,小灯却一直闪烁,退不出来了,这是为什么?
2.是while语句放在前面,{}中的flashLed()又不执行了,这个真不懂了
C:\Users\DELL\Pictures\4.png
求教
回复

使用道具 举报

13#
ID:30063 发表于 2022-12-7 10:34 | 只看该作者
1261867136qq 发表于 2022-12-6 08:37
if(receiveData==0x01)
{
ledFlash();

完整代码如下:
  1. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器

  2. typedef unsigned int u16;          //对数据类型进行声明定义
  3. typedef unsigned char u8;



  4. sbit led=P1^0;                 //将单片机的P2.0端口定义为led


  5. sbit beep=P2^3;         //蜂鸣器引脚


  6. /*******************************************************************************
  7. * 函 数 名         : delay
  8. * 函数功能                   : 延时函数,i=1时,大约延时10us
  9. *******************************************************************************/
  10. void delay(u16 i)
  11. {
  12.         while(i--);       
  13. }

  14. void ledFlash()
  15. {
  16.         int i=3;
  17.         while(i--)
  18.         {
  19.                 led=0;
  20.                 delay(50000); //大约延时450ms
  21.                 led=1;
  22.                 delay(50000); //大约延时450ms       
  23.         }               
  24. }


  25. void UsartInit()
  26. {
  27.         SCON=0X50;                        //设置为工作方式1
  28.         TMOD=0X20;                        //设置计数器工作方式2
  29.         PCON=0X80;                        //波特率加倍
  30.         TH1=0XF3;                                //计数器初始值设置,注意波特率是4800的
  31.         TL1=0XF3;
  32.         ES=1;                                                //打开接收中断
  33.         EA=1;                                                //打开总中断
  34.         TR1=1;                                        //打开计数器
  35. }


  36. void main()
  37. {       
  38.         UsartInit();  //        串口初始化
  39.         while(1);               
  40. }


  41. void Usart() interrupt 4
  42. {
  43.         u8 receiveData;
  44.         if(RI)
  45.         {
  46.          
  47.         receiveData=SBUF;//出去接收到的数据       

  48.          
  49.         {
  50.          ledFlash();//
  51.         }
  52.         while(receiveData==0x01)

  53.         RI = 0;//清除接收中断标志位

  54.   }
  55. }
复制代码

代码可以执行,led闪烁,
但是,出现了2个问题:
1.小灯一直闪烁,停不下来了
2.采用while提前,又不执行了
  1. void Usart() interrupt 4
  2. {
  3.         u8 receiveData;
  4.         if(RI)
  5.         {
  6.          
  7.         receiveData=SBUF;//出去接收到的数据       

  8.            while(receiveData==0x01)
  9.         {
  10.          ledFlash();//
  11.         }
  12.          

  13.         RI = 0;//清除接收中断标志位

  14.   }
复制代码

不知道这是怎么回事
回复

使用道具 举报

14#
ID:213173 发表于 2022-12-7 11:46 | 只看该作者
goodshot 发表于 2022-12-7 10:05
你好,抱歉,没大看明白,能否解释一下呢

另外,说一下项目的情况,我是想实现双机通信,另外一个设备 ...

不知道你的ledFlash()函数的具体代码,但放在串口中断中运行肯定是不当的,LED闪烁是需要在一定的时间范围完成,而串口中断函数是不能把占用较长时间的LED闪烁函数放进去。串口中断只能根据收到的信息经判断输出一个标志并立即退出函数。主函数根据这个标志调用指定的子函数。
void Usart() interrupt 4
{
        unsigned char receiveData;
        receiveData=SBUF;//获取接收到的数据
        RI = 0;//清除接收中断标志位
        if(receiveData==0x01)//判断是真
        {
                flag=1;//标志置1
        }
        else
        {
                flag=0;//标志清0
        }
}
如果主函数中要持续执行
        if(flag)
        {
                ledFlash();
        }

如果主函数中只要执行1次
        if(flag)
        {
                flag=0;
                ledFlash();
        }
回复

使用道具 举报

15#
ID:401564 发表于 2022-12-7 17:20 | 只看该作者
在中断中最好不要使用while
也不要在中断调用延时时间过长的函数
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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