• STM32应用实例七:与宇电设备实现AI-BUS通讯


    宇电的设备使用基于RS-485的自定义协议,协议本身比较简单,只有2条指令:

    读:地址代号+52H(82) +要读的参数代号+0+0+校验码

    写:地址代号+43H(67)+要写的参数代号+写入数低字节+写入数高字节+校验码

    校验码采用 16 位求和校验方式,其中读指令的校验码计算方法为:要读参数的代号×256+82+ADDR。

    写指令的校验码计算方法为以下公式做 16 位二进制加法计算得出的余数(溢出部分不处理):要写的参数代号×256+67+要写的参数值+ADDR。

    返回的数据格式更是固定的,无论是读还是写,仪表都返回以下10个字节数据:测量值 PV+给定值 SV+输出值 MV 及报警状态+所读/写参数值+校验码。

    其中 PV、 SV 及所读参数值均各占 2 个字节,代表一个 16 位二进制有符号补码整数,低位字节在前,高位字节在后,整数无法表示小数点,要求用户在上位机处理; MV 占一个字节,按 8 位有符号二进制数格式,数值范围-110~+110,状态位占一个字节,校验码占 2 个字节,共 10 个字节。

    而返回的校验码计算则是:PV+SV+(报警状态*256+MV)+参数值+ADDR。清楚协议的这些规则后,编写程序只是顺理成章的事。直接上代码:

    /*读取目标设备的参数值*/
    
    void ReadAiBusDeviceParameter(uint8_t deviceAddr,uint8_t paraAddr,void (*AiBusSendByte)(uint8_t *,uint16_t))
    
    {
    
      uint8_t readCommand[INSTRUCTION_LENGTH];
    
      uint16_t index=0;
    
      readCommand[index++]=0x80+deviceAddr;
    
      readCommand[index++]=0x80+deviceAddr;
    
      readCommand[index++]=READ_INSTRUCTION;
    
      readCommand[index++]=paraAddr;
    
      readCommand[index++]=0x0;
    
      readCommand[index++]=0x0;
    
     
    
      uint16_t checkSum=(uint16_t)paraAddr*256+READ_INSTRUCTION+(uint16_t)deviceAddr;
    
     
    
      readCommand[index++]=checkSum;
    
      readCommand[index++]=(checkSum>>8);
    
     
    
      AiBusSendByte(readCommand,INSTRUCTION_LENGTH);
    
    }
    
     
    
    /*设置目标设备的参数值*/
    
    void WriteAiBusDeviceParameter(uint8_t deviceAddr,uint8_t paraAddr,uint16_t data,void (*AiBusSendByte)(uint8_t *,uint16_t))
    
    {
    
      uint8_t writeCommand[INSTRUCTION_LENGTH];
    
      uint16_t index=0;
    
      writeCommand[index++]=0x80+deviceAddr;
    
      writeCommand[index++]=0x80+deviceAddr;
    
      writeCommand[index++]=WRITE_INSTRUCTION;
    
      writeCommand[index++]=paraAddr;
    
      writeCommand[index++]=data;
    
      writeCommand[index++]=(data>>8);
    
     
    
      uint16_t checkSum=(uint16_t)paraAddr*256+WRITE_INSTRUCTION+(uint16_t)deviceAddr+data;
    
     
    
      writeCommand[index++]=checkSum;
    
      writeCommand[index++]=(checkSum>>8);
    
     
    
      AiBusSendByte(writeCommand,INSTRUCTION_LENGTH);
    
    }
    
     
    
    /*解析返回数据,返回值为读或者写的参数值*/
    
    int ParsingReturnData(uint8_t *receiveData,uint16_t *returnData,uint8_t *deviceAddr,uint16_t deviceNum)
    
    {
    
      int status=-1;
    
     
    
      uint16_t pValue=0;
    
      uint16_t sValue=0;
    
      uint16_t mValue=0;
    
      uint16_t alarmStatus=0;
    
      uint16_t paraValue=0;
    
      uint16_t checkSum=0;
    
     
    
      pValue=receiveData[0]+receiveData[1]*256;
    
      sValue=receiveData[2]+receiveData[3]*256;
    
      mValue=(uint16_t)receiveData[4];
    
      alarmStatus=(uint16_t)receiveData[5];
    
      paraValue=receiveData[6]+receiveData[7]*256;
    
      checkSum=receiveData[8]+receiveData[9]*256;
    
     
    
      uint16_t chk=pValue+sValue+alarmStatus*256+mValue+paraValue;
    
     
    
      for(int i=0;i<deviceNum;i++)
    
      {
    
        if(checkSum==chk+deviceAddr[i])
    
        {
    
          status=i;
    
          returnData[0]=pValue;
    
          returnData[1]=sValue;
    
          returnData[2]=mValue;
    
          returnData[3]=alarmStatus;
    
          returnData[4]=paraValue;
    
          break;
    
        }
    
      }
    
      return status;
    
    }
  • 相关阅读:
    不用循如何计算数组累加和
    mysql通过binlog恢复删除数据
    windows下打开binlog
    mysql的binlog
    枚举实现线程池单例
    AtomicInteger的CAS算法浅析
    不用循环如何计算1累加到100
    MongoDB查询报错:class com.mongodb.MongoSecurityException: Exception authenticating MongoCredential
    Senparc.Weixin微信开发(3) 自定义菜单与获取用户组
    Senparc.Weixin微信开发(2) 消息机制和上下文(Session)
  • 原文地址:https://www.cnblogs.com/foxclever/p/6581599.html
Copyright © 2020-2023  润新知