6257|12

144

帖子

2

TA的资源

一粒金砂(高级)

楼主
 

上下位机串口通信遭遇的问题 [复制链接]

labview上位机向单片机发送一组字符串:单字符0、单字符1、单字符2、单字符3、单字符4;其中单字符0固定为a;
      单字符1在上位机中可通过下拉列表控件编辑5个选项:a b c d e
      单字符2在上位机中可通过下拉列表控件编辑5个选项:a b c d e
      单字节3固定为回车符
      单字节4固定为换行符。
比如单字符1选择为a,单字符2选择为e,则此时,上位机向单片机发送的字符串为:
aae回车符换行符,该组字符对应的十六进制分别为:0x61 0x61 0x65 0x0D 0x0A。


上位机向单片机发送字符串时,产生串口中断,单片机开始接收数据:0x61,0x61,0x65,
并在遇到0x0D时不再接收数据,且在遇到0x0A时关闭串口中断。
即单片机只接收了前三个字符:a a e,并保存在unsigned char USART_RX_BUF[3]中。
即USART_RX_BUF[0]=0x61,USART_RX_BUF[1]=0x61,USART_RX_BUF[2]=0x65;
在单片机程序中有如下选择语句:
switch(USART_RX_BUF[1])
{
        case 'a':Start_Frequency=25;break;
        case 'b':Start_Frequency=26;break;
        case 'c':Start_Frequency=27;break;
        case 'd':Start_Frequency=28;break;
        case 'e':Start_Frequency=29;break;
        default:break;
}
switch(USART_RX_BUF[2])
{
    case 'a':End_Frequency=29;break;
        case 'b':End_Frequency=30;break;
        case 'c':End_Frequency=31;break;
        case 'd':End_Frequency=32;break;
        case 'e':End_Frequency=33;break;
        default:break;
}

上文有提到,单字符1和单字符2可通过上位机的下拉列表输入控件实现多种选择,最终
是为了实现Start_Frequency和End_Frequency的多个选择。
单片机程序main.c中主要的功能是测量温度和幅度,然后将温度和幅度数据上传给上位机。

在调试过程中,让我疑惑不解的是:比如
(1)通过上位机向单片机发送字符串:aae回车符换行符,单片机接收前3个字符,所以有
     USART_RX_BUF[0]=0x61,USART_RX_BUF[1]=0x61,USART_RX_BUF[2]=0x65;
     此时的Start_Frequency=25,End_Frequency=33;
     但是单片机上传给上位机的数据明显不对;
(2)如果在单片机中直接初始化USART_RX_BUF[3],即
    USART_RX_BUF[0]=0x61,USART_RX_BUF[1]=0x61,USART_RX_BUF[2]=0x65;
    此时的Start_Frequency当然仍是25,End_Frequency也是33;
    这个时候单片机上传给上位机的数据才是正确的。
原因在哪里呢?
我有考虑过上面的switch(USART_RX_BUF[1])和switch(USART_RX_BUF[2]),会不会以为串口
多次收发过程中,会改变第一次收到的UASRT_RX_BUF[1]和USART_RX_BUF[2]的值,从而导致
后面的Start_Frequency和End_Frequency的设置改变。
如果是这样的话,我我应该怎样保存我第一次收到的UASRT_RX_BUF[1]和UASRT_RX_BUF[2],
来保证这两个数据不管串口通信如何进行收发,都不会改变呢?
之所以会有这样的考虑,是因为在多次调试过程中,发现,只要UASRT_RX_BUF[1]和
UASRT_RX_BUF[2]在main函数一开始就直接初始化,而不通过上位机串口通信来设置,
上位机上的数据就总是对的。
一旦通过上位机来控制UASRT_RX_BUF[1]和UASRT_RX_BUF[2],上位机的程序就完全不对。


这就是我目前的困难,坛友们有什么建议吗?求指教!谢谢






此帖出自stm32/stm8论坛

最新回复

很意外的发现:串口调试助手第一次虽然发送的是:41 61 65 0D 0A 但单片机返回的并不是41 61 65 0D 0A,而是00 00 00 00 00。复制代码这部分可以在认真查找一下单片机的程序,会什么返回的是 0. 不客气哦,加油,看你写贴还用颜色标注,说明你是一个很认真的人,保持这样的好习惯。   详情 回复 发表于 2014-12-3 16:59
点赞 关注
 

回复
举报

144

帖子

2

TA的资源

一粒金砂(高级)

沙发
 
之前我使用过一个Switch(UASRT_RX_BUF[0]),只通过判断单字符0来实现Start_Frequency和End_Frequency的多种设置,上位机上的数据显示是正确的。难道这两个switch语句有问题吗?

此帖出自stm32/stm8论坛
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

板凳
 
也就是说,到底是下位机接收的USART_RX_BUF[1]和USART_RX_BUF[2]有问题?还是上述的两个switch语句有问题?
此帖出自stm32/stm8论坛
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

4
 
刚刚重新试了一下,发现在串行通信最开始的时候,也就是最开始上位机接收到的数据是正确的,但是很快就不对了。我个人觉得还是USART_RX_BUF[1]和USART_RX_BUF[2]的问题,但具体到底是什么问题,我还不太清楚。最有可能的应该是串口通信过程中数据不断被改变导致USART_RX_BUF[1]、USART_RX_BUF[2]会发生变更。
此帖出自stm32/stm8论坛
 
 
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

5
 
我觉得楼主你的思路已经有点开始混乱了,但你开始混乱的时候,你需要抽丝剥茧,逐个查找。
这个问题,我觉得你可以分开来测试。
测试单片机数据是否正常:在 PC 上用串口调试助手,模拟你的上位机发送数据,看回来的数据到底是什么。
测试上位机数据发送是否正常:可以在 PC 开一对虚拟串口,我一般用 com0com,用上位机连接到其中之一,用串口调试助手连接另一个,测试看上位机对数据的接收和发送是否有问题。
多做一些测试,问题自然就找到了。
此帖出自stm32/stm8论坛

点评

恩,确实有点混乱,找不到问题所在,有些着急了。不过,真的很谢谢版主们的帮忙!  详情 回复 发表于 2014-12-3 16:36
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

6
 
如果原因是USART_RX_BUF[1]和USART_RX_BUF[2],那到底是上位机没发送好,还是下位机没接收好?刚刚对上位机的各个阶段的数据进行监控,发现上位机确实发送好了。难道真的是下位机没有接收好?可是,下位机接收的数据不对,不对在哪里?
此帖出自stm32/stm8论坛

点评

判断下位机有没有接收好,你可以写个简单的 if elseif 来逐个字节地判断,然后设置断点,判断一下。  详情 回复 发表于 2014-12-3 10:33
 
 
 

回复

4997

帖子

19

TA的资源

裸片初长成(初级)

7
 
涉及到与串口通信的项目,必须分为两步完成,一就是单片机与串口调试软件,保证单片机收发都是增强的,因为串口调试软件是一定不会错的;二才是用单片机与自己的上位机软件通过。

一就是说,必须要保证一方决定正确,才好找原因。
此帖出自stm32/stm8论坛

点评

谢谢  详情 回复 发表于 2014-12-3 16:33
 
个人签名我的博客
 
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

8
 
qiwan 发表于 2014-12-3 10:15
如果原因是USART_RX_BUF[1]和USART_RX_BUF[2],那到底是上位机没发送好,还是下位机没接收好?刚刚对上位机 ...
判断下位机有没有接收好,你可以写个简单的 if elseif 来逐个字节地判断,然后设置断点,判断一下。

此帖出自stm32/stm8论坛

点评

谢谢帮忙!  详情 回复 发表于 2014-12-3 16:34
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

9
 
超级感谢两位版主的帮忙,一直在纠结上位机和下位机的通信问题,却忘记了得力的串口调试助手。
(1)用串口调试助手向单片机发送字符串:Aae回车符换行符,十六进制显示为:41 61 65 0D 0A
    得到的数据是这样的:
串口调试助手第一次发送上述字符串,单片机第一次返回的数据:
41 15 19 4D 00 4E
    15 19 4D 00 4E
    15 19 4D 00 4E
    00 00 00 00 00
    19 21 C8 00 00 00 80
串口调试助手第二次发送上述字符串,单片机第二次返回的数据:
41 15 19 4D 00 4E
   15 19 4D 00 4E
   15 19 4D 00 4E
   41 61 65 0D 0A
   19 21 C8 00 00 00 80
串口调试助手第三次发送上述字符串,单片机第三次返回的数据:
41 15 19 4D 00 4E
   15 19 4D 00 4E
   15 19 4D 00 4E
   41 61 65 0D 0A
   19 21 C8 00 00 00 80

——————————————————————————————
上面标红的数据:串口调试助手给单片机发送数据,单片机一旦接收到
数据,就将接收到的数据保存在字符数组USART_RX_BUF[5]中,并返回给
串口调试助手。
很意外的发现:串口调试助手第一次虽然发送的是:41 61 65 0D 0A
但单片机返回的并不是41 61 65 0D 0A,而是00 00 00 00 00。
而程序接下来执行并返回给助手的数据全部是错误的。
(2)接下来不用串口调试助手发送数据,而是直接在main函数的while(1)的一开始
就字节直接初始化USART_RX_BUF[5]:
  while(1)
    {

  USART_RX_BUF[0]=65;   // 0x41
  USART_RX_BUF[1]=97;  //0x61
  USART_RX_BUF[2]=101;//0x65
  USART_RX_BUF[3]=13;//0x0D
  USART_RX_BUF[4]=10;//0x0A

            ...
            ...
            ...
    }
单片机第一次返回的数据为:
41 16 21 19 00 51
   15 19 38 00 4F
   16 11 D0 00 4C
   41 61 65 0D 0A
   19 21 C8 00 00 00 80

___________________________________
程序执行下来所有的数据都是我期望的。
***************************************
也就是说,在用串口调试助手时发现,单片机返回我所期望的数据,需要满足:
上位机发送了   41 61 65 0D 0A,第一次返回的也必须是41 61 65 0D 0A.
否则,即使第二次第三次第n次返回的值是41 61 65 0D 0A,
返回的值都是正确的,但第一次返回的值不对,都是徒劳的。
于是,我就在while(1)中加了一个判断语句:
    while(1)
    {

        data[15]=USART_RX_BUF[0];
        data[16]=USART_RX_BUF[1];
        data[17]=USART_RX_BUF[2];
        data[18]=USART_RX_BUF[3];
        data[19]=USART_RX_BUF[4];
        if((data[15]!=0)&&(data[16]!=0)&&(data[17]!=0)&&(data[18]!=0)&&(data[19]!=0))
        {
               ...
        }
              ...
}       

因为第一次返回的数值是00 00 00 00 00,既然不对,那我就放弃不要了,
第二次返回的数值是 41 61 65 0D 0A,那么就从第二次开始,程序接着往下执行。
于是,结果就对了。
下午的调试过程就是这样的。
很感谢两位版主的提醒,谢谢!
至于第一次返回的值为什么是00 00 00 00 00,我觉得可能是单片机还没来得及读
串口调试助手发送来的数据,就直接给助手返回数据了。
此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

10
 
谢谢
zhaojun_xf 发表于 2014-12-3 10:31
涉及到与串口通信的项目,必须分为两步完成,一就是单片机与串口调试软件,保证单片机收发都是增强的,因为串口调试软件是一定不会错的;二才是用单片机与自己的上位机软件通过。

一就是说,必须要保证一方决定正确,才好找原因。

此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

11
 
谢谢帮忙!
Study_Stellaris 发表于 2014-12-3 10:33
判断下位机有没有接收好,你可以写个简单的 if elseif 来逐个字节地判断,然后设置断点,判断一下。

此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

12
 
恩,确实有点混乱,找不到问题所在,有些着急了。不过,真的很谢谢版主们的帮忙!
Study_Stellaris 发表于 2014-12-3 10:12
我觉得楼主你的思路已经有点开始混乱了,但你开始混乱的时候,你需要抽丝剥茧,逐个查找。
这个问题,我觉得你可以分开来测试。
测试单片机数据是否正常:在 PC 上用串口调试助手,模拟你的上位机发送数据,看回来的数据到底是什么。
测试上位机数据发送是否正常:可以在 PC 开一对虚拟串口,我一般用 com0com,用上位机连接到其中之一,用串口调试助手连接另一个,测试看上位机对数据的接收和发送是否有问题。
多做一些测试,问题自然就找到了。

此帖出自stm32/stm8论坛

点评

这部分可以在认真查找一下单片机的程序,会什么返回的是 0. 不客气哦,加油,看你写贴还用颜色标注,说明你是一个很认真的人,保持这样的好习惯。  详情 回复 发表于 2014-12-3 16:59
 
 
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

13
 
qiwan 发表于 2014-12-3 16:36
恩,确实有点混乱,找不到问题所在,有些着急了。不过,真的很谢谢版主们的帮忙!
  1. 很意外的发现:串口调试助手第一次虽然发送的是:41 61 65 0D 0A
  2. 但单片机返回的并不是41 61 65 0D 0A,而是00 00 00 00 00。
复制代码
这部分可以在认真查找一下单片机的程序,会什么返回的是 0.
不客气哦,加油,看你写贴还用颜色标注,说明你是一个很认真的人,保持这样的好习惯。

此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表