宇电的设备使用基于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=;

  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*+READ_INSTRUCTION+(uint16_t)deviceAddr;

  readCommand[index++]=checkSum;

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

  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=;

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

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

  writeCommand[index++]=WRITE_INSTRUCTION;

  writeCommand[index++]=paraAddr;

  writeCommand[index++]=data;

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

  uint16_t checkSum=(uint16_t)paraAddr*+WRITE_INSTRUCTION+(uint16_t)deviceAddr+data;

  writeCommand[index++]=checkSum;

  writeCommand[index++]=(checkSum>>);

  AiBusSendByte(writeCommand,INSTRUCTION_LENGTH);

}

/*解析返回数据,返回值为读或者写的参数值*/

int ParsingReturnData(uint8_t *receiveData,uint16_t *returnData,uint8_t *deviceAddr,uint16_t deviceNum)

{

  int status=-;

  uint16_t pValue=;

  uint16_t sValue=;

  uint16_t mValue=;

  uint16_t alarmStatus=;

  uint16_t paraValue=;

  uint16_t checkSum=;

  pValue=receiveData[]+receiveData[]*;

  sValue=receiveData[]+receiveData[]*;

  mValue=(uint16_t)receiveData[];

  alarmStatus=(uint16_t)receiveData[];

  paraValue=receiveData[]+receiveData[]*;

  checkSum=receiveData[]+receiveData[]*;

  uint16_t chk=pValue+sValue+alarmStatus*+mValue+paraValue;

  for(int i=;i<deviceNum;i++)

  {

    if(checkSum==chk+deviceAddr[i])

    {

      status=i;

      returnData[]=pValue;

      returnData[]=sValue;

      returnData[]=mValue;

      returnData[]=alarmStatus;

      returnData[]=paraValue;

      break;

    }

  }

  return status;

}

STM32应用实例七:与宇电设备实现AI-BUS通讯的更多相关文章

  1. STM32应用实例六:与MS5837压力传感器的I2C通讯

    MS5837压力传感器是一种可用于电路板上,适用于检测10-1200mbar压力范围的传感器,灵敏度非常高,理论上能够检测到0.01mbar的压力变化,实际使用过程中测试并无明显的变化. MS5837 ...

  2. C语言库函数大全及应用实例七

    原文:C语言库函数大全及应用实例七 [编程资料]C语言库函数大全及应用实例七 函数名: getw 功 能: 从流中取一整数 用 法: int getw(FILE *strem); 程序例: #i nc ...

  3. STM32应用实例八:与多台MS5803压力传感器I2C通讯

    MS5803压力传感器支持SPI和I2C总线通讯,拥有24位AD转换.能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度.各引脚功能及参数如下: ...

  4. STM32学习笔记(七) ADC模数转换测电平(普通和DMA模式)

    嵌入式系统在微控制领域(温度,湿度,压力检测,四轴飞行器)中占据着重要地位,这些功能的实现是由微处理器cpu(如stm32)和传感器以及控制器共同完成的,而连接他们,使它们能够互相正常交流的正是本小节 ...

  5. STM32应用实例十:简析STM32 I2C通讯死锁问题

    I2C接口是一种使用非常普遍的MCU与外部设备的接口方式,在STM32中也集成了I2C接口,我们也常常使用它来与外围的传感器等设备通讯. 最近在我们使用STM32F1VET6读取压力和温湿度传感器数据 ...

  6. python实例七

    https://www.cnblogs.com/evablogs/p/6791548.html 题目:将一个列表的数据复制到另一个列表中. 程序分析:打算利用for循环和append函数来复制到另一个 ...

  7. STM32应用实例十五:STM32的ADC通道间干扰的问题

    最近我们在开发一个项目时,用到了MCU自带的ADC,在调试过程中发现通道之间村在相互干扰的问题.以前其实也用过好几次,但要求都不高所以没有太关注,此次因为物理量的量程较大,所以看到了变化. 首先来说明 ...

  8. STM32应用实例十四:利用光敏二极管实现光度测量

    最近我们在开发臭氧发生器时,需要监测生成的臭氧的浓度,于是想到使用光度计来测量.因为不同浓度的臭氧对管的吸收作用是不相同的,于是检测光照强度的变化就可以得到相应的浓度数据. 1.硬件设计 此次光照度检 ...

  9. STM32应用实例十一:基于SPI和AD7192的数据采集

    在开发臭氧发生器的时,我们需要一个高分辨率的AD采集,于是选择了AD7192,选择这款ADC的原因比较简单.首先它是24位的符合我们的精度要求:其次它自带时钟,便于节省空间:第三他又4路单端或2路差分 ...

随机推荐

  1. 2156: 中南大学2018年ACM暑期集训前期训练题集(入门题) D: 机器人的指令

    不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! ...

  2. operator的itemgetter和attrgetter

    前几天在给个list做排序的时候,隐隐约约想起来有个语法糖可以替代lambda函数,用来获取list中dict的key,作为排序的key. 这个语法糖平时用得少,怎么都想不起来.今天查看python标 ...

  3. Git与GitHub学习笔记(五)一次提交失败的记录

    代码已经跟踪了,添加注释说明,但是总是添加不了 error: pathspec 'live-page'' did not match any file(s) known to git. 重复了好多遍, ...

  4. 选择排序算法的JAVA实现

    1,采用选择排序对元素进行排列时,元素之间需要进行比较,因此需要实现Comparable<T>接口.即,<T extends Comparable<T>>. 更进一 ...

  5. baiduTemplate.js 百度JS模板引擎

    baiduTemplate希望创造一个用户觉得“简单好用”的JS模板引擎 先展示两个例子,然后说说对baidutemplate.js的理解,从而将这一工具加到个人百宝箱里. <script id ...

  6. luogu P2680 运输计划

    传送门 要最长链的长度最短,一秒想到二分,因为如果对于某个长度满足改掉一边的边权后能使得所有链长度不超过该长度,则所有比他长的长度也满足. 二分最终答案.我们要使得原来长度大于二分的\(mid\)的链 ...

  7. aar jar包打包

    使用Android Studio Module的方式编译出aar和jar包: aar包:打aar包时,gradle compile依赖编译进来的包不会被打到aar包中,所以接入aar的应用仍然需要添加 ...

  8. SpringBoot使用Redis缓存

    (1).添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g ...

  9. 【windows核心编程】注入DLL时BUG排除与调试

    DLL注入排除bug的思路步骤. 1.在VS中监视输入err,hr检查DLL是否注入成功 2.OD断点loadlibraryW,loadlibraryA是否已经注入成功,eax是否有值. 3.检查路径 ...

  10. MISC混杂设备 struct miscdevice /misc_register()/misc_deregister()【转】

    本文转自:http://blog.csdn.net/angle_birds/article/details/8330407 在Linux系统中,存在一类字符设备,他们共享一个主设备号(10),但此设备 ...