查看: 6762|回复: 16

[已解决] 求解关于arduino的485通讯问题

[复制链接]
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    发表于 2018-8-1 20:15 | 显示全部楼层 |阅读模式
    41金币
    本帖最后由 暗杀星 于 2018-8-4 15:20 编辑

    我现在有一个ttl转485芯片,一个uno和一个用485通讯的蠕动泵,我想用uno来控制蠕动泵,来读取转速(03),控制转速等(06)!哪位大佬知道怎么编程么,我在网上搜了一些程序,调试都失败了。蠕动泵通讯协议见附件!,我自己的03读取功能程序如下,但是没实现读取。求大神拯救
    #include <ModbusMaster.h>//modbusmaster库,03读取功能

    uint16_t m_startAddress = 2;//要读取的从站起始地址
    uint8_t m_length = 2;//从从站起始地址开始你需要读取的数据的长度
    uint8_t result;//串口通信结果,不用明白是什么,只要知道这不是你最终需要的数据就行

    ModbusMaster node(1);//对1号从站进行通信
    int LED = 8;
    void setup() {
      node.begin(9600);//定义arduino与从站之间的串口波特率
      pinMode(LED,OUTPUT);
    //Serial.begin(9600); //端口的波特率设置
    Serial.begin(9600, SERIAL_8N2);        //数据位8,无校验位,停止位2

    }

    void loop() {  
      result = node.readHoldingRegisters(m_startAddress, m_length);//调用相关函数
      if (result == node.ku8MBSuccess) {//如果通信成功
        digitalWrite(LED,HIGH);
        delay(500);
        digitalWrite(LED,LOW);
        delay(500);

      }
      else {
        digitalWrite(LED,HIGH);
      }
    }

    调速系列蠕动泵产品通讯协议.pdf

    154.64 KB, 下载次数: 51

  • TA的每日心情
    开心
    2020-8-19 08:39
  • 签到天数: 818 天

    [LV.10]以坛为家III

    发表于 2018-8-2 09:04 | 显示全部楼层
    首先 我看到这样的代码 第一反应就是  为什么没有调试信息  你想要知道为什么不行 那么就老老实实加调试信息  看看代码运行到哪里出错了 大神
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-8-2 09:25 | 显示全部楼层
    单片机菜鸟 发表于 2018-8-2 09:04
    首先 我看到这样的代码 第一反应就是  为什么没有调试信息  你想要知道为什么不行 那么就老老实实加调试信 ...

    代码拷到arduino运行后,读不到转速,串口接收区显示01 03 00 02 00 02 65 CB   正确的话第二个0002显示的是转速,但是我改变转速,他不变,断开与步进电机连线,他依然还是那样,显然就没有通信啊。而且我最想实现的是06写入功能,就是可以调转速。但是我不会写代码,所以来求助。
  • TA的每日心情
    慵懒
    2018-11-12 08:58
  • 签到天数: 37 天

    [LV.5]常住居民I

    发表于 2018-8-2 10:26 | 显示全部楼层
    本帖最后由 跑龙套的保 于 2018-8-2 15:01 编辑

    就那么难么,问了那么久了,用了TTL转485,你就别把它当做485通讯的了,arduino 里的程序就是读写串口,直接帮你写好吧
    [mw_shl_code=cpp,true]#include <SoftwareSerial.h>
    const byte rxPin = 2;
    const byte txPin = 3;

    //ttl转485接软串
    SoftwareSerial TTL2485(rxPin, txPin);

    // #define TTL2485 Serial

    #define MAX_PACKETSIZE 128 //自定义的缓冲buff长度

    uint8_t softUart_Receive_Buff [ MAX_PACKETSIZE ]; //定义缓冲buff

    unsigned int softUart_Receive_Index = 0; //收到的字节实际长度

    unsigned long preSoftUartTime = 0; //记录读取最好一个字节的时间点


    /*
      计算crc16校验
      modbus
    */
    uint16_t calcCRC16 (uint8_t *ptr, size_t size)
    {
      unsigned short a, b, tmp, CRC16, V;
      CRC16 = 0xffff;               //CRC寄存器初始值
      for (a = 0; a < size; a++)      //N个字节
      {
        CRC16 = *ptr ^ CRC16;
        for (b = 0; b < 8; b++)      //8位数据
        {
          tmp = CRC16 & 0x0001;
          CRC16 = CRC16 >> 1;     //右移一位
          if (tmp)
            CRC16 = CRC16 ^ 0xa001;  //异或多项式
        }
        *ptr++;
      }
      //大小端转换
      V = ((CRC16 & 0x00FF) << 8) | ((CRC16 & 0xFF00) >> 8); //高低字节转换
      return V;
    }

    /*
      校验crc16
      modbus
    */
    bool checkCRC16(uint8_t *p, size_t len)
    {
      if (p[len - 2] * 256 + p[len - 1] == calcCRC16(p, len - 2))
        return true;
      else
        return false;
    }

    /*
      16进制转字符串
    */
    void printHex(uint8_t *p, uint16_t len)
    {
      char *pbuff = (char*)malloc(len * 3 + 1);
      if (pbuff == NULL ) return;
      pbuff[0] = 0x00;
      char t[5];
      for (int i = 0; i < len; i++)
      {
        sprintf(t, "%02X ", p);
        strcat(pbuff, t);
      }

      Serial.println("[printHex]");
      Serial.println(pbuff);

      free(pbuff);
    }

    /*
      处理串口数据函数,可以在函数内编写处理函数数据的程序
    */
    void parseSoftUartPackage(uint8_t *p , int len) {
      //打印日志到串口
      Serial.print(F("[SoftUart Read]:"));
      printHex(p, len);

      if (len != 8) {
        Serial.println(F("[ERROR]:len != 8"));
        return;
      }

      if (!checkCRC16(p, len)) {
        Serial.println(F("[ERROR]:check CRC16 error"));
        return;
      }

      if(p[1] == 0x03){
          Serial.println(F("cmd 03 responded successfully"));

          //发送启动指令
          uint8_t cmd06[8] = {0x01,0x06,0x00,0x00,0x00,0x01,0x48,0x0a};
          send2SoftUart(cmd06,8);
      }

      else if(p[1] == 0x06){
          Serial.println(F("cmd 06 responded successfully"));

      }

    }

    //发送数据到串口
    void send2SoftUart(uint8_t *p, size_t len)
    {
      Serial.print(F("[send to SoftUart ]:"));
      printHex(p, len);
      TTL2485.write(p,len);
    }


    /*
      软串串口数据接受进程
    */
    void doSotfUartTick()
    {
      if (TTL2485.available())
      { //读取串口数据
        //每次读取一个字节的数据存储在这个buff中
        softUart_Receive_Buff [ softUart_Receive_Index ++ ] = TTL2485.read();
        //记录下读取这个数据的时间点
        preSoftUartTime = millis();

        //判断读取到的数据长度是否超过设定的记录长度,超过长度时间点往前200ms 立即执行分析函数
        if (softUart_Receive_Index >= MAX_PACKETSIZE - 1) {
          softUart_Receive_Index = MAX_PACKETSIZE - 2;
          preSoftUartTime = preSoftUartTime - 200;
        }
      }
      //判断收到的最后一个字节后超过100ms开始执行分析函数
      if (softUart_Receive_Index > 0 && (millis() - preSoftUartTime >= 100))
      { //处理串口数据
        //把buff最后一个字节设为0,在字符串处理中很有用
        softUart_Receive_Buff [ softUart_Receive_Index ] = 0x00;
        TTL2485.flush();

        //执行串口数据处理函数
        parseSoftUartPackage(softUart_Receive_Buff, softUart_Receive_Index);
        softUart_Receive_Index = 0;
      }
    }

    void setup() {
      TTL2485.begin(9600);
      Serial.begin(9600);

      //发送查询指令
      uint8_t cmd03[8] = {0x01,0x03,0x00,0x02,0x00,0x01,0x25,0xca};
      send2SoftUart(cmd03,8);
    }

    void loop()
    {
      //调用串口数据处理进程
      doSotfUartTick();
    }[/mw_shl_code]
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-8-2 14:20 | 显示全部楼层
    跑龙套的保 发表于 2018-8-2 10:26
    就那么难么,问了那么久了,用了TTL转485,你就别把它当做485通讯的了,arduino 里的程序就是读写串口,直 ...

    非常感谢!现在可以写入了,可以调速了。但是读取转速还有点问题,串口监视器是这样显示的:
    [send to SoftUart ]:[printHex]
    01 03 00 02 00 01 25 FFCA
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-8-2 14:46 | 显示全部楼层
    暗杀星 发表于 2018-8-2 14:20
    非常感谢!现在可以写入了,可以调速了。但是读取转速还有点问题,串口监视器是这样显示的:
    [send to So ...

    为什么写入速度指令只能是:char cmd06[8] = {0x01,0x06,0x00,0x02,0x01,0x2c,0x28,0x47};
      send2SoftUart(cmd06,8);
    我把它改为char cmd06[8] = {0x01,0x06,0x00,0x02,0x00,0x11,0xe8,0x06};
      send2SoftUart(cmd06,8);换个速度就不行了呢?
    还有我输入停止指令char cmd06[8] = {0x01,0x06,0x00,0x00,0x00,0x00,0x89,0xca};
      send2SoftUart(cmd06,8);它并没有停止啊。
    大佬再来给我解答一下,非常感谢!!
  • TA的每日心情
    慵懒
    2018-11-12 08:58
  • 签到天数: 37 天

    [LV.5]常住居民I

    发表于 2018-8-2 15:00 | 显示全部楼层
    暗杀星 发表于 2018-8-2 14:20
    非常感谢!现在可以写入了,可以调速了。但是读取转速还有点问题,串口监视器是这样显示的:
    [send to So ...

    这条回应什么,打印多了个ff是printhex这个函数出的问题,不影响,发到485的没变,改下无符号类型就行了,我更新了下上文的代码
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-8-2 15:39 | 显示全部楼层
    跑龙套的保 发表于 2018-8-2 15:00
    这条回应什么,打印多了个ff是printhex这个函数出的问题,不影响,发到485的没变,改下无符号类型就行了 ...

    大神完美的解决了我的问题,我还有一个小小的请求,能不能帮我在这个程序基础上修改一下,比如我输入“a”对应一个速度,输入b对应一个速度....输入1停止,输入2启动,输入A正转,输入B反转。万分感谢!
  • TA的每日心情
    慵懒
    2018-11-12 08:58
  • 签到天数: 37 天

    [LV.5]常住居民I

    发表于 2018-8-2 16:23 | 显示全部楼层
    暗杀星 发表于 2018-8-2 15:39
    大神完美的解决了我的问题,我还有一个小小的请求,能不能帮我在这个程序基础上修改一下,比如我输入“a ...

    根据现有的代码,复制修改添加一套读取硬件串口的就可以了
  • TA的每日心情
    开心
    2019-1-20 11:13
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-8-2 16:25 | 显示全部楼层
    跑龙套的保 发表于 2018-8-2 16:23
    根据现有的代码,复制修改添加一套读取硬件串口的就可以了

    您就好人做到底,帮帮我吧,我不会编程,正在学。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    读取传感器的16进制问题
    读取传感器的16进制问题
    这是我的代码,求助怎样写才能分别获得通道1、2的TDS值和温度值,求助!!! [mw_shl_
    RPG游戏 无人世界
    RPG游戏 无人世界
    操作:方向键移动,a键确认 b键打开符文菜单 游戏流程大约半小时 视频攻略:ht
    开贴讲讲NRF24L01P,让你彻底搞懂它的工作原理,持续更...
    开贴讲讲NRF24L01P,让你
    *****************************************
    Arduino MEGA 与UNO 通过nRF24L模块通讯
    Arduino MEGA 与UNO 通过n
    一开始测试时手头上只有论坛给的一块mega以及自己的一块仿制UNO,结果是nRF24L无法
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表