搜索
bottom↓
楼主: sunnydragon

【开源】自己重构的FreeModbus主机+从机协议栈

  [复制链接]

出0入198汤圆

 楼主| 发表于 2015-11-21 20:20:06 | 显示全部楼层
xh2008email 发表于 2015-11-21 13:18
我没有理解,老大扫一下盲

不明白自己看文档吧,文档说的太清楚不过了。https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32#三api

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-11-30 09:59:51 | 显示全部楼层
modbus主机从机协议栈,mark,谢谢楼主分享!牛!!

出0入0汤圆

发表于 2016-1-16 19:39:02 | 显示全部楼层
楼主你好,看了你的代码,写的非常好,佩服!

我有一些阅读体会,不知道是不是正确:
感觉是提供了一个modbus的框架,让应用者只需要 调用API接口功能函数,然后结果就在buffer了。解放了应用者。
核心任务poll就是个状态机,甚至可以理解成一个简单的调度器。这个调度器 一方面接收请求,另一方面输出响应,耦合小。

我还有点疑惑,想请求指教:
我觉得,如果请求方法是非阻塞的,我觉得这样用才能体现它的优势啊。代码上清晰移植性高,系统上无论是负荷还是响应速度都不影响,甚至更好。
如果是阻塞的,和我直接write,然后read 这种方式 没有什么优势啊,从对系统的负荷 和 响应速度上讲。

当然作为一个框架的作者,能支持所有的这些阻塞或者是非阻塞是最好了。这我也能够理解。
所以我看到你举的例子thread_entry_SysMonitor()里调用的那些接口都设成了RT_WAITING_FOREVER不太能显示出优势,是不是例子写成非阻塞的,至少是部分是非阻塞的话给使用者作为参考例子是不是更好呢。

出0入198汤圆

 楼主| 发表于 2016-1-16 23:14:27 | 显示全部楼层
imjacob 发表于 2016-1-16 19:39
楼主你好,看了你的代码,写的非常好,佩服!

我有一些阅读体会,不知道是不是正确:

感谢你的建议哈,不过我不太赞同你说的在非阻塞模式下:“代码上清晰移植性高,系统上无论是负荷还是响应速度都不影响,甚至更好”
1、非阻塞的代码都是异步方式执行,这种异步方式由于需要并行,往往需要同时考虑更多条件,这样就会增加代码量,影响代码结构,降低可读性及可移植性;
2、对于负荷及响应速度,写数据到从机肯定会提高,后期也可以对写操作增加非阻塞接口。但是读数据没有影响,即便非阻塞方式迅速返回,但此时用户也无法获取到当前最新的数据。所以我更建议用户能够有专门的数据刷新线程,在应用层与数据刷新线程有共用的数据缓冲区(PS:我之前还做过一个数据变化自动进行事件通知的库,就是用在 Modbus 数据刷新场景,如果有兴趣,可以再看下这里:https://github.com/armink/EasyDataManager)。

对于你说的“我看到你举的例子thread_entry_SysMonitor()里调用的那些接口都设成了RT_WAITING_FOREVER不太能显示出优势”,我没理解你说的优势是什么。

出0入0汤圆

发表于 2016-1-17 11:01:10 | 显示全部楼层
sunnydragon 发表于 2016-1-16 23:14
感谢你的建议哈,不过我不太赞同你说的在非阻塞模式下:“代码上清晰移植性高,系统上无论是负荷还是响应 ...

感谢回复,但看了后,我又有点疑问了,如下,

1.“后期也可以对写操作增加非阻塞接口”,我看了你在120楼说 是 支持非阻塞访问的,为何还说要 在后期增加。    然后 你在 1楼的介绍中第5条写 “目前的Modbus主机请求功能是异步模式”。 你在github的Readme中又这样描述“所有的主机请求方法都是线程安全的也是阻塞模式的” 。 我的理解 异步 就类似非阻塞的。同步类似 阻塞的。我有点搞不清楚状况了。


2.你现在写成了RT_WAITING_FOREVER, 不就是阻塞了吗? 我说的这种情况下“不太能显示出优势”,是和 不用你这种框架的情况比较,例如直接写出类似以下:

  1. status = write();//非阻塞去写

  2. status =read();//阻塞去读,当然要加超时判断。
复制代码


这种思维方式简单明了,当然通用性不好。还有就是若两个线程都调用这段代码,会有问题。但如果限定在只会在同一个线程调用,也就不存在这个问题了。我就在想这种情况下,用你的框架 优势在哪里呢?




出0入198汤圆

 楼主| 发表于 2016-1-17 22:40:54 | 显示全部楼层
imjacob 发表于 2016-1-17 11:01
感谢回复,但看了后,我又有点疑问了,如下,

1.“后期也可以对写操作增加非阻塞接口”,我看了你在120 ...

1、是这样的,早期的代码就是非阻塞模式的,即1楼位置的代码,但后来统一修改为阻塞模式了,所以你在 Github 上看到的代码就是阻塞模式。

2、具体哪种方式更有优势,这个也要看用户的使用场景。有些时候用户写数据时,必须要求写成功才能执行接下来的业务,此时使用非阻塞模式是毫无意义的,但有些场景下,可能不需要关心写数据的结果。所以两种方式都支持,让用户自己选择,这样做更加灵活。

出0入0汤圆

发表于 2016-1-18 09:10:12 | 显示全部楼层
阻塞的方法更好写,非阻塞的很难实现统一,然后程序又比较复杂,而阻塞的方式无非就建立一个收发线程而已,与普通的单片机收发能统一起来

出0入0汤圆

发表于 2016-2-19 22:10:37 | 显示全部楼层
谢谢楼主的代码!
有个问题想向楼主请教,
Modbus ascii中 要求串口的默认配置为 1起始位,7数据位,1位偶校验,1停止位
你公开的代码中,有MB_SLAVE_ASCII_ENABLED 和 MB_MASTER_ASCII_ENABLED,但串口的驱动中,没有体现出来7数据位

请问楼主有没有1起始位,7数据位,1位偶校验,1停止位的stm32串口驱动代码,或者如何实现?  stm32函数库中只有8位和9位的
谢谢

出0入0汤圆

发表于 2016-3-17 08:42:23 | 显示全部楼层
顶起  这个太有用了

出0入0汤圆

发表于 2016-4-21 16:29:44 | 显示全部楼层
谢谢楼主的分享,节约了好多时间

出0入10汤圆

发表于 2016-4-21 21:49:16 来自手机 | 显示全部楼层
狂顶一个

出0入0汤圆

发表于 2016-7-4 21:20:00 | 显示全部楼层
if ((usAddress >= REG_HOLDING_START)
            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
    {
        iRegIndex = usAddress - usRegHoldStart;
        switch (eMode)
        {
        /* read current register values from the protocol stack. */
        case MB_REG_READ:
            while (usNRegs > 0)
            {
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                iRegIndex++;
                usNRegs--;
            }
            break;
        /* write current register values with new values from the protocol stack. */
        case MB_REG_WRITE:
            while (usNRegs > 0)
            {
                pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                iRegIndex++;
                usNRegs--;
            }
            break;
        }
}
从这程序来看读寄存器是把主机的发给从机?不是读从机的保持寄存器回来吗?

出0入0汤圆

发表于 2016-7-4 21:32:57 | 显示全部楼层
非常不错,帮你顶。有时间研究研究

出0入0汤圆

发表于 2016-7-29 08:51:56 | 显示全部楼层
撸主好强大威武,本屌丝要拿来慢慢学习一番~~~~哈哈哈哈哈

出0入0汤圆

发表于 2016-7-29 15:49:39 | 显示全部楼层
正好需要modbus 主机的程序。。。拿走研究下

出0入0汤圆

发表于 2016-7-29 15:50:29 | 显示全部楼层
正好需要modbus 主机的程序。。。拿走研究下

出0入0汤圆

发表于 2016-7-30 18:04:57 | 显示全部楼层

非常不错,用到的时候很难找。

出0入0汤圆

发表于 2016-8-1 13:37:16 | 显示全部楼层
东西太繁琐了,代码效率太低了,还是谢谢楼主分享

出0入0汤圆

发表于 2016-8-11 15:29:38 | 显示全部楼层
好贴 学习了

出0入0汤圆

发表于 2016-8-27 09:07:54 | 显示全部楼层
mark FreeModbus主机+从机协议栈

出0入0汤圆

发表于 2016-9-4 20:06:46 | 显示全部楼层
支持楼主,感谢共享!

出0入0汤圆

发表于 2016-9-7 12:13:47 | 显示全部楼层
不改变字符间的超时判断机制以及其它的影响时序的因素注定MODBUS只能用在对时序要求低的场合MODBUS TCP也是,最大的优势是推出的时间早、开源、支持该协议的自动化厂家最多。

出0入0汤圆

发表于 2016-9-7 14:31:51 | 显示全部楼层
谢谢了,下载来学习一下。

出0入0汤圆

发表于 2016-10-13 14:46:12 | 显示全部楼层
楼主好,刚刚再看源码,有点疑问FreeModbus 的CRC校验检验这里是不是错了??
  1. eMBErrorCode
  2. eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
  3. {
  4.     BOOL            xFrameReceived = FALSE;
  5.     eMBErrorCode    eStatus = MB_ENOERR;

  6.     ENTER_CRITICAL_SECTION(  );
  7.     assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );

  8.     /* Length and CRC check */
  9.     if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
  10.         && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) )
  11.     {
  12.         /* Save the address field. All frames are passed to the upper layed
  13.          * and the decision if a frame is used is done there.
  14.          */
  15.         *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF];

  16.         /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
  17.          * size of address field and CRC checksum.
  18.          */
  19.         *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );

  20.         /* Return the start of the Modbus PDU to the caller. */
  21.         *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF];
  22.         xFrameReceived = TRUE;
  23.     }
  24.     else
  25.     {
  26.         eStatus = MB_EIO;
  27.     }

  28.     EXIT_CRITICAL_SECTION(  );
  29.     return eStatus;
  30. }
复制代码


usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 这里应该改成!=0 吧?

还有一点疑问,总感觉这样校验不稳妥,最好是不是应该把数据帧里面的CRC拿出来和自己计算的这个比对一下?

出0入198汤圆

 楼主| 发表于 2016-10-13 20:44:17 | 显示全部楼层
生来孤独 发表于 2016-10-13 14:46
楼主好,刚刚再看源码,有点疑问FreeModbus 的CRC校验检验这里是不是错了??

没有错误,这就是 CRC 的特性。简单点的理解可以认为是“正负”相互抵消。

出0入0汤圆

发表于 2016-10-13 22:59:30 | 显示全部楼层
这个下载学习

出0入0汤圆

发表于 2016-10-14 08:05:52 | 显示全部楼层
sunnydragon 发表于 2016-10-13 20:44
没有错误,这就是 CRC 的特性。简单点的理解可以认为是“正负”相互抵消。 ...

奥,这样,基础不扎实,要去查阅学习一下了

出0入198汤圆

 楼主| 发表于 2016-10-14 08:31:36 | 显示全部楼层
生来孤独 发表于 2016-10-14 08:05
奥,这样,基础不扎实,要去查阅学习一下了

这也是个技巧,还可以降低代码量

出0入0汤圆

发表于 2016-10-15 00:21:37 | 显示全部楼层
sunnydragon 发表于 2016-10-14 08:31
这也是个技巧,还可以降低代码量

楼主你好!如果我想将你的代码不用操作系统需要注意什么呢。

出0入198汤圆

 楼主| 发表于 2016-10-15 09:24:56 | 显示全部楼层
596142041 发表于 2016-10-15 00:21
楼主你好!如果我想将你的代码不用操作系统需要注意什么呢。

要注意主从机事件处理接口的移植。

出0入17汤圆

发表于 2016-10-15 15:15:27 | 显示全部楼层
必须看下

出0入0汤圆

发表于 2016-10-15 19:21:05 | 显示全部楼层
sunnydragon 发表于 2016-10-15 09:24
要注意主从机事件处理接口的移植。

是的,我能否按照原来官方提供的例程那样来处理呢。用一个全局变量来进行

出0入198汤圆

 楼主| 发表于 2016-10-15 19:52:30 | 显示全部楼层
596142041 发表于 2016-10-15 19:21
是的,我能否按照原来官方提供的例程那样来处理呢。用一个全局变量来进行 ...

从机肯定没问题,主机恐怕不行吧。

出0入0汤圆

发表于 2016-12-19 19:47:24 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2017-4-6 14:44:32 | 显示全部楼层
高手呀,我不得不顶呀。大神呀

出0入0汤圆

发表于 2017-5-14 02:45:01 | 显示全部楼层
今天测试了下,芯片换成STM32F103RCT6 发现 从机的        eMBPoll(); 函数执行第二遍的时候会死掉。仔细跟踪发现在第二次调用 xMBPortEventGet( &eEvent ) 这个函数判断后,void thread_entry_ModbusSlavePoll(void* parameter) 进程就会死掉,不执行。只剩下 void thread_entry_SysMonitor(void* parameter) 和 void thread_entry_ModbusMasterPoll(void* parameter) 在执行了。
// <o> Internal SRAM memory size[Kbytes] <8-64>
//        <i>Default: 64
#define STM32_SRAM_SIZE         48
#define STM32_SRAM_END          (0x20000000 + STM32_SRAM_SIZE * 1024)
赢更改。

出0入0汤圆

发表于 2017-5-14 02:59:38 | 显示全部楼层
rt_event_recv(&xSlaveOsEvent,
            EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT,
            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
            &recvedEvent);
在调用这个函数时候死掉的

出0入0汤圆

发表于 2017-6-15 22:42:05 | 显示全部楼层
谢谢,备用一下。modbus主从机

出0入0汤圆

发表于 2017-6-16 09:28:18 | 显示全部楼层
先收着,谢谢了

出0入0汤圆

发表于 2017-10-11 16:49:38 | 显示全部楼层
为什么不使用DMA发送数据?

出0入0汤圆

发表于 2017-10-17 10:19:27 | 显示全部楼层
主机模式一直通信不上,

出0入0汤圆

发表于 2017-10-20 12:59:14 | 显示全部楼层
致敬,这样的帖子为啥不是精华了呢?

出0入0汤圆

发表于 2017-12-13 08:48:46 | 显示全部楼层
FreeModbus主机源码,关注~ 支持~

出0入0汤圆

发表于 2018-3-12 09:22:39 | 显示全部楼层
/**
* Modbus master holding register callback function.
*
* @param pucRegBuffer holding register buffer
* @param usAddress holding register address
* @param usNRegs holding register number
* @param eMode read or write
*
* @return result
*/
eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
        USHORT usNRegs, eMBRegisterMode eMode)
{
    eMBErrorCode    eStatus = MB_ENOERR;
    USHORT          iRegIndex;
    USHORT *        pusRegHoldingBuf;
    USHORT          REG_HOLDING_START;
    USHORT          REG_HOLDING_NREGS;
    USHORT          usRegHoldStart;

    pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
    REG_HOLDING_START = M_REG_HOLDING_START;
    REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
    usRegHoldStart = usMRegHoldStart;
    /* if mode is read, the master will write the received date to buffer. */
    eMode = MB_REG_WRITE;

    /* it already plus one in modbus function method. */
    usAddress--;

    if ((usAddress >= REG_HOLDING_START)
            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
    {
        iRegIndex = usAddress - usRegHoldStart;
        switch (eMode)
        {
        /* read current register values from the protocol stack. */
        case MB_REG_READ:
            while (usNRegs > 0)
            {
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                iRegIndex++;
                usNRegs--;
            }
            break;
        /* write current register values with new values from the protocol stack. */
        case MB_REG_WRITE:
            while (usNRegs > 0)
            {
                pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                iRegIndex++;
                usNRegs--;
            }
            break;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}

/**
主机模式的eMBMasterRegHoldingCB函数里的红色部分,被强制为写了,对吗?去掉这句,读回来的数据会被清掉,怎么解决?
**/

出0入198汤圆

 楼主| 发表于 2018-3-12 21:42:37 | 显示全部楼层
cqfeiyu 发表于 2018-3-12 09:22
/**
* Modbus master holding register callback function.
*

没问题的,那个只是为了缓存从机的寄存器数据

出0入0汤圆

发表于 2018-3-24 00:00:48 | 显示全部楼层
写得不错,这么多年了楼主也还热心解答问题,不知道读数据时缓冲区太大的问题解决了没有,有时候需要读取的寄存器地址范围比较宽,那么缓存就得开得很大,这样很浪费资源

出0入198汤圆

 楼主| 发表于 2018-3-24 12:53:55 | 显示全部楼层
WinExt 发表于 2018-3-24 00:00
写得不错,这么多年了楼主也还热心解答问题,不知道读数据时缓冲区太大的问题解决了没有,有时候需要读取的 ...

你是指的本地对 寄存器数据 缓存的那一堆数组吗?比如:https://github.com/armink/FreeMo ... t/user_mb_app.c#L43

出0入0汤圆

发表于 2018-3-25 00:47:31 | 显示全部楼层
sunnydragon 发表于 2018-3-24 12:53
你是指的本地对 寄存器数据 缓存的那一堆数组吗?比如:https://github.com/armink/FreeModbus_Slave-Mas ...

作为主机去读从机的保持寄存器时定义了下面的数组

usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]

在回调函数里是判断合法性:

if( ( usAddress >= REG_HOLDING_START ) &&
         ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
        iRegIndex = usAddress - usRegHoldStart;
}

下面取得从机寄存器的值
         pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
         pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;


关键在与iRegIndex的计算,例如我只需要读取0x0001和 0xF813这两个寄存器的时候,此时 REG_HOLDING_NREGS希望定义为 2(两个寄存器),但是这样地址合法性判断不通过,所以

REG_HOLDING_NREGS 需要定义为 0xF813或者更大,pusRegHoldingBuf的长度出能满足(也就是说 pusRegHoldingBuf[iRegIndex]  不溢出)。

这样分析下来为了获取两个寄存器的数据却要定义一个很长的数组,很浪费资源。,不知我的理解是否有误?

另外,我移植主机部分到FreeRTOS上,跟电脑的SLAVE软件通信能正常读到数据,但是运行一定的时间(可能是10来秒)之后程序就挂了,

屏蔽掉读寄存器的语句后系统能正常运行(此时 eMBMasterPoll 没有屏蔽),这是什么原因呢?

出0入198汤圆

 楼主| 发表于 2018-3-25 16:16:17 | 显示全部楼层
WinExt 发表于 2018-3-25 00:47
作为主机去读从机的保持寄存器时定义了下面的数组

usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOL ...

其实数组方式只是 Modbus 寄存器数据一种缓冲方式,本身 FreeModbus 非常灵活,对于缓冲方式是可以由用户来决定的。只是数组模式作为顺序存储的模式,非常简单,容易实现,被作为最常见的 demo 提供出来。

比如 这里(https://github.com/armink/EasyDataManager) 有我之前专门为 Modbus 设计的一款数据缓存系统,采用链式存储的方式,支持数据变化主动通知,完全采用事件驱动模式编程。

你的程序具体挂掉的原因,要先定位到执行的代码才好接下来深入分析。

出0入0汤圆

发表于 2018-3-26 10:42:20 | 显示全部楼层
sunnydragon 发表于 2018-3-25 16:16
其实数组方式只是 Modbus 寄存器数据一种缓冲方式,本身 FreeModbus 非常灵活,对于缓冲方式是可以由用户 ...

程序挂掉的问题找到了,移入FreeRTOS时3.5定时器和串口中断没有做好临界保护,加上去就可以了。

接收缓存也根据自己的需求修改。

感谢你的热心解答和无私奉献。

出0入198汤圆

 楼主| 发表于 2018-3-26 12:39:59 | 显示全部楼层
WinExt 发表于 2018-3-26 10:42
程序挂掉的问题找到了,移入FreeRTOS时3.5定时器和串口中断没有做好临界保护,加上去就可以了。

接收缓 ...

接收缓存如果能做成通用方案,欢迎分享出来哈~

出0入0汤圆

发表于 2018-3-27 23:26:06 | 显示全部楼层
sunnydragon 发表于 2018-3-26 12:39
接收缓存如果能做成通用方案,欢迎分享出来哈~

抱歉我并没有做成通用的,只是根据自己需要,将需要通信的寄存器事先存入一个结构体数组里,结构体里寄存器与数据缓存一一对应,这样读寄存器时就存到对应的缓存上。

出0入0汤圆

发表于 2018-4-21 22:40:37 | 显示全部楼层
sunnydragon 发表于 2018-3-26 12:39
接收缓存如果能做成通用方案,欢迎分享出来哈~

最新代码在哪里下载  github 上不去了

出0入198汤圆

 楼主| 发表于 2018-4-22 09:04:05 | 显示全部楼层
305546594 发表于 2018-4-21 22:40
最新代码在哪里下载  github 上不去了

OSChina 上也有同步 : https://gitee.com/Armink/FreeModbus_Slave-Master-RTT-STM32

出0入0汤圆

发表于 2018-4-22 11:25:20 | 显示全部楼层
关注,支持。

出0入0汤圆

发表于 2018-4-23 21:29:34 | 显示全部楼层
本帖最后由 305546594 于 2018-4-23 22:17 编辑


没有问题  我的测试软件 的问题

出0入0汤圆

发表于 2018-4-26 10:35:31 | 显示全部楼层
sunnydragon 发表于 2018-4-22 09:04
OSChina 上也有同步 : https://gitee.com/Armink/FreeModbus_Slave-Master-RTT-STM32

主机轮训  有么有相关参考程序  楼主能不能出个主机轮训相关的应用贴,体现错误重发机制。

出0入0汤圆

发表于 2018-4-26 18:53:33 | 显示全部楼层
好资料!

出0入198汤圆

 楼主| 发表于 2018-4-26 19:22:43 | 显示全部楼层
305546594 发表于 2018-4-26 10:35
主机轮训  有么有相关参考程序  楼主能不能出个主机轮训相关的应用贴,体现错误重发机制。  ...


这里有主机测试函数:https://github.com/armink/FreeMo ... /app_task.c#L54-L62

这里也有说明文章:https://blog.csdn.net/arminkztl/article/details/11738395

关于应用贴,我都好几年没碰 Modbus 了,现在连测试环境都没了。如果你学会了,欢迎分享给大家哈。

出0入0汤圆

发表于 2018-5-31 09:36:01 | 显示全部楼层
十分感谢,mark

出0入0汤圆

发表于 2018-6-9 10:49:22 | 显示全部楼层
sunnydragon 发表于 2018-4-26 19:22
这里有主机测试函数:https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32/blob/master/APP/sr ...

你好,请问有裸机移植的代码吗?

出0入0汤圆

发表于 2018-7-7 09:27:18 | 显示全部楼层
sunnydragon 发表于 2018-4-26 19:22
这里有主机测试函数:https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32/blob/master/APP/sr ...

楼主,我现在发现,第一次发送数据会少了第一个字节,后面就好了,每次上电第一次发送都会少第一个字节,有碰到过吗

出0入0汤圆

发表于 2018-7-7 10:03:00 | 显示全部楼层
谢谢楼主分享。

出0入198汤圆

 楼主| 发表于 2018-7-7 11:12:00 | 显示全部楼层
chenweigang 发表于 2018-7-7 09:27
楼主,我现在发现,第一次发送数据会少了第一个字节,后面就好了,每次上电第一次发送都会少第一个字节, ...

这个是挺常见的驱动问题,你可以百度,关键词:STM32 串口发送 第一个字节 丢失

出0入0汤圆

发表于 2018-7-7 15:43:23 | 显示全部楼层
sunnydragon 发表于 2018-7-7 11:12
这个是挺常见的驱动问题,你可以百度,关键词:STM32 串口发送 第一个字节 丢失
...

感谢楼主指点,敬大佬

出0入0汤圆

发表于 2018-7-17 13:00:16 | 显示全部楼层
兄台现在在rt thread,而且还是核心人物哦,挺厉害的

出0入0汤圆

发表于 2018-7-17 13:13:42 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2018-7-21 11:08:49 | 显示全部楼层
本帖最后由 myxiaonia 于 2018-7-21 11:15 编辑
zhangshixing 发表于 2014-7-17 12:59
我发现freemodbus从机接收完一帧,并没有关闭接收,请问下楼主这样有没有问题啊。。。。


你说的有道理,确实存在这种问题,也就是协议存在安全漏洞,可能被不法者破坏网络运行。。。

但是从modbus的规范来看,这种情况是很大可能不会发生的,从机接收消息后,主机肯定是在等待响应,这个时间窗口应该足够从机响应的(指接收消息,处理,准备发送响应前的这段时间)。从机应该认真考虑主机等待响应的这个时间窗口。

我曾经也给rtx提过你说的这种bug,属于代码上有漏洞,但是原理上没问题。严格说也是bug,就看怎么看待了。
看过ucos和rtx的代码,就能发现这种巨大的思路差别,rtx代码很少有非法情况处理,ucos从头开始就不信任用户。是不是也反应了欧洲人和美国人的思维方式

出0入0汤圆

发表于 2018-7-23 10:47:19 | 显示全部楼层
不知道楼主还能够回复疑问不,主机模式下,如果要求读取消息,例如读输入寄存器
  1. eMBException
  2. eMBMasterReqReadInputRegister( UCHAR ucSlaveAddress, USHORT usRegAddr, USHORT usNRegs)
复制代码

这个函数即使返回成功的话,请问读取的数据保存在哪里

出0入198汤圆

 楼主| 发表于 2018-7-23 11:04:33 | 显示全部楼层
myxiaonia 发表于 2018-7-23 10:47
不知道楼主还能够回复疑问不,主机模式下,如果要求读取消息,例如读输入寄存器

这个函数即使返回成功的话 ...



位于 Modbus 主机缓冲区中,在 GitHub 的 readme 有介绍哦

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2018-8-25 16:04:16 | 显示全部楼层
我提个意见,不知道对不对
lwip提供了3种接口,raw模式是基于回调的,socket模式是同步的,netcon我不清楚不讨论

类比对照,freemodbus的从机源代码也是基于回调的,姑且称为raw模式,改造成主机的话,如果提供同步模式,是不是也可以提供一套类似于socket的接口,现在armink的主机功能函数
是同步模式的,但是还是有回调,是不是把这些回调功能直接放入主机功能函数里,这样可以得到完全的同步,和socket类似

用这种方法后使用起来就真的爽了,用户代码会变得非常简洁

出0入0汤圆

发表于 2018-8-25 16:25:34 | 显示全部楼层
myxiaonia 发表于 2018-7-17 13:00
兄台现在在rt thread,而且还是核心人物哦,挺厉害的


你认识该作者? 我印象中他以前说过是在北京的啊,可是RT系统不是在上海的吗?





出0入0汤圆

发表于 2018-8-25 18:57:29 | 显示全部楼层
kinsno 发表于 2018-8-25 16:25
你认识该作者? 我印象中他以前说过是在北京的啊,可是RT系统不是在上海的吗?

哈哈哈  都上新闻了啊  搜一下就知道了  我也是新闻上看到的

出0入198汤圆

 楼主| 发表于 2018-8-25 20:11:09 | 显示全部楼层
myxiaonia 发表于 2018-8-25 16:04
我提个意见,不知道对不对
lwip提供了3种接口,raw模式是基于回调的,socket模式是同步的,netcon我不清楚 ...

“这样可以得到完全的同步,和socket类似”

不太理解你说的这个同步大概长什么样,简单写一些伪代码吧

出0入0汤圆

发表于 2018-8-25 22:10:45 来自手机 | 显示全部楼层
现在还更新不?

出0入0汤圆

发表于 2018-8-25 23:05:54 | 显示全部楼层
sunnydragon 发表于 2018-8-25 20:11
“这样可以得到完全的同步,和socket类似”

不太理解你说的这个同步大概长什么样,简单写一些伪代码吧 ...

比如读寄存器,这个函数直接提供缓冲区,读成功了数据就直接写到缓冲区,不用再进回调函数了

出0入0汤圆

发表于 2018-8-26 07:52:17 来自手机 | 显示全部楼层
假如使用free的主机,从机,

出0入0汤圆

发表于 2018-8-26 07:52:57 来自手机 | 显示全部楼层
大概能办证多久通讯无故障啊?通讯线2米以内,115200bps

出0入0汤圆

发表于 2018-12-13 09:30:58 | 显示全部楼层
收藏了,留着以后用

出0入0汤圆

发表于 2019-5-12 12:11:45 | 显示全部楼层
非常感谢,很受用,学习中   

出0入0汤圆

发表于 2019-7-12 09:42:23 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2019-10-13 13:31:28 | 显示全部楼层
freemodbus  主从机开源

出0入0汤圆

发表于 2020-1-7 10:43:28 | 显示全部楼层
下载了,正在看。谢谢大神。FreeModbus曾经让我成功做过项目。这个主机模式,现在学习一下。

出0入0汤圆

发表于 2020-1-19 17:30:49 | 显示全部楼层
收藏FreeModbus主机+从机协议栈,感谢

出0入0汤圆

发表于 2020-2-8 13:54:55 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2020-3-27 16:32:47 | 显示全部楼层
楼主有没有FreeRTOS版本的提供一份,从机成功了,主机移植到FreeRTOS不成功,感激不尽

出0入0汤圆

发表于 2020-6-22 12:39:27 来自手机 | 显示全部楼层
谢谢分享!学习学习

出130入129汤圆

发表于 2023-4-19 15:10:02 | 显示全部楼层
多谢大神10年前的开源精神,我修修改改把主机代码用到自己程序中了。
freemodbus+RTOS2+STM32F401,超时定时器时间太短,就没有使用OS的虚拟定时器了,直接用STM32的TIM。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-18 14:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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