0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

宇电AI-BUS通讯协议的驱动设计与实现

CHANBAEK 来源:木南创智 作者:尹家军 2022-12-08 11:41 次阅读

嵌入式系统通常都会与外部设备进行通讯,这就涉及到通讯协议的问题。这些通讯协议有的是标准协议有的厂家自定义的协议,如宇电的AI-BUS。在本篇中,我们将讨论AI-BUS的驱动,以便于与宇电设备的通讯。

1 、功能概述

宇电的设备使用基于RS-485的自定义协议,该协议称为AI-BUS。AI-BUS协议采用16进制数据格式来表示各种指令代码。数据协议本身比较简单,标准的通讯指令只有两条,一条为读指令,一条为写指令:

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

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

具体结构如下图所示:

Dingtalk_20221206154648.jpg

地址代号:为了在一个通讯接口上连接多台 AI 仪表,需要给每台 AI 仪表编一个互不相同的通讯地址。有效的地址为 080(部分型号为 0100),所以一条通讯线路上最多可连接 81 台 AI 仪表,仪表的通讯地址由参数 Addr 决定。仪表内部采用两个重复的 128208(16 进制为 80HD0H)之间数值来表示地址代号,由于大于 128 的数较少用到(如 ASC 方式的协议通常只用 0-127 之间的数),因此可降低因数据与地址重复造成冲突的可能性。 AI 仪表通讯协议规定,地址代号为两个相同的字节,数值为(仪表地址+80H)。例如:仪表参数 Addr=10

(16 进制数为 0AH,0A+80H=8AH),则该仪表的地址代号为:8AH 8AH

参数代号:仪表的参数用 1 个 8 位二进制数(一个字节,写为 16 进制数)的参数代号来表示。它在指令中表示要读/写的参数名。

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

公式中的数字都为十进制;公式中 ADDR 为仪表地址参数值,范围是 0~80(注意不要加上 80H)。校验码为以上公式做二进制 16 位整数加法后得到的余数,余数为 2 个字节,其低字节在前,高字节在后。要写的参数值用 16 位二进制整数表示。

返回的数据格式更是固定的,无论是读还是写,仪表都返回以下10个字节数据:

测量值 ** PV+** 给定值 ** SV+** 输出值 ** MV ** 及报警状态 + 所读 / 写参数值 + 校验码。

Dingtalk_20221206154648.jpg

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

返回校验码的计算公式: PV+SV+ (报警状态 *256+MV + 参数值 +ADDR

2 、驱动设计与实现

我们已经清楚了AI-BUS协议的的基本规则,对于通讯协议的驱动开发,只需要按照通讯协议来实现代码就可以了。

2.1 、对象定义

同样的我们在操作AI-BUS设备之前,我们先需要定义AI-BUS设备对象。然后针对AI-BUS设备的操作就是针对该对象的操作。

2.1.1 、对象的抽象

根据AI-BUS设备对象的特点,我们抽象对象类型。该对象各类型包括设备地址和状态2个属性和发送命令一个操作。而对于消息的接收我们一般采用串口中断方式。对象类型定义如下:

/* 定义AI-BUS设备对象 */
typedef struct AIbusObject {
      uint8_t deviceAddr;
      uint8_t status;
      void(*SendBytes)(uint8_t *cmd,uint16_t size);
}AIbusObjectType;

2.1.2 、对象初始化

定义了AI-BUS对象类型后,我们就可以使用该类型声明不同的对象,但是声明的对象仅为一个对象变量,在使用之前必须对其进行初始化,初始化函数如下:

/* AI-BUS对象初始化 */
void AIbusInitialization(AIbusObjectType*aibus,uint8_t addr,AiBusSendBytessend)
{
      if((aibus==NULL)||(send==NULL))
      {
             return;
      }

      aibus->deviceAddr=addr;
      aibus->SendBytes=send;
}

2.2 、对象操作

完成了对象的初始化后就可以实现对对象的操作了。根据前面对AI-BUS协议的了解,我们所需要完成的操作实际上就是3个方面。一是对目标设备参数的读操作;二是对目标设备参数的写操作;三是对接收到的消息进行解析。

2.2.1 、读对象操作

对AI-BUS对象的读就是将读命令按一定格式下发就好了。读命令的格式为**:地址代号** +52H 82 + 要读的参数代号 +0+0+ 校验码 。可以据此编写读操作如下:

/*读取目标设备的参数值*/
void ReadAiBusDeviceParameter(AIbusObjectType *aibus,uint8_tparaAddr)
{
 uint8_t readCommand[INSTRUCTION_LENGTH];
 uint16_t index=0;
 readCommand[index++]=0x80+aibus->deviceAddr;
 readCommand[index++]=0x80+aibus->deviceAddr;
 readCommand[index++]=READ_INSTRUCTION;
 readCommand[index++]=paraAddr;
 readCommand[index++]=0x0;
 readCommand[index++]=0x0;
 
 uint16_tcheckSum=(uint16_t)paraAddr*256+READ_INSTRUCTION+(uint16_t)aibus->deviceAddr;
 
 readCommand[index++]=checkSum;
 readCommand[index++]=(checkSum>>8);
 
 aibus->SendBytes(readCommand,INSTRUCTION_LENGTH);
}

2.2.2 、写对象操作

同样,对AI-BUS对象的写操作也是按照写命令的格式下发命令就可以了。写对象的命令格式为**:地址代号** +43H 67 + 要写的参数代号 + 写入数低字节 + 写入数高字节 + 校验码 。我们据此可以编写写操作函数:

/*设置目标设备的参数值*/
void WriteAiBusDeviceParameter(AIbusObjectType *aibus,uint8_t paraAddr,uint16_t data)
{
 uint8_t writeCommand[INSTRUCTION_LENGTH];
 uint16_t index=0;
 writeCommand[index++]=0x80+aibus->deviceAddr;
 writeCommand[index++]=0x80+aibus->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)aibus->deviceAddr+data;
 
 writeCommand[index++]=checkSum;
 writeCommand[index++]=(checkSum>>8);
 
 aibus->SendBytes(writeCommand,INSTRUCTION_LENGTH);
}

2.2.3 、消息解析

我们已经知道AI-BUS对象的返回消息是一个固定的的格式。即:测量值 ** PV+** 给定值 ** SV+** 输出值 ** MV ** 及报警状态 + 所读 / 写参数值 + 校验码 。每一个字都是低字节在前,而校验码则是返回的数据和加上设备地址,我们据此编写解析函数:

/*解析返回数据,返回值为读或者写的参数值*/
int ParsingReturnData(uint8_t*receiveData,uint16_t *returnData,AIbusObjectType *aibus,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;iif(checkSum==chk+aibus[i].deviceAddr)
   {
     status=i;
     returnData[0]=pValue;
     returnData[1]=sValue;
     returnData[2]=mValue;
     returnData[3]=alarmStatus;
     returnData[4]=paraValue;
     break;
   }
 }
      
 aibus[status].status=alarmStatus;
      
 return status;


}

3 、驱动的使用

AI-BUS协议设备驱动的使用主要按照三个步骤来操作:声明并初始化对象;发送操作命令;接收并解析消息。接下来我们将据此完成驱动的使用。

3.1 、声明并初始化对象

我们需要使用AIbusObjectType类型声明对象变量。同时我们要实现一个typedef void (*AiBusSendBytes)(uint8_t *cmd,uint16_t size)类型的操作函数。我们假设使用的USART1端口,则具体实现如下:

/*发送数据*/
void AiBusSendByte(uint8_t *instruction,uint16_t length)
{
  /*RS485设置为发送模式,准备发送*/
  TEMPCTL_TRANSMIT_ALLOW();
  aiBusRxLength=0;
 
  uint16_t i;
  for(i=0;i/*传送寄存器不为空,等待传送结束*/
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
    {
    }
    /*写一个字节到对应的串口传送数据寄存器*/
    USART_SendData(USART1, instruction[i]);
  }
  Delayms(3);
  /*发送完毕,将RS485改为接收模式准备接收*/
  TEMPCTL_RECIEVE_ALLOW();
  Delayms(20);
}

对于单个的对象我们直接使用其声明就可:AIbusObjectType aiDev;假设其设备地址为uint8_t addr=0x01。然后调用初始化函数初始化。对于单台设备则可直接调用:

AIbusInitialization(&aiDev,addr,AiBusSendByte);

而如果是在同一总线上有多个设备,我们也可以将其定义为数组形式。假设有4台设备,地址我分别为:0x01,0x02,0x03,0x04,则可定义为:

AIbusObjectTypeaiDev[4];

uint8_t addr[4]={0x01,0x02,0x03,0x04};

然后同样调用初始化函数初始化:

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

{

AIbusInitialization(aiDev+i,addr[i],AiBusSendByte);

}

3.2 、发送操作命令

初始化完成后就可以对其进行真正的操作:读取或者写某个参数的值。对于读参数的值操作则只需要调用读操作函数来完成:

ReadAiBusDeviceParameter(&aiDev,paraAddr);

而对于写参数值的操作也只是简单的调用写操作函数来完成:

WriteAiBusDeviceParameter(&aiDev,paraAddr,data);

如果是多个对象,与前面一样操作数组的方式来操作就可以了,再次就不赘述。

3.3 、接收并解析消息

接收消息我们采用串口中断接收。具体实现如下:

void USART1_ReceiveDataHandle(void)
{
    if(aiBusRxLength>=RETURNING_DATA_LENGTH)
  {
    aiBusRxLength=0;
  }
  /*接收寄存器为空,等待字节被对应的串口完全接收*/
  if(USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET)
    {  
    /*获取接收到的字节数*/
    aiBusRxBuffer[aiBusRxLength++] =USART_ReceiveData(USART1);
  }
  }

我们知道接受的消息格式是固定的,我们调用消息解析函数来完成解析:

ParsingReturnData(receiveData,returnData,&aiDev,deviceNum);

其中receiveData是长度为10的uint8_t类型数组。returnData是长度为5的uint16_t类型数组。

4 、应用总结

我们完成了AI-BUS驱动的编写及应用。我们使用其同时操作4台温度控制器。我们操作数组的方式简化函数的调用过程。当然结果与我们的预期是相符的。

使用本驱动程序操作AI-BUS设备,有一点需要注意:对于不懂的设备类型,参数的具体地址是用所不同的,需要查看厂家的参数定义来操作。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • AI
    AI
    +关注

    关注

    87

    文章

    30919

    浏览量

    269166
  • bus
    bus
    +关注

    关注

    0

    文章

    120

    浏览量

    47597
  • 通讯协议
    +关注

    关注

    10

    文章

    274

    浏览量

    20354
  • 驱动设计
    +关注

    关注

    1

    文章

    111

    浏览量

    15285
收藏 人收藏

    评论

    相关推荐

    #伺服电机 #PLC 30秒初步学习modbus通讯协议

    plcbus通讯协议
    学习电子知识
    发布于 :2022年10月24日 00:05:40

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

    的设备使用基于RS-485的自定义协议协议本身比较简单,只有2条指令:读:地址代号+52H(82) +要读的参数代号+0+0+校验码写:地址代号+43H(67)+要写的参数代号+
    发表于 03-19 18:55

    基于LabVIEW的Modbus串口通讯协议实现

    基于LabVIEW 的Modbus 串口通讯协议实现附件基于LabVIEW 的Modbus 串口通讯协议
    发表于 10-16 10:50

    S.BUS是什么?S.BUS协议有何特点

    S.BUS是什么?S.BUS协议有何特点?
    发表于 12-15 07:40

    S.BUS协议原理

    内容本篇文章主要是S.BUS协议原理介绍,并实现了arduino输出S.BUS数据。S.BUS简介SBUS是一个接收机串行总线输出,通过这根
    发表于 01-20 08:06

    采用socket形式进行通讯的ec20驱动是需要自己实现mqtt协议吗?

    看了下ec20的AT组件包,驱动是采用socket的形式进行通讯的,那么这个通讯的开发是需要在rtt上自己实现mqtt,http,ftp等应用层的
    发表于 03-07 14:19

    Modbus通讯协议的几种实现方式

    RTU和TCP两种协议中转换,根据需要选择不同协议。这是LabVIEW多态的一个非常好的示例。程序见下图。   5.LabVIEW 采用TCP模块实现Modbus通讯   在没有DSC
    发表于 05-05 16:19

    基于DSP的CANopen通讯协议实现

    CANopen 是一种开放的应用层协议,其应用可以进一步提高系统的可靠性、通讯效率及灵活性,而且可以使产品具有很好的兼容性。本文采用CANopen 通讯协议
    发表于 09-03 09:19 19次下载

    基于C++的modbus通讯协议模型实现

    基于C++的modbus通讯协议模型实现,很好的资料,快来下载学习吧。
    发表于 03-21 17:27 55次下载

    AIBUS及MODBUS通讯协议说明V80

    AIBUS及MODBUS通讯协议说明,word文档,包括变量地址及输入输出指令格式
    发表于 03-23 15:31 9次下载

    一种新型通讯管理装置的研究与实现_丁志

    一种新型通讯管理装置的研究与实现_丁志
    发表于 02-07 18:11 0次下载

    ModbusRTU通讯协议(主站)通讯联机便利指令

    FUN150(M-BUS)指令提供永宏PLC(主站)透过Port1,2,3或4以ModbusRTU通讯协议与具有该通讯协议之智能型外围(仆站
    发表于 09-29 17:38 17次下载
    ModbusRTU<b class='flag-5'>通讯</b><b class='flag-5'>协议</b>(主站)<b class='flag-5'>通讯</b>联机便利指令

    海为PLC与AI-706M多路巡检仪通讯介绍

    因为AI-706M多路巡检仪的通讯协议公司
    发表于 10-09 11:26 11次下载
    海为PLC与<b class='flag-5'>宇</b><b class='flag-5'>电</b><b class='flag-5'>AI</b>-706M多路巡检仪<b class='flag-5'>通讯</b>介绍

    智能仪 让温控系统更简单

    。触摸屏电脑上的并行口还可以直接和打印机连接实时或定时打印当前或历史数据。利用触摸屏中电脑内置的RS485通讯口与AI708、AI708M温控表直接通讯
    的头像 发表于 09-26 10:20 4406次阅读

    AI808与组态王6.01通讯测试教程

    AI808与组态王6.01通讯测试教程
    发表于 07-23 09:24 18次下载