找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于不支持在线仿真的单片机的单线单工通信接收函数的问题

[复制链接]
跳转到指定楼层
楼主
ID:540927 发表于 2020-8-26 08:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我现在在做一个单线单工通信的程序,但是单片机不支持在线仿真,接收函数如下:
void Receive()                                 //接收函数,接收5byte数据,先接收低位再接收高位
{
CHAR Temp;
if((time1 > 40)&&(time1 < 60))               //新的引导码开始退出接收函数
{
  Temp = 0;
  beginflag = 0;
}
if((time1 > 0)&&(time1 < 5))                 //数据位低电平所在范围
{
  BitNum++;
  time1 = 0;
  lowflag = 1;                       //低电平信号标志
}
else if((time1 >= 5)&&((time1 <=40)||(time1 >= 60)))
{
  
  time1 = 0;
  Temp = 0;
  beginflag = 0;                                            //数据出错退出接收
}
if(lowflag == 1)                               //每一位的低电平接收成功则接收高电平
{
  if((time2 > 0)&&(time2 < 5))           //数据位0信号
  {
   time2 = 0;
   Bit = 0;
  }
  else if((time2 > 8)&&(time2 < 14))           //数据位1信号
  {
   time2 = 0;
   Bit = 1;
  }
  else if((time2 >= 5)&&((time2 <= 8)||(time2 >= 14)))
  {
   
   time2 = 0;
   Temp = 0;
   beginflag = 0;                                  //数据出错退出接收
  }
  Temp |= (Bit << (BitNum - 1));                   //把所在位的数据存入
  lowflag = 0;
  if(BitNum >= 8)                                   //1byte数据接收完之后存入     
    {
   ByteNum++;
   switch(ByteNum)
   {
    case 1: {NewByte1 = Temp; Temp = 0;break;}
    case 2: {NewByte2 = Temp; Temp = 0;break;}
    case 3: {NewByte3 = Temp; Temp = 0;break;}
    case 4: {NewByte4 = Temp; Temp = 0;break;}
    case 5: {NewByte5 = Temp; Temp = 0;break;}
    default : break;
   }
      BitNum = 0;
      
   if(ByteNum >= 5)                             //5byte数据接收完进行数据处理
      {
   
        ByteNum = 0;
    beginflag = 0;                         //接收完毕标志置0
    dataflag = 1;                         //数据处理标志
   }
  }
}
}

在调试过程中,我不能知道NewByte1,NewByte2,NewByte3,NewByte4,NewByte5的具体值,只能直接烧录在板子上验证,但是结果不成功。我已经确认了这个函数一直能运行到完,只能说明接收到的数据不正确。请问有什么办法可以知道这几个数据的具体值是多少?不支持在线仿真的单片机调试有技巧吗?我的这个函数有什么问题?请大家帮帮我吧,谢谢!
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:739545 发表于 2020-8-26 10:33 | 只看该作者
有LCD显示的话,把你需要看的数据实时在LCD上显示出来,或者有串口的话,把debug的数据用串口传输看结果。很多情况下都是没有在线仿真的。都是在线检查
回复

使用道具 举报

板凳
ID:654028 发表于 2020-8-26 11:48 | 只看该作者
串口通信?或者其他方式,比如收到什么数据做什么事情,比较容易观察的
回复

使用道具 举报

地板
ID:540927 发表于 2020-8-26 12:27 | 只看该作者
lovezjf234 发表于 2020-8-26 10:33
有LCD显示的话,把你需要看的数据实时在LCD上显示出来,或者有串口的话,把debug的数据用串口传输看结果。 ...

感谢你的回复,我这个是单线通信的,没有用到串口板上也没有LCD,所以比较难办
回复

使用道具 举报

5#
ID:540927 发表于 2020-8-26 12:31 | 只看该作者
心有浮生 发表于 2020-8-26 11:48
串口通信?或者其他方式,比如收到什么数据做什么事情,比较容易观察的

感谢您的回复,我的这个不是串口通信而是单线通信,就是收到数据进行处理可以在板子上验证,但是就是因为不能成功,我才想知道接收到的具体数据,或者说我的接收函数是不是正确的
回复

使用道具 举报

6#
ID:540927 发表于 2020-8-26 13:10 | 只看该作者
lovezjf234 发表于 2020-8-26 10:33
有LCD显示的话,把你需要看的数据实时在LCD上显示出来,或者有串口的话,把debug的数据用串口传输看结果。 ...

谢谢您,确实可以自己做串口通信到电脑看结果,这个对不能在线仿真的单片机来说确实是个好办法
回复

使用道具 举报

7#
ID:804115 发表于 2020-8-26 13:58 | 只看该作者
你这个是底层信号接收,对时序要求比较严格,用串口debug和lcd显示都不行,因为都比较耗时。
你可以用一个没有用的io来调试,因为IO翻转耗费的时间比较少。你可以将此io接到一个灯上用于指示。
另外,你可以通过示波器或者逻辑分析仪抓取发送端的发送时序,看看发送端是否符合要求,再分析你的接收端是否匹配。
回复

使用道具 举报

8#
ID:540927 发表于 2020-8-26 15:19 | 只看该作者
1692483014 发表于 2020-8-26 13:58
你这个是底层信号接收,对时序要求比较严格,用串口debug和lcd显示都不行,因为都比较耗时。
你可以用一个 ...

感谢您的回复,我调试的时候也是把一个引脚置1输出,然后一步一步看程序可以执行到哪,但是在使用数据处理的时候出了问题,所以我需要了解接收的数据怎么了
回复

使用道具 举报

9#
ID:230118 发表于 2020-8-26 15:24 | 只看该作者
逻辑分析仪或示波器最简单直观,没有的话,可以尝试按比例把通讯时隙按比例放大若干倍(以保证肉眼能观察到led变化),接收端用指示灯来指示接收数据位的变化
回复

使用道具 举报

10#
ID:540927 发表于 2020-8-26 17:19 | 只看该作者
bro0310 发表于 2020-8-26 15:24
逻辑分析仪或示波器最简单直观,没有的话,可以尝试按比例把通讯时隙按比例放大若干倍(以保证肉眼能观察到l ...

感谢您的回复,接收端我可以用示波器测到波形的,关键是单片机中的程序处理不知道是不是错了
回复

使用道具 举报

11#
ID:230118 发表于 2020-8-26 19:54 | 只看该作者
你这个通讯方式和NEC红外协议很类似,既然是单线单工,你的引导码和数据应该是读的同一个引脚,那么time1,time2是同一个引脚的电平持续时间,对吗?要找到问题,我的思路是这样的,仅供参考:
1  根据你的晶振精度,以及系统中有无其它优先级更高的中断影响通讯时序,合理设计0、1bit的时序特征,提高容错性,比方说3~10us低电平后接10~20us高电平代表0; 10~18us低电平厚街3~10us高电平代码1;
2  由于时序要求比较高,发送端的延时最好用定时器来做
3  示波器测量输出端时序,比方说你发送数据0x55,确认发送端的输出时序和你的协议设计相符
4  接收端用定时器的输入捕获功能来测量电平时间
中断服务程序
void Capture_ISR (void)
{
    // 读取timer寄存器时间time
    if (!receive_flag)
    {
        receive(time);
    }
}


void receive(uint16_t Capture_Time )
{
    if(IR_State == 0)
    {
        IR_LDC_Ready = 0;           // Clear LeaDer Code Ready
        IR_State=1;
    }
    // Leader or Repeater code
    else if(IR_State == 1)
    {
        // Leader code
        if((Capture_Time >= IR_LDC_MIN) && (Capture_Time <= IR_LDC_MAX))
        {
            IR_LDC_Ready = 1;       // Set LeaDer Code Ready
            IR_State++;
        }
        else
        {
            IR_State = 1;
            IR_LDC_Ready = 0;           // Clear LeaDer Code Ready
        }
    }
      // Data
    else if((IR_State >= 2 && IR_State < 10) && (IR_LDC_Ready == 1))
    {
        IR_State++;
        NewByte1 = NewByte1 >> 1;
        if((Capture_Time >= IR_BIT_0_MIN) && (Capture_Time <= IR_BIT_0_MAX))
            NewByte1 &= 0x7f;
        else if((Capture_Time >= IR_BIT_1_MIN) && (Capture_Time <= IR_BIT_1_MAX))
            NewByte1 |= 0x80;
        else
            IR_State = 0;
    }
    else if((IR_State >= 10 && IR_State < 18) && (IR_LDC_Ready == 1))
    {
        IR_State++;
        NewByte2 = NewByte2 >> 1;
        if((Capture_Time >= IR_BIT_0_MIN) && (Capture_Time <= IR_BIT_0_MAX))
            NewByte2 &= 0x7f;
        else if((Capture_Time >= IR_BIT_1_MIN) && (Capture_Time <= IR_BIT_1_MAX))
            NewByte2 |= 0x80;
        else
            IR_State = 0;
    }
    else if((IR_State >= 18 && IR_State < 26) && (IR_LDC_Ready == 1))
    {
        IR_State++;
        NewByte3= NewByte3>> 1;
        if((Capture_Time >= IR_BIT_0_MIN) && (Capture_Time <= IR_BIT_0_MAX))
            NewByte3&= 0x7f;
        else if((Capture_Time >= IR_BIT_1_MIN) && (Capture_Time <= IR_BIT_1_MAX))
            NewByte3|= 0x80;
        else
            IR_State = 0;
    }
    else if((IR_State >= 26 && IR_State < 34) && (IR_LDC_Ready == 1))
    {
        IR_State++;
        NewByte4= NewByte4>> 1;
        if((Capture_Time >= IR_BIT_0_MIN) && (Capture_Time <= IR_BIT_0_MAX))
            NewByte4&= 0x7f;
        else if((Capture_Time >= IR_BIT_1_MIN) && (Capture_Time <= IR_BIT_1_MAX))
            NewByte4|= 0x80;
        else
            IR_State = 0;
    }
    else if((IR_State >= 34 && IR_State < 42) && (IR_LDC_Ready == 1))
    {
        IR_State++;
        NewByte5= NewByte5>> 1;
        if((Capture_Time >= IR_BIT_0_MIN) && (Capture_Time <= IR_BIT_0_MAX))
            NewByte5&= 0x7f;
        else if((Capture_Time >= IR_BIT_1_MIN) && (Capture_Time <= IR_BIT_1_MAX))
            NewByte5|= 0x80;
        else
            IR_State = 0;
    }

        if(IR_State == 42)
        {
            IR_LDC_Ready = 0;   // Clear LeaDer Code Ready
            received_flag= 1;
            IR_State = 0;
        }
}

评分

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

查看全部评分

回复

使用道具 举报

12#
ID:213173 发表于 2020-8-26 20:06 | 只看该作者
其实可以参照ds18b20温度传感器的单总线通讯方式完成异步串行通讯,如果只是单向传输就更简单了。
回复

使用道具 举报

13#
ID:540927 发表于 2020-8-27 08:13 | 只看该作者
bro0310 发表于 2020-8-26 19:54
你这个通讯方式和NEC红外协议很类似,既然是单线单工,你的引导码和数据应该是读的同一个引脚,那么time1,t ...

感谢您详细的回复,我会参考您提供的办法试图解决问题的,不过由于接收端的单片机功能比较少,没有输入捕获功能,很遗憾呢
回复

使用道具 举报

14#
ID:540927 发表于 2020-8-27 08:15 | 只看该作者
wulin 发表于 2020-8-26 20:06
其实可以参照ds18b20温度传感器的单总线通讯方式完成异步串行通讯,如果只是单向传输就更简单了。

感谢您的回复,我也参考了这个,同时还参考了红外解调,后来我想要自己的方法编程,可惜不尽如意
回复

使用道具 举报

15#
ID:176854 发表于 2020-8-27 16:29 | 只看该作者
TB买一个串行数码管,用数码管显示接收值。
飞线也就4、5根。
回复

使用道具 举报

16#
ID:540927 发表于 2020-8-28 09:45 | 只看该作者
jjjjjjir 发表于 2020-8-27 16:29
TB买一个串行数码管,用数码管显示接收值。
飞线也就4、5根。

好主意呢,不错,谢谢啦
回复

使用道具 举报

17#
ID:540927 发表于 2020-8-28 11:08 | 只看该作者
lovezjf234 发表于 2020-8-26 10:33
有LCD显示的话,把你需要看的数据实时在LCD上显示出来,或者有串口的话,把debug的数据用串口传输看结果。 ...

不好意思了,前天尝试了用串口通信到电脑上看数据,结果昨天一整天单片机引脚检测不到电平信号,我换了好多器件都没解决,今天我才发现,我的串口就是输入信号的接口,再做串口通信就冲突了
回复

使用道具 举报

18#
ID:540927 发表于 2020-8-28 11:50 | 只看该作者
jjjjjjir 发表于 2020-8-27 16:29
TB买一个串行数码管,用数码管显示接收值。
飞线也就4、5根。

感谢您的建言,果然是个好方法的,我会参考的,谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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