查看: 425|回复: 12

[未解决] UART 传输(字符)不稳定,如何解决数据错位和乱码的情况

[复制链接]
  • TA的每日心情
    难过
    2019-3-22 16:57
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2019-3-22 16:57 | 显示全部楼层 |阅读模式
    本帖最后由 tommyjtl 于 2019-3-22 17:09 编辑

    求助大家,我正在写一个 UART 传输多组数据的项目,想要将一端 Arduino 的多组数据通过 UART 的方式传输到 ESP8266 上,比如:4 组按钮、1 个旋钮、1 串字符。目前传是能够传了,能发送也能接收,但就是总是不稳定,会有错位的情况,我尝试把发送端的速度调慢一点(延迟 250ms、500ms),但还是会有错位的情况,有人知道这是为什么吗?
    出现错位和乱码的情况(视频 ),前往这个链接查看:https://transfer.sh/yNZLp/Mar-22-2019%2016-54-44.mp4

    正常获取数据的时候: (传输的是 6 组数据,最后一个数据是文字)
    Screen Shot 2019-03-22 at 17.01.28.png
    获取数据不稳定的时候: Screen Shot 2019-03-22 at 17.01.21.png

    下面是我现在的代码:(这里我的 Arduino 是 Arduino Leonardo,所以 UART 会用到 Serial1)

    发送端

    kittenblock中小学创客名师推荐的图形化编程软件

    
    void setup() {
      pinMode(8, INPUT);
      pinMode(9, INPUT);
      pinMode(12, INPUT);
      pinMode(13, INPUT);
      pinMode(A3, INPUT);
    
      Serial.begin(9600);
      Serial1.begin(9600);
    }
    
    void loop() {
      serialSendData();
    }
    
    
    // new transfer (send) method below:
    
    void serialSendData() {
      char dataBuf[dataPackage().length() + 1]; // or strlen()?
      dataPackage().toCharArray(dataBuf, dataPackage().length() + 1);
    
      // Serial.println(dataBuf);
      Serial1.write(dataBuf);
      delay(250);
    }
    
    String dataPackage() {
      String data = "";
      data += digitalRead(8);
      data += "|";
      data += digitalRead(9);
      data += "|";
      data += digitalRead(12);
      data += "|";
      data += digitalRead(13);
      data += "|";
      data += analogRead(A3);
      data += "|";
      data += "hello arduino";
      data += "\n";
      return data;
    }
    


    接收端:

    kittenblock中小学创客名师推荐的图形化编程软件

    
    String readString;
    String incomingDataPack;
    String dataPackage;
    
    void setup() {
      Serial.begin(9600);
      Serial1.begin(9600);
    }
    
    void loop() {
      serialReceiveData();
    
      // Serial.println(dataPackage);
    
      Serial.print(getValue(dataPackage, '|', 0));
      Serial.print("\t");
      Serial.print(getValue(dataPackage, '|', 1));
      Serial.print("\t");
      Serial.print(getValue(dataPackage, '|', 2));
      Serial.print("\t");
      Serial.print(getValue(dataPackage, '|', 3));
      Serial.print("\t");
      Serial.print(getValue(dataPackage, '|', 4));
      Serial.print("\t");
      Serial.println(getValue(dataPackage, '|', 5));
    }
    
    // new transfer (receive) method below:
    
    void serialReceiveData() {
      while (Serial1.available() > 0)
      {
        char received = Serial1.read();
        incomingDataPack += received;
        // Process message when new line character is recieved
        if (received == '\n')
        {
          // Serial.print(incomingDataPack);
          dataPackage = incomingDataPack;
          incomingDataPack = ""; // Clear recieved buffer
        }
    
      }
    
      Serial1.flush();
      Serial.flush();
    }
    
    String getValue(String data, char separator, int index)
    {
      int found = 0;
      int strIndex[] = {0, -1};
      int maxIndex = data.length() - 1;
    
      for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i + 1 : i;
        }
      }
    
      return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
    }
    
    








  • TA的每日心情
    奋斗
    2019-3-3 00:05
  • 签到天数: 40 天

    [LV.5]常住居民I

    发表于 2019-3-22 22:38 | 显示全部楼层
    发送端第21、22行,两次调用 dataPackage().length() 返回的结果可能不一样。
    举个例子:第一次调用 length() 时第39行 analogRead(A3) 读到了 11,
    而第二次调用 length() 时读到了 1023,这样第二次返回结果比第一次要大2.

    上述过程很要命,会导致 dataBuf 在转换时(发送端22行)长度超出,数组越界。
    本来挺简单的事情搞复杂了,第25行 Serial1.print(dataPackage()) 不行么?
  • TA的每日心情
    难过
    2019-3-22 16:57
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2019-3-23 13:59 | 显示全部楼层
    t3486784401 发表于 2019-3-22 22:38
    发送端第21、22行,两次调用 dataPackage().length() 返回的结果可能不一样。
    举个例子:第一次调用 length ...

    你的意思是,如果我把「+1」 去除,是否就可以避免这种情况发生了?
  • TA的每日心情
    奋斗
    2019-3-3 00:05
  • 签到天数: 40 天

    [LV.5]常住居民I

    发表于 2019-3-23 14:02 | 显示全部楼层
    tommyjtl 发表于 2019-3-23 13:59
    你的意思是,如果我把「+1」 去除,是否就可以避免这种情况发生了?

    我的意思是你不该调两次 length() 方法。
    正确应该是只调用一次,用变量缓存起来。
  • TA的每日心情
    难过
    2019-3-22 16:57
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2019-3-23 14:22 | 显示全部楼层
    t3486784401 发表于 2019-3-23 14:02
    我的意思是你不该调两次 length() 方法。
    正确应该是只调用一次,用变量缓存起来。 ...

    那应该怎么缓存呢?直接这样吗:

    kittenblock中小学创客名师推荐的图形化编程软件

    int dataPackageLength = dataPackage().length() + 1;
  • TA的每日心情
    奋斗
    2019-3-3 00:05
  • 签到天数: 40 天

    [LV.5]常住居民I

    发表于 2019-3-23 15:06 | 显示全部楼层
    tommyjtl 发表于 2019-3-23 14:22
    那应该怎么缓存呢?直接这样吗:
    [mw_shl_code=arduino,true]int dataPackageLength = dataPackage().len ...

    是的,然后用到长度的地方都用这个变量
  • TA的每日心情
    难过
    2019-3-22 16:57
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2019-3-23 15:19 | 显示全部楼层
    t3486784401 发表于 2019-3-23 15:06
    是的,然后用到长度的地方都用这个变量

    仍然还是会有错位
  • TA的每日心情
    奋斗
    2019-3-3 00:05
  • 签到天数: 40 天

    [LV.5]常住居民I

    发表于 2019-3-23 15:28 | 显示全部楼层
    建议用其他串口助手,十六进制模式查看接收,分析下是丢字节了,还是字节内数据有误
  • TA的每日心情
    难过
    2019-3-22 16:57
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2019-3-23 15:51 | 显示全部楼层
    本帖最后由 tommyjtl 于 2019-3-23 16:14 编辑
    t3486784401 发表于 2019-3-23 15:28
    建议用其他串口助手,十六进制模式查看接收,分析下是丢字节了,还是字节内数据有误 ...

    丢字节倒是没有,我用串口调试工具看 Serial.print 的数据,数据都没问题,我怀疑是接收端的代码问题,但目前还是没找到具体原因
  • TA的每日心情
    开心
    2018-1-7 19:07
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2019-3-30 00:47 | 显示全部楼层

    kittenblock中小学创客名师推荐的图形化编程软件

    void serialSendData()
    {
      String qwer = dataPackage();
      char dataBuf[qwer.length() + 1]=qwer.toCharArray();
      Serial1.write(dataBuf);
      delay(250);
    }
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    arduino温湿度串口监视器显示问题
    arduino温湿度串口监视器
    本人刚学arduino,遇到一些技术问题,希望大佬们帮我看一下程序,具体就是温湿度开始
    全过程展示:PWM自定义、测速、PID调速、PID自整定
    全过程展示:PWM自定义、
    有一天,电控小白在某宝上买来了一块Arduino Mega2560、一款直流电机。小白想:“这款
    关于数据同步遇到的问题
    关于数据同步遇到的问题
    首先,下载了DHT-sensor-library-master.zip 并解压到libraries文件夹中(图1) 其次
    blinker设备连接一会后自动断开
    blinker设备连接一会后自
    [mw_shl_code=arduino,true]#define BLINKER_WIFI #define BLINKER_PRINT Serial #
    学生智能打卡系统(接入blinker)
    学生智能打卡系统(接入bl
    【项目名称】学生智能打卡系统(接入blinker) 一.感谢各位大佬 首先感谢社区的管理员
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表