OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2937|回复: 2

分享一个自己写的MODBUS协议

[复制链接]

14

主题

51

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
410
金钱
410
注册时间
2016-6-10
在线时间
50 小时
发表于 2018-7-18 15:05:53 | 显示全部楼层 |阅读模式
本帖最后由 崔洪玺 于 2018-7-18 18:02 编辑

声明:
这个MODBUS协议是从2018.7.13开始写,到今天7.18总共写了5天。时间比较短,肯定有很多不足之处。希望大家把发现的BUG或者要求都告诉我,
我会进行改进,并将结果通知您。我的联系方式是 QQ: 108287205
文件结构:
  UHEAD.H  - 这个头文件里包含的是u8,u16,u32的数据类型定义,其他的没什么了。
  MODBUS  - 这里定义了REQ(请求)和RSP(回复)这两种模式所使用的公共的函数。异常代号和功能码都在这里,数据类型都在这里
     - 还有一个定时器所使用的函数。这个函数也被REQ,RSP公用
     - 注意这里仅需要配置一个地方:MD_BUFNUM 足够大就可以。这是定义存放MODBUS数据的大小
  MODBUS_REQ - 请求模式使用(主机)
  MODBUS_RSP - 回复模式使用(从机)
  MODBUS_CONFIG - 除了MD_BUFNUM,所有的配置都在这里
  
数据存放位置:
  在MODBUS_CONFIG.C中定义了四个数组,根据名字可以知道,当为从机RSP模式时,分别是输出线圈,输入线圈,输出寄存器,输入寄存器数据存放的位置。
  当为主机REQ模式时,只使用前2个数组,输出线圈数组保存的是发送的器件地址,命令,数量,地址,所以大小至少为6;
  输入线圈数组临时保存的是从机的返回数据;
  (注意)由于MODBUS协议数据的读取方式,为了方便读写,数据在数组中是倒着存放的,就是线圈数组的最后一个数的最低位是位置0,寄存器数组的最后一个数,是位置0
  
移植方法:
① MODBUS.H 中MD_BUFNUM足够大,保证在数据传输时不会溢出。
② MODBUS_CONFIG.H 中配置
  - 包含串口头文件;
  - 分别设置REQ,RSP模式的串口初始化函数;
  - 分别设置REQ,RSP模式的配置串口发送一个字节的函数;
  - 如果是从机,设置地址,地址范围(1~247);
  - 配置四组数组的大小,这四个数组功能分别是输出线圈,输入线圈,输出寄存器,输入寄存器;
    说明:当为主机REQ模式时,只使用输入和输出线圈数组大小至少为6。
使用方法:
--->首先,定义一个MD_datstr类型的变量。把这个变量想象成一个对象,一个变量就是一个对象。之后的函数调用哪个变量就是对哪个对象处理;
需要一个定时器,并开启定时中断;
需要一个串口,并开启接收中断;
将MODBUS.H中的 MD_Fun_InTime(MD_datstr* pMD_datstr,u32 period)放在定时器中断中,period值是定时器中断的周期时间,单位us
--->从机RSO模式下

使用RSP.H中的函数 MD_RSP_Init(u16 baud,MD_datstr* pMD_Reqstr) 初始化对象,配置波特率;
   将 RSP_Fun_InUart(MD_datstr* pMD_datstr,u8 receiveByte) 放在串口接收中断中;
在主程序中
  不断判断是否接收到数据,然后调用 RSP_CallBack(MD_datstr* pMD_datstr)进行处理,该函数返回异常,可以接收进行处理。

举例:
  if(MD_str.flag_receiveOK == MD_OK)
  {
   RSP_CallBack(&MD_str);     
  }
  
--->主机REQ模式下使用
   MD_REQ_Init(u16 baud,MD_datstr* pMD_Reqstr)初始化对象,配置波特率
   使用req.H中的函数对从机进行询问,
   主程序中不断判断是否接收到数据,然后调用REQ_CallBack(MD_datstr* pMD_Reqstr);进行处理。
   __weak修饰的函数主要对应的是异常处理,请根据需要改写。
   
  举例:
   
  if(MD_str.flag_listener)    //发送数据后监听
  {
   if(MD_str.flag_waitRelpy == MD_NO) //等待超时  
   {
    ErroOutTime(&MD_str);   //超时处理
    MD_str.flag_listener = 0;  //停止监听
   }
   else
   if(MD_str.flag_receiveOK == MD_OK) //有数据接收到
   {
    erro = REQ_CallBack(&MD_str);
    if(erro)      //处理异常
    {
     printf("erro = 0X%X\r\n",erro);
    }else
    {
     printf("OK--------------------\r\n");
    }         
   }
  } MODBUS.zip (18.17 KB, 下载次数: 227)

程序.zip

8.2 MB, 下载次数: 13856

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

162

帖子

0

精华

高级会员

Rank: 4

积分
933
金钱
933
注册时间
2017-3-23
在线时间
255 小时
发表于 2018-7-18 15:56:21 | 显示全部楼层
回复 支持 反对

使用道具 举报

14

主题

51

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
410
金钱
410
注册时间
2016-6-10
在线时间
50 小时
 楼主| 发表于 2018-7-18 18:03:43 | 显示全部楼层
程序.zip不是这里的,但是我也删不掉了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-16 21:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表