移植Modbus到STM32F103(1):coil、discrete、holding和input的取舍

之前自己给设备写的通信协议,一到工作环境就不停通信错误。思前想后,觉得原因是自己瞎写的协议不好,无法适应有噪音的环境。下定决定移植一个成熟的协议。查了资料,发现Modbus协议简单(容易学),稳定(不出错),应用广泛(轮子多)。就是它了。

Modbus通信协议定义了四种常用的寄存器,分别为:线圈状态(coil),离散输入状态(discrete),保持寄存器(holding)和输入寄存器(input)。

这四种寄存器的分类有其历史原因。因为Modbus起源于PLC通信,而PLC是基于非易失性存储介质的,所以使用了coil和holding来表示PLC内部的非易失性变量,使用了discrete和input来表示PLC外界的信号。但现在的系统,其寄存器基本都是掉电丢失的,无论使用哪个来称呼这些寄存器,都会感到有些困惑。

保守的做法,是利用自定义命令来读写这些易失性寄存器,但是这样做会丧失通用性,而且很多现成的移植也失效了。更方便的方法还是按读写能力来分类,单纯地将coil和holding理解为可读写寄存器,而把discrete和input理解为协议里的只读寄存器。

Modbus协议的coil和discrete,针对的是位寄存器;holding和input,针对的是16位寄存器。但这两者也是模糊的。光靠coil和discrete,或者光靠holding和input,其实都已足够。两套方法都可以用,让我这种选择困难患者感觉很难取舍。我最后的方案是,不管什么寄存器,全用holding和input。

定下来以后,就可以开始移植了。

转载于:https://my.oschina.net/u/4076592/blog/3012747

对于STM32F407的Modbus RTU从机代码,你可以参考以下示例代码: ```c #include "stm32f4xx.h" #include "modbusrtu.h" // 定义Modbus从机地址 #define MODBUS_SLAVE_ADDR 0x01 // 定义Modbus数据缓冲区 uint8_t modbus_data[MODBUS_DATA_SIZE]; // 初始化Modbus RTU从机 void modbus_slave_init(void) { // 初始化串口 // ... // 初始化Modbus RTU modbusrtu_init(MODBUS_SLAVE_ADDR, modbus_data, MODBUS_DATA_SIZE); } // 处理接收到的Modbus RTU数据 void modbus_slave_process(void) { // 检查是否接收到Modbus RTU数据 if (modbusrtu_receive()) { // 解析并处理Modbus RTU数据 if (modbusrtu_parse()) { // 获取Modbus功能码 uint8_t function_code = modbusrtu_get_function_code(); // 根据功能码执行相应操作 switch (function_code) { case MODBUS_FUNCTION_READ_COILS: // 处理读线圈寄存器请求 // ... break; case MODBUS_FUNCTION_WRITE_SINGLE_COIL: // 处理写单个线圈寄存器请求 // ... break; case MODBUS_FUNCTION_READ_HOLDING_REGISTERS: // 处理读保持寄存器请求 // ... break; case MODBUS_FUNCTION_WRITE_SINGLE_REGISTER: // 处理写单个保持寄存器请求 // ... break; // 其他功能码处理 // ... default: // 不支持的功能码,返回异常 modbusrtu_exception_response(MODBUS_EXCEPTION_ILLEGAL_FUNCTION); break; } } } } int main(void) { // 初始化Modbus RTU从机 modbus_slave_init(); while (1) { // 处理Modbus RTU数据 modbus_slave_process(); } } ``` 请注意,这只是一个简单的示例代码,你需要根据你的具体需求进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值