保持寄存器的访问属性为读写

对保持寄存器的操作包括:读保持寄存器(0x03)、写单个保持寄存器(0x06)、写多个保持寄存器(0x10)、读写多个保持寄存器(0x17)

读保持寄存器(0x03)

在一个远程设备中,使用该功能码读取保持寄存器连续块的内容。请求PDU说明了起始寄存器地址和寄存器数量。从零开始寻址寄存器。因此,寻址寄存器1-16 为0-15。

将响应报文中的寄存器数据分成每个寄存器有两字节,在每个字节中直接地调整二进制内容。对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。

读保持寄存器状态图

/* 读保持寄存器 */
eMBException eMBFuncReadHoldingRegister(UCHAR *pucFrame, USHORT *usLen)
{USHORT usRegAddress;USHORT usRegCount;UCHAR *pucFrameCur;eMBException eStatus = MB_EX_NONE;eMBErrorCode eRegStatus;/* 校验PDU长度是否合理 */if(*usLen == (MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN)){/* 寄存器地址 */usRegAddress = (USHORT)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8);usRegAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1]);/* 第1个寄存器寻址为0,所以地址加一 */usRegAddress++;/* 寄存器数量 */usRegCount = (USHORT)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8);usRegCount = (USHORT)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1]);/* 检查寄存器数量是否合理 */if((usRegCount >= 1) && (usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX)){/* 构建响应 *//* PDU指针 */pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];/* PDU长度初始化为0 */*usLen = MB_PDU_FUNC_OFF;/* 功能码 */*pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER;*usLen += 1;/* 字节数 */*pucFrameCur++ = (UCHAR)(usRegCount * 2);*usLen += 1;/* 读取保持寄存器数据 */eRegStatus = eMBRegHoldingCB(pucFrameCur, usRegAddress, usRegCount, MB_REG_READ);/* 产生异常 */if(eRegStatus != MB_ENOERR){/* 错误转化为异常码 */eStatus = prveMBError2Exception(eRegStatus);}/* 未产生异常 */else{/* 数据长度 */*usLen += usRegCount * 2;}}/* 寄存器数量不合理 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}}/* PDU长度不对 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}return eStatus;
}

写单个保持寄存器(0x06)

在一个远程设备中,使用该功能码写单个保持寄存器。请求PDU 说明了被写入寄存器的地址。从零开始寻址寄存器。因此,寻址寄存器1 为0。

正常响应是请求的应答,在写入寄存器内容之后返回这个正常响应。

写单个保持寄存器状态图

/* 写单个保持寄存器 */
eMBException eMBFuncWriteHoldingRegister(UCHAR *pucFrame, USHORT *usLen)
{USHORT usRegAddress;eMBException eStatus = MB_EX_NONE;eMBErrorCode eRegStatus;/* 校验PDU长度是否合理 */if(*usLen == (MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN)){/* 寄存器地址 */usRegAddress = (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8);usRegAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1]);/* 第1个寄存器寻址为0,所以地址加一 */usRegAddress++;/* 读写保持寄存器数据 */eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],usRegAddress, 1, MB_REG_WRITE);/* 产生异常 */if(eRegStatus != MB_ENOERR){/* 错误转化为异常码 */eStatus = prveMBError2Exception(eRegStatus);}}/* PDU长度不对 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}return eStatus;
}

写多个保持寄存器(0x10)

在一个远程设备中,使用该功能码写连续寄存器块(1 至约120 个寄存器)。在请求数据域中说明了请求写入的值。每个寄存器将数据分成两字节。

正常响应返回功能码、起始地址和被写入寄存器的数量。

写多个保持寄存器状态图

/* 写多个保持寄存器 */
eMBException eMBFuncWriteMultipleHoldingRegister(UCHAR *pucFrame, USHORT *usLen)
{USHORT usRegAddress;USHORT usRegCount;UCHAR ucRegByteCount;eMBException eStatus = MB_EX_NONE;eMBErrorCode eRegStatus;/* 校验PDU长度是否合理 */if(*usLen >= (MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN)){/* 寄存器地址 */usRegAddress = (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8);usRegAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1]);/* 第1个寄存器寻址为0,所以地址加一 */usRegAddress++;/* 寄存器数量 */usRegCount = (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8);usRegCount |= (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1]);/* 字节数 */ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];/* 检查寄存器数量和字节数是否合理 */if((usRegCount >= 1) &&(usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX) &&(ucRegByteCount == (UCHAR)(2 * usRegCount))){/* 写保持寄存器数据 */eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], usRegAddress, usRegCount, MB_REG_WRITE);/* 产生异常 */if(eRegStatus != MB_ENOERR){/* 错误转化为异常码 */eStatus = prveMBError2Exception(eRegStatus);}else{/* 数据长度 */*usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;}}/* 寄存器数量或字节数不合理 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}}/* PDU长度不对 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}return eStatus;
}

读写多个保持寄存器(0x17)

在一个单独MODBUS 事务中,这个功能码实现了一个读操作和一个写操作的组合。从零开始寻址保持寄存器。因此,寻址保持寄存器1-16 为0-15。请求说明了起始地址、被读取的保持寄存器号和起始地址、保持寄存器号以及被写入的数据。在写数据域中,字节数说明随后的字节号。

正常响应包括被读出的寄存器组的数据。在读数据域中,字节数域说明随后的字节数量。

读写多个保持寄存器状态图

/* 读写多个保持寄存器 */
eMBException eMBFuncReadWriteMultipleHoldingRegister(UCHAR *pucFrame, USHORT *usLen)
{USHORT usRegReadAddress;USHORT usRegReadCount;USHORT usRegWriteAddress;USHORT usRegWriteCount;UCHAR ucRegWriteByteCount;UCHAR *pucFrameCur;eMBException eStatus = MB_EX_NONE;eMBErrorCode eRegStatus;/* 校验PDU长度是否合理 */if(*usLen >= (MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN)){/* 读寄存器地址 */usRegReadAddress = (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U);usRegReadAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1]);/* 第1个寄存器寻址为0,所以地址加一 */usRegReadAddress++;/* 读寄存器数量 */usRegReadCount = (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U);usRegReadCount |= (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1]);/* 写寄存器地址 */usRegWriteAddress = (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U);usRegWriteAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1]);/* 第1个寄存器寻址为0,所以地址加一 */usRegWriteAddress++;/* 写寄存器数量 */usRegWriteCount = (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U);usRegWriteCount |= (USHORT)(pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1]);/* 写字节数 */ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];/* 检查读、写寄存器数量和写字节数是否合理 */if((usRegReadCount >= 1) && (usRegReadCount <= 0x7D) &&(usRegWriteCount >= 1) && (usRegWriteCount <= 0x79) &&((2 * usRegWriteCount) == ucRegWriteByteCount)){/* 写保持寄存器数据 */eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],usRegWriteAddress, usRegWriteCount, MB_REG_WRITE);if(eRegStatus == MB_ENOERR){/* 构建响应 *//* PDU指针 */pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];/* PDU长度初始化为0 */*usLen = MB_PDU_FUNC_OFF;/* 功能码 */*pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;*usLen += 1;/* 字节数 */*pucFrameCur++ = (UCHAR) (usRegReadCount * 2);*usLen += 1;/* 读取保持寄存器数据 */eRegStatus = eMBRegHoldingCB(pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ);/* 未产生异常 */if(eRegStatus == MB_ENOERR){/* 数据长度 */*usLen += 2 * usRegReadCount;}}/* 产生异常 */if(eRegStatus != MB_ENOERR){/* 错误转化为异常码 */eStatus = prveMBError2Exception(eRegStatus);}}/* 寄存器数量或字节数不合理 */else{/* 非法数据值 */eStatus = MB_EX_ILLEGAL_DATA_VALUE;}}return eStatus;
}

FreeModbus保持寄存器相关推荐

  1. FreeModbus读/写寄存器小Bug

    备注:经过评论区网友批评指正,协议栈没有Bug.这里只是一种临时解决问题的思路,可能带来其他问题,请各位朋友谨慎使用. 在STM32F401中移植了FreeModBus,移植教程参考了这里:http: ...

  2. 关于Modbus 3区、4区寄存器地址的理解以及Freemodbus中开始地址的设定

    在Modbus实际应用中,我们对Modbus 3区.4区的地址有的时候会出现混淆,尤其是类似于404097这种表达方式的地址,就更容易乱,因为我们常常会用串口调试,这个就容易难理解. Modbus 中 ...

  3. FreeModbus 移植于STM32 实现Modbus RTU通信

    http://ntn314.blog.163.com/blog/static/161743584201233084434579/ 毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像 ...

  4. FreeModbus移植到STM32F103(串行传输方式)

    1.创建工程 2.将FreeModbus源码,拷贝到工程目录 3.将FreeModbus文件添加进工程 添加好之后,编译出现错误 4.移植底层接口 先看第一个错误,缺少port.h 借鉴AVR架构的程 ...

  5. Freemodbus 1.5

    源:http://blog.sina.com.cn/s/blog_4935209001012eax.html 网站位置:http://www.freemodbus.org/index.php?lang ...

  6. STM32F103/107 移植Freemodbus RTU

    1.简介 FreeMODBUS一个奥地利人写的Modbus协议.它是一个针对嵌入式应用的一个免费(自由)的通用MODBUS协议的移植.Modbus是一个工业制造环境中应用的一个通用协议.Modbus通 ...

  7. uip+freemodbus网络通信

    前言: TCP/IP协议通过uip协议栈来实现,应用层的modbus协议使用freemodbus来实现,另外还需要一个网卡(笔者使用的是KSZ8851网卡控制器)来实现底层的数据传输(包括物理层.数据 ...

  8. Rtthread学习笔记(十八)RT-Thread Studio添加freemodbus主机和从机

    有些项目需要同时既做主机读取传感从机器的数据,然后再做从机整合数据与上层主控单元进行通讯,这时候就需要程序中即存在主机,又存在从机.这里就做下测试,主机用串口2,从机用串口3,分别与对应的上位机通讯, ...

  9. freemodbus多从机支持

    MODBUS文件包含 callback.modbus.port. callback文件下有回调函数文件夹 mbcallback.c #include "mb.h"#include ...

最新文章

  1. 世界创新竞争力发展报告:中美日创新产出竞争力居前三
  2. ubuntu怎么测tcp协议的服务器,Ubuntu利用TCP协议来获取server时间(示例代码)
  3. java 学习 --------接口概念
  4. php获取当前设备,Linux_在Linux系统中使用lsblk和blkid显示设备信息的方法,今天我们将会向你展示如何使 - phpStudy...
  5. 在某公司用到一些shell
  6. 视图加载时自动执行铵钮事件
  7. java nio 对消息分片_Java NIO:应用
  8. Pure Pursuit trajectory tracking and Stanley trajectory tracking总结与比较
  9. Flutter基础—根据用户输入改变控件
  10. 记账APP华而不实?Excel门槛太高?不如用它在线记账!
  11. 《看见》读后感:跟柴静一起成长,追求独立与真相
  12. Wagtail 教程 2:简单博客实现
  13. 用c语言编程小鸭子,小鸭子
  14. 无线扩展器中继器 和 电力猫 性能比较
  15. 高仿Android网易云音乐OkHttp+Retrofit+RxJava+Glide+MVC+MVVM
  16. EXCEL中小数点后面的0怎么去掉
  17. web网页设计实例作业——代码质量好-上海介绍(5页) HTML+CSS+JavaScript(含源码)
  18. 自己动手刷原生android系统
  19. Kaggle word2vec NLP 教程 第三部分:词向量的更多乐趣
  20. 巧用ecshop做淘宝客

热门文章

  1. Java工作笔记-AJAX实现整体不变,局部更新(与整体刷新比较)
  2. 计算机组成原理个人笔记(二)
  3. HTML期末网页作业-仿QQ官网QQ注册网页
  4. linux 修改用户登录密码
  5. 铁幕一体计算机配置,讽刺的铁幕来自俄罗斯套娃的爱情配置要求介绍 配置要求高吗_游侠网...
  6. 浪潮服务器nf5280m2安装系统,破茧化蝶之作 浪潮NF5280M2服务器评测
  7. (王道408考研操作系统)第二章进程管理-第一节2:进程状态及其切换
  8. 2-3:配置与环境之定制提示符
  9. 动态规划问题中最长公共子序列---C语言实现
  10. 树:二叉树的层序遍历算法(超简洁实现及详细分析)