Translation: en
Freemodbus 移植, 以 CMSIS-RTOS2 为实时操作系统。
储库 | 原作者 | 系统 | 说明 |
---|---|---|---|
FreeModbus_Slave-Master-RTT-STM32 | Armink | RT-Thread | Freemodbus主机的原作者 |
FreeModbus_Slave-Master-RTT-STM32 | Armink | RT-Thread | 也是原作者的储库,但是在gitee |
STM32-FreeModbus-Example | ADElectronics | 无 | 一个简单的移植,实现modbus RTU 主机和从机 |
HAL_FreeRTOS_Modbus | Alidong | FreeRTOS | FreeRTOS移植版 |
chibi-modbus-master | AndruPol | chibiOS | ChibiOS移植版 |
freemodbus_master_slave | connictro | ESP32 RTOS | FreeRTOS ESP32移植版 |
- 关于其它移植,请在github上查#freemodbus主题或者搜索freemodbus。大部分的储库都是freertos移植,或者只有一种模式(从机或主机)。
这个移植版遵守以下的规律:
- 独立性:除了portserial.c和portserial_m.c之外,每个文件都是用它内在的变数。portserial.c和portserial_m.c必须用HAL的串口变数来传达信息。但是其它的变数也是static的。
- 减少ISR的执行时间:每个信息都是一次性的解决。发送信息时,把所有的字节一起性的发送出去。详细请看下面的移植。接收字节时,所有数据保存在一个缓冲器里面。等到IDLE了,信息处理过程就交给一个线程来解决。
- 信息过时:每个信息请求有一个限定的时间。超过这个时间时,程序会放弃请求和等待。
用Armink的源代码作为起点
- 改名port/rtt为我们用的系统 - cmsis_rtos2
- 在port/cmsis_rtos2里面,改名port.c为portcritical.c。因为在编译的时候会发生冲突。实时操作系统的代码里面也有一个port.c的文件。
- 实现
EnterCriticalSection
和ExitCriticalSection
接口使用CMSIS-RTOS2 kernel control API。 - 实现portevent.c和portevent_m.c使用CMSIS-RTOS2 Event flags。
- 实现porttimer.c和porttimer_m.c使用CMSIS-RTOS2定时器或者硬件定时器(硬件定时器版可以参考ADElectronic的储库)。
- 实现portserial.c和portserial_m.c使用HAL UART(或者LL UART)。这些文件也实现了串口的中断服务程序接口。
- 在mbrtu.c和mbrtu_m.c里面,把
xMBMasterPortSerialPutBytes
接口应用到xMBMasterRTUTransmitFSM
里面的STATE_M_TX_XMIT
状态。可以代替xMBMasterPortSerialPutByte
或者用以下的片段:
/* Defines the MASTER_SEND_ALL_BYTES_IN_ONE_CALL macro yourself */
#if MASTER_SEND_ALL_BYTES_IN_ONE_CALL > 0
xMBMasterPortSerialPutBytes(pucMasterSndBufferCur, usMasterSndBufferCount);
usMasterSndBufferCount = 0;
#else
xMBMasterPortSerialPutByte( ( CHAR )*pucMasterSndBufferCur );
pucMasterSndBufferCur++; /* next byte in send buffer. */
usMasterSndBufferCount--;
#endif
- 用ADElectronics的储库的部分实现方法来把整条信息内容一次性的发送出去。在mbport.h里面加
xMBPortSerialPutBytes
和xMBMasterPortSerialPutBytes
接口定义。然后在portserial.c和portserial_m.c实现它们。 - 实现系统的中断处理程序。详细的中断服务程序已经实现在portserial.c和portserial_m.c和它们的定义在port.h。我们只要把它们叫出来就好。我们只关心以下的三个中断旗:
- RXNE - 接收缓冲区不空或者新的字节已接收,我们把它转移到内存的缓冲器;
- IDLE - 闲旗,表示全部信息内容已收到;
- TC - 送达完成,所有发送内容已发出去
- 注: 我们不处理TXE中断,由下面的HAL来处理。
- 创造modbus polling线程,使用以下的简单程序片段:
void MBMasterPollTask(void *argument)
{
eMBMasterInit(MB_RTU, 6, 9600, MB_PAR_NONE);
eMBMasterEnable();
for(;;)
{
eMBMasterPoll();
}
}
- 把需要的modbus文件加到Makefile(或者其它toolchain/IDE)里面。
- 工具: CubeMX + Makefile
- 微控制器:STM32F407ZET6(其它的微控制器请看移植)
- Modbus串口: USART6(主机)和USART3(从机)。若想要用其它串口,在(portserial.c和portserial_m.c)里面,该以下的UART片段成为你想要的串口。
extern UART_HandleTypeDef huart6;
// ...
#define huart huart6