微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > STM32应用实例七:与宇电设备实现AI-BUS通讯

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

时间:10-02 整理:3721RD 点击:

宇电的设备使用基于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_tdeviceAddr,uint8_t paraAddr,void (*AiBusSendByte)(uint8_t *,uint16_t))


{


  uint8_treadCommand[INSTRUCTION_LENGTH];


  uint16_tindex=0;


readCommand[index++]=0x80+deviceAddr;


readCommand[index++]=0x80+deviceAddr;


readCommand[index++]=READ_INSTRUCTION;


readCommand[index++]=paraAddr;


readCommand[index++]=0x0;


readCommand[index++]=0x0;


  


  uint16_tcheckSum=(uint16_t)paraAddr*256+READ_INSTRUCTION+(uint16_t)deviceAddr;


  


readCommand[index++]=checkSum;


readCommand[index++]=(checkSum>>8);


  


AiBusSendByte(readCommand,INSTRUCTION_LENGTH);


}



/*设置目标设备的参数值*/


void WriteAiBusDeviceParameter(uint8_tdeviceAddr,uint8_t paraAddr,uint16_t data,void (*AiBusSendByte)(uint8_t*,uint16_t))


{


  uint8_twriteCommand[INSTRUCTION_LENGTH];


  uint16_tindex=0;


writeCommand[index++]=0x80+deviceAddr;


writeCommand[index++]=0x80+deviceAddr;


writeCommand[index++]=WRITE_INSTRUCTION;


writeCommand[index++]=paraAddr;


writeCommand[index++]=data;


writeCommand[index++]=(data>>8);


  


  uint16_tcheckSum=(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)


{


  intstatus=-1;


  


  uint16_tpValue=0;


  uint16_tsValue=0;


  uint16_tmValue=0;


  uint16_talarmStatus=0;


  uint16_tparaValue=0;


  uint16_tcheckSum=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_tchk=pValue+sValue+alarmStatus*256+mValue+paraValue;


  


  for(inti=0;i<deviceNum;i++)


  {


   if(checkSum==chk+deviceAddr)


    {


     status=i;


     returnData[0]=pValue;


     returnData[1]=sValue;


     returnData[2]=mValue;


     returnData[3]=alarmStatus;


     returnData[4]=paraValue;


     break;


    }


  }


  returnstatus;

}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top