OpenEdv-开源电子网

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

开源Modbus协议---XTinyModbus

[复制链接]

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
发表于 2020-4-18 21:43:26 | 显示全部楼层 |阅读模式
本帖最后由 lotoohe 于 2020-12-10 12:38 编辑

Github下载:https://github.com/lotoohe-space/XTinyModbus

博客下载:https://blog.csdn.net/LOTOOHE/article/details/105289542

已经移植好STM32F1
XTinyModbus
===

一个应用于嵌入式方面的小型Modbus协议栈,采用C语言编写,支持master与slave,支持离散映射,支持非阻塞与阻塞读写模式,并提供完整示例,可以移植到不同的处理器,使用简单,移植方便。<br>

2020/11/23
优化从机协议解析策略,更加稳定
优化循环队列,使得其适应性更强
循环队列内存修改为用户指定
主机增加RTOS支持,可以通过MD_RTU_Config.h下的MD_RTU_USED_OS开启,默认关闭,已经移植好XTinyRTOS,可以通过修改MD_RTU_Sysinterface.c进行移植
其它修改及优化
2020/9/24
增加从机掉线不轮询功能,主机可以使用MDM_RTU_CB_SetDisPollEnFlag函数进行设置,
可以使用MDM_RTU_CB_ClrDisFlag函数进行复位。
增加简单的主机发送控制器。
修复主机阻塞模式和非阻塞模式混合调用的BUG。
代码中所有注释修改为英文。
2020/9/6 增加多从机示例。
增加一些测试用的宏。
2020/8/31 增加MD_RTU_Config.h进行协议栈配置。
增加测试配置宏。
文件命名的修改。
一些其它的修改。
2020/6/6 修正一个大小端错误。
Slaver 修正离散映射函数读取的错误。
从机支持广播地址。
Master 主机添加发送缓存。
2020/4/28 Master 主机的离散映射将必须指定从机号,不在采用共用方式。
2020/4/23 Slave 修复CRC宏的一个BUG。
修复离散映射表主从机大小不一致的BUG。
Master 修复读命令,因变量从用导致错误的BUG。
串口初始化位置修改到MD_RTU_Serial.c 与 MDM_RTU_Serial.c内。
修正一些命名规范。
2020/4/13 Slave增加发送缓存,该项为可选项,可以通过MD_RTU_Fun.h内的宏配置,默认开启。
2020/4/12 增加收发转换控制。
2020/4/10 代码添加注释,规范注释方式,优化文件存放结构。
2020/4/4 Slave修复定时器溢出可能导致丢包的极小概率bug。
2020/4/3 Slave更改离散映射方式,输入分开映射
2020/3/31 Slave添加主机写回调函数监听。
Slave添加部分异常码与错误码支持。
Slave修复发送未进行帧间隔的错误。
优化CRC16效率。

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

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-21 21:43:59 | 显示全部楼层
比freemodbus简单,而且使用很简单,目前只支持裸机
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2019-7-11
在线时间
21 小时
发表于 2020-4-22 17:32:38 | 显示全部楼层
欧里给
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2017-9-23
在线时间
2 小时
发表于 2020-4-22 23:33:20 | 显示全部楼层
支持一下
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10627
金钱
10627
注册时间
2017-4-14
在线时间
2778 小时
发表于 2020-4-23 10:57:36 | 显示全部楼层
本帖最后由 nashui_sx 于 2020-4-23 12:35 编辑

简单看了下 很不错 裸机以后试试你这个


可能发现个bug

RegTableListAdd
RegTableListDel
这两个函数用的最大值宏都是REG_COIL_ITEM_NUM
应该主机用 MDM_REG_COIL_ITEM_NUM
从机用        REG_COIL_ITEM_NUM

要么两个宏合成一个,要么结构体内增加成员变量标记是主机调用还是从机调,要么函数增加参数 好点
发现的原因是你底层MD_RTU_RegCoil.c   调用了上层的头文件#include "MD_RTU_Fun.h" 看为啥调用就发现了这个宏

回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10627
金钱
10627
注册时间
2017-4-14
在线时间
2778 小时
发表于 2020-4-23 18:45:54 | 显示全部楼层
本帖最后由 nashui_sx 于 2020-4-23 18:52 编辑

又发现你两个严重的错误
你的所有的读功能都是错误的,
原因是MDM_RTU_NB_RW()函数中 MDM_RTU_InsideWriteBits    MDM_RTU_InsideWriteRegs ()   最后一个参数你传入的是byte  但是当时byte已经是数据长度了  

修改
switch(byte)前新建一个临时变量把这时候byte还是功能码的byte存起来,给的  MDM_RTU_InsideWriteBits    MDM_RTU_InsideWriteRegs用

如下
  1. MDError MDM_RTU_NB_RW(
  2.         PModbus_RTU_CB pModbus_RTU_CB,
  3.         ModbusFunCode funCode,
  4.         uint8 slaveAddr,
  5.         uint16 startAddr,
  6.         uint16 numOf,
  7.         void *wData
  8. ){
  9.         MDError errRes;
  10.         uint8 index;
  11.         uint16 wAddr;
  12.         errRes = ERR_NONE;
  13.         if(pModbus_RTU_CB==NULL){return ERR_VOID;}
  14.         if(pModbus_RTU_CB->pModbus_RTU==NULL){return ERR_VOID;}
  15.         
  16.         if(        pModbus_RTU_CB->pModbus_RTU->parentObj!=NULL &&
  17.                         pModbus_RTU_CB!=pModbus_RTU_CB->pModbus_RTU->parentObj){
  18.                         return ERR_IDLE;
  19.         }
  20.         
  21.         if(pModbus_RTU_CB->sendFlag==0){/*还没发送过,或者已经发送成功*/
  22.                 /*清除接收队列*/
  23.                 MDResetQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue));
  24.                 if(funCode>=1 && funCode<=4){
  25.                         /*还没有发送过,则发送*/
  26.                         MDM_RTU_ReadFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,numOf);
  27.                 }
  28.                 else if(funCode==5||funCode==6){
  29.                         if(numOf>=1){/*长度必须大于等于1*/
  30.                                 MDM_RTU_WriteSingleFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,((uint16*)(wData))[0]);
  31.                         }
  32.                 }else if(funCode==15||funCode==16){
  33.                         MDM_RTU_WriteFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,numOf,(uint8*)(wData));
  34.                 }
  35.                 /*设置超时时间起点*/
  36.                 pModbus_RTU_CB->sendTimeTick=pModbus_RTU_CB->pModbus_RTU->timesTick;
  37.                
  38.                 /*已经发送数据,等待超时检测*/
  39.                 //MD_SET_SENDED_FLAG(pModbus_RTU_CB);
  40.                 pModbus_RTU_CB->sendFlag=1;
  41.                 /*设置该块正在工作*/
  42.                 pModbus_RTU_CB->pModbus_RTU->parentObj=pModbus_RTU_CB;
  43.                 return ERR_SEND_FIN;
  44.         }else if(pModbus_RTU_CB->RTCount<pModbus_RTU_CB->RTTimes){/*已经发送过,并且没有出现发送错误的情况*/
  45.                
  46.                 if(pModbus_RTU_CB->pModbus_RTU->recvFlag){/*收到了数据*/
  47.                         uint8 byte;
  48.                         uint8 AddrType_byte=0;
  49.                         /*清楚标志*/
  50.                         pModbus_RTU_CB->pModbus_RTU->recvFlag=0;
  51.                         
  52.                         if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte)){//提取地址
  53.                                 errRes =  ERR_DATA_LEN;
  54.                                 goto _exit;
  55.                         }
  56.                         /*如果收到数据,则对数据进行处理*/
  57.                         if(slaveAddr!=byte){
  58.                                 errRes =  ERR_SLAVE_ADDR;
  59.                                 goto _exit;
  60.                         }
  61.                         if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&AddrType_byte)){//提取功能码
  62.                                 errRes =  ERR_DATA_LEN;
  63.                                 goto _exit;
  64.                         }
  65.                         
  66.                         switch(AddrType_byte){
  67.                                 case 0x1:/*读线圈成功*/
  68.                                 case 0x2:/*读输入离散量*/
  69.                                 {
  70.                                         uint16 i;
  71.                                         MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte);//提取数据长度
  72.                                         if((byte+2)!=MDQueueLength(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue))){//长度+2位crc
  73.                                                 /*长度错误*/
  74.                                                 errRes =  ERR_DATA_LEN;
  75.                                                 goto _exit;
  76.                                         }
  77.                                         index = numOf;
  78.                                         wAddr=startAddr;
  79.                                         for(i=0;i<byte;i++){
  80.                                                 uint8 rByte;
  81.                                                 if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte)){
  82.                                                                 /*长度错误*/
  83.                                                                 errRes =  ERR_DATA_LEN;
  84.                                                                 goto _exit;
  85.                                                 }
  86.                                                 /*单次存小于等于8bit*/
  87.                                                 if(!MDM_RTU_InsideWriteBits(pModbus_RTU_CB->pModbus_RTU,wAddr,((index<8)?index:8), &rByte,(AddrType)AddrType_byte)){
  88.                                                         errRes= ERR_DATA_SAVE;
  89.                                                         goto _exit;
  90.                                                 }
  91.                                                 wAddr += ((index<8)?index:8);
  92.                                                 index-=8;
  93.                                         }
  94. //                                        /*释放通道*/
  95. //                                        pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;
  96.                                         /*从机收到*/
  97.                                                 pModbus_RTU_CB->sendFlag=2;
  98.                                         errRes= ERR_RW_FIN;
  99.                                         goto _exit;
  100.                                 }
  101.                                 case 0x3:/*读保持寄存器*/
  102.                                 case 0x4:/*读输入寄存器*/
  103.                                 {
  104.                                         uint16 i;
  105.                                         uint16 len;
  106.                                         MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte);
  107.                                         if((byte+2)!=MDQueueLength(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue))){
  108.                                                 /*长度错误*/
  109.                                                 errRes= ERR_DATA_LEN;
  110.                                                 goto _exit;
  111.                                         }
  112.                                         len=byte>>1;
  113.                                         for(i=0;i<len ;i++){
  114.                                                 uint16         wTemp;
  115.                                                 uint8                rByte;
  116.                                                 MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte);
  117.                                                 wTemp=(rByte<<8);
  118.                                                 MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte);
  119.                                                 wTemp|=rByte;
  120.                                                 if(!MDM_RTU_InsideWriteRegs(pModbus_RTU_CB->pModbus_RTU,startAddr+i,1,&wTemp,0,(AddrType)AddrType_byte)){
  121.                                                         errRes= ERR_DATA_SAVE;
  122.                                                         goto _exit;
  123.                                                 }
  124.                                         }
  125.                                                 pModbus_RTU_CB->sendFlag=2;
  126.                                         errRes= ERR_RW_FIN;
  127.                                         goto _exit;
  128.                                 }        
  129.                                 
  130.                                 case 0x5:/*写单线圈*/
  131.                                 case 0x6:        /*写单个寄存器*/
  132.                                 {
  133.                                         uint16 res;
  134.                                         if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){
  135.                                                 errRes= ERR_DATA_LEN;
  136.                                                 goto _exit;
  137.                                         }
  138.                                         /*返回地址不匹配错误*/
  139.                                         if(res!=startAddr){
  140.                                                 errRes= ERR_WRITE_COIL;
  141.                                                 goto _exit;
  142.                                         }
  143.                                         if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){
  144.                                                 errRes= ERR_DATA_LEN;
  145.                                                 goto _exit;
  146.                                         }
  147.                                         /*返回数据不匹配*/
  148.                                         if(res!=*((uint16*)wData)){
  149.                                                 errRes= ERR_WRITE_COIL;
  150.                                                 goto _exit;
  151.                                         }
  152.                                                 pModbus_RTU_CB->sendFlag=2;
  153.                                         errRes= ERR_RW_FIN;
  154.                                         goto _exit;
  155.                                 }
  156.                                 case 0x0F:        /*写多线圈*/
  157.                                 case 0x10:{        /*写多寄存器*/
  158.                                         uint16 res;
  159.                                         if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){
  160.                                                 errRes= ERR_DATA_LEN;
  161.                                                 goto _exit;
  162.                                         }
  163.                                         /*返回地址不匹配错误*/
  164.                                         if(res!=startAddr){
  165.                                                 errRes= ERR_WRITE_COIL;
  166.                                                 goto _exit;
  167.                                         }
  168.                                         if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){
  169.                                                 errRes= ERR_DATA_LEN;
  170.                                                 goto _exit;
  171.                                         }
  172.                                         /*返回数据不匹配*/
  173.                                         if(res!=numOf){
  174.                                                 errRes= ERR_WRITE_COIL;
  175.                                                 goto _exit;
  176.                                         }
  177.                                         pModbus_RTU_CB->sendFlag=2;
  178.                                         errRes= ERR_RW_FIN;
  179.                                         goto _exit;
  180.                                 }
  181.                                 case 0x81: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_COIL; goto _exit;                        /*读线圈异常*/
  182.                                 case 0x82: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_INPUT; goto _exit;                        /*读输入离散量异常*/
  183.                                 case 0x83: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_HOLD_REG; goto _exit;        /*读保持寄存器错误*/
  184.                                 case 0x84: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_INPUT_REG; goto _exit;        /*读输入寄存器错误*/
  185.                                 case 0x85: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_COIL; goto _exit;                        /*写单线圈错误*/
  186.                                 case 0x86: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_REG; goto _exit;                        /*写单寄错误*/
  187.                                 case 0x8F: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_COIL; goto _exit;                        /*写多线圈错误*/        
  188.                                 case 0x90: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_REG; goto _exit;                        /*写多寄存器错误*/        
  189.                         }        

  190.                 }
  191.                 if(pModbus_RTU_CB->sendFlag==2){/*如果发送成功则进行从新发送*/
  192.                         /*定时重发*/
  193.                         if(pModbus_RTU_CB->pModbus_RTU->timesTick-pModbus_RTU_CB->sendTimeTick
  194.                                 >=pModbus_RTU_CB->sendIntervalTime){
  195.                                 /*重新发送*/
  196.                                 //MD_CLR_SENDED_FLAG(pModbus_RTU_CB);
  197.                                 pModbus_RTU_CB->sendFlag=0;
  198.         //                        /*释放通道*/
  199.         //                        pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;
  200.                                 errRes= ERR_NONE;
  201.                                 goto _exit;
  202.                         }
  203.                 }else if(pModbus_RTU_CB->sendFlag==1 || pModbus_RTU_CB->sendFlag==3){/*已经发送了,但是还没收到反馈,则执行超时检测*/               
  204.                         /*接收超时检测*/
  205.                         if(pModbus_RTU_CB->pModbus_RTU->timesTick-pModbus_RTU_CB->sendTimeTick
  206.                                 >=pModbus_RTU_CB->sendOverTime){
  207.                                         /*设置超时时间起点*/
  208.                                         pModbus_RTU_CB->sendTimeTick=pModbus_RTU_CB->pModbus_RTU->timesTick;
  209.                                         /*重新发送*/
  210.                                         pModbus_RTU_CB->sendFlag=0;
  211.                                         /*重传次数+1*/
  212.                                         pModbus_RTU_CB->RTCount++;
  213.                                        
  214.                                         /*释放通道*/
  215.                                         pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;
  216.                                        
  217.                                         if(pModbus_RTU_CB->RTCount>=pModbus_RTU_CB->RTTimes){
  218.                                                 /*重传次数超了*/
  219.                                                 errRes= ERR_RW_OV_TIME_ERR;
  220.                                                 goto _exit;
  221.                                         }
  222.                                         /*超时了*/
  223.                                         errRes= ERR_OVER_TIME;
  224.                                         goto _exit;
  225.                         }
  226.                 }
  227.         }else {
  228.                 /*重传次数超了*/
  229.                 errRes= ERR_RW_OV_TIME_ERR;
  230.                 goto _exit;
  231.         }

  232.         if(pModbus_RTU_CB->sendFlag==1){/*已经发送过则返回发送完成标志*/
  233.                 return ERR_SEND_FIN;
  234.         }
  235. _exit:
  236. //        MD_CLR_SENDED_FLAG(pModbus_RTU_CB);
  237. //        if(errRes == ERR_RW_FIN){
  238. //                pModbus_RTU_CB->RTCount=0;
  239. //        }
  240.         /*释放通道*/
  241.         pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;
  242.         return errRes;
  243. }
复制代码
另外头文件包含关系稍微有点混乱,不过也没错误


crc函数写的不对   MD_RTU_CRC16_FAST_MODE=0时候错误
修改如下
  1. uint16 MD_CRC16Update(uint16 CRC, uint8 byte)
  2. {
  3. #if MD_RTU_CRC16_FAST_MODE
  4.          return (((CRC) >> 8) ^ crc16_table[((CRC) ^ byte) & 0xff]);
  5. #else
  6.   int i;
  7.   CRC ^= byte;
  8.   for (i = 0; i < 8; ++i)
  9.   {
  10.     if (CRC & 1)
  11.       CRC = (CRC >> 1) ^ 0xA001;
  12.     else
  13.       CRC = (CRC >> 1);
  14.   }

  15.   return CRC;
  16. #endif
  17. }
复制代码


回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-23 19:02:37 | 显示全部楼层
nashui_sx 发表于 2020-4-23 10:57
简单看了下 很不错 裸机以后试试你这个

多谢,确实存在这个bug,会立刻修正这个bug
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-23 20:45:38 | 显示全部楼层
BUG已经修正
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-23 20:52:51 | 显示全部楼层
2020/4/23 Slave         修复CRC宏的一个BUG。<br>                 修复离散映射表主从机大小不一致的BUG。<br> Master        修复读命令,因变量从用导致错误的BUG。<br> 串口初始化位置修改到MD_RTU_Serial.c 与 MDM_RTU_Serial.c内。<br> 修正一些命名规范。<br>
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-23 20:53:17 | 显示全部楼层
2020/4/23
Slave         修复CRC宏的一个BUG。<br>
                修复离散映射表主从机大小不一致的BUG。<br>
Master        修复读命令,因变量从用导致错误的BUG。<br>
串口初始化位置修改到MD_RTU_Serial.c 与 MDM_RTU_Serial.c内。<br>
修正一些命名规范。<br>
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2019-7-11
在线时间
21 小时
发表于 2020-4-27 10:25:42 | 显示全部楼层
非常支持楼主
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-4-28 16:49:14 | 显示全部楼层

欢迎交流
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-6-8 09:39:47 | 显示全部楼层
2020/6/6 修正一个大小端错误。
Slaver 修正离散映射函数读取的错误。
从机支持广播地址。
Master 主机添加发送缓存。

2020/4/28 Master 主机的离散映射将必须指定从机号,不在采用共用方式。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2019-8-24
在线时间
1 小时
发表于 2020-6-10 10:36:16 | 显示全部楼层
有没有关于modbus的项目使用的 关于参数保存(eeprom spi flash)的项目
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-6-10 23:11:51 | 显示全部楼层
lilong8470 发表于 2020-6-10 10:36
有没有关于modbus的项目使用的 关于参数保存(eeprom spi flash)的项目

参数保存,用库加eeprom应该很好实现
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2020-8-8
在线时间
7 小时
发表于 2020-8-8 16:28:39 | 显示全部楼层
谢谢楼主
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2020-8-20
在线时间
13 小时
发表于 2020-8-29 17:31:31 | 显示全部楼层
本帖最后由 秋名山藤原拓海 于 2020-8-29 21:27 编辑

楼主大神,在用你的这个程序,我发现个不理解的地方。就是在读取保存寄存器数据,超过5个寄存器时,会出现,读出来的数据重新开始第一个数据的结果,十分疑惑,如下图,但是我看了半天感觉好像你的程序没错啊,我查找不出原因,万望赐教!
QQ图片20200829173009.png
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2020-8-20
在线时间
13 小时
发表于 2020-8-29 22:46:39 | 显示全部楼层
楼主大神,我运行你的程序的时候发现个问题,就是程序当作从机使用时,读保持寄存器的数据,超过5个寄存器时,会出现读取的数据是只有前五个是对的,接下来的数据又从第一个开始,我看了很久的代码还是找不出原因,希望楼主走一波自己的程序看看,看看是什么问题,万分感谢!
QQ图片20200829173009.png
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2020-8-20
在线时间
13 小时
发表于 2020-8-30 15:40:11 | 显示全部楼层
你好,楼主,我使用了你的Xtinymodbus的程序,发现在从机程序中,读保持寄存器的参数值,在第五个之后就会回到第一个值,我很疑惑,查看了你的代码很多次,还是没发现错误,希望赐教,谢谢你。
QQ图片20200829173009.png
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-9-23 11:46:50 | 显示全部楼层
秋名山藤原拓海 发表于 2020-8-30 15:40
你好,楼主,我使用了你的Xtinymodbus的程序,发现在从机程序中,读保持寄存器的参数值,在第五个之后就会 ...

请查看MDS_RTU_APP.c 下的MDS_RTU_UserUpdate函数,新版本已经更新:2020/9/24 <br>
增加从机掉线不轮询功能,主机可以使用MDM_RTU_CB_SetDisPollEnFlag函数进行设置,<br>
可以使用MDM_RTU_CB_ClrDisFlag函数进行复位。<br>
增加简单的主机发送控制器。<br>
修复主机阻塞模式和非阻塞模式混合调用的BUG。<br>
代码中所有注释修改为英文。<br>
回复 支持 反对

使用道具 举报

5

主题

152

帖子

0

精华

高级会员

Rank: 4

积分
777
金钱
777
注册时间
2016-7-15
在线时间
119 小时
发表于 2020-10-14 20:12:10 | 显示全部楼层
goto语句用多了出问题很难调试
好好学习,天天向上。
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-10-27 11:57:33 | 显示全部楼层
小程序员 发表于 2020-10-14 20:12
goto语句用多了出问题很难调试

推荐你学习下goto在什么时候用比较合理
回复 支持 反对

使用道具 举报

0

主题

46

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
489
金钱
489
注册时间
2019-1-12
在线时间
65 小时
发表于 2020-11-12 16:27:25 | 显示全部楼层
感谢分享,楼主的代码很给力&……
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2014-5-25
在线时间
65 小时
 楼主| 发表于 2020-11-25 22:04:56 | 显示全部楼层
2020/11/23
优化从机协议解析策略,更加稳定
优化循环队列,使得其适应性更强
循环队列内存修改为用户指定
主机增加RTOS支持,可以通过MD_RTU_Config.h下的MD_RTU_USED_OS开启,默认关闭,已经移植好XTinyRTOS,可以通过修改MD_RTU_Sysinterface.c进行移植
其它修改及优化
回复 支持 反对

使用道具 举报

9

主题

119

帖子

0

精华

高级会员

Rank: 4

积分
742
金钱
742
注册时间
2014-7-8
在线时间
97 小时
发表于 2020-11-27 16:18:03 | 显示全部楼层
谢谢分享,后面会继续关注!
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-6-8 15:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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