目录
7.00 RTOS接口
uC/Modbus-S可能会用到RTOS接口,uC/Modbus-M是假设RTOS存在的,但是不会假设一个特定的RTOS。事实上,uC/Modbus是设计成可以工作在商业RTOS之上的,只需要提供简单的RTOS接口层即可。
uC/Modbus提供了uC/Modbus RTOS接口层,因此,如果您的产品中使用了uC/OS-II或uC/OS-III,您也可以uC/Modbus,也可以将该接口层作为您自己的RTOS参考。
图7-1展示了接收模型的流程图。
图7-1,uC/Modbus Rx任务模型
F7-1(1) |
uC/Modbus使用一个简单的任务从每个通道接收数据包。Modbus Rx Task只需要等待每个Modbus通道的数据包即可。假设以uC/OS-II作为RTOS,那么就是通过消息队列来实现该功能。对于uC/OS-III,消息队列是内置在任务中的。当接收到数据后,一个指向接收数据通道的指针被发送至消息队列指示“Modbus Rx Task”是哪一个通道接收到数据包。“Modbus Rx Task”只需要解析数据包并给出响应,响应会被适当的转发。 |
|||||||||||||||||||||
F7-1(2) |
假设来自UART的字节是由中断驱动的。接收到字节被存放到一个接收缓存中,直到数据接收完成。如果通道配置为Modbus ASCII,数据包结尾是一个换行符(即,0x0A)。如果通道配置为Modbus RTU,如果3.5字节周期(参考Modbus RTU规范)内未收到任何数据则表示数据结束。 |
|||||||||||||||||||||
F7-1(3) |
假设是Modbus ASCII,通过调用MB_OS_RxSignal()并指定一个指向已接收数据通道的指针来发出数据包结束信号。 |
|||||||||||||||||||||
F7-1(4) |
如果您的产品需要支持Modbus RTU模式,就需要提供一个定时器来中断CPU以便跟踪数据包的结束。基本上,当通道上接收一个字节的时候,该通道的RTU计数器将根据该通道的波特率重置为一个值(见表7-1)。 表7-1,基于通道波特率的RTU超时。
例如,如果一个通道配置为19200的波特率,在1800us中未接收到任何字节视为数据包结束(RTU模式)。如果RTU计时器被设置为每毫秒中断一次,那么大约需要两次这样的中断,然后才能断定收到了一个数据包。我们决定假设一个数据包至少是在接收5.0字节的时间之后接收完成,而不是3.5字节的时间后。此外,由于计时器相对接收字节的异步特性,我们决定计算至少两个RTU中断,以得出收到数据包的结论。 如果增加RTU计时器中断率,对于超时可以有更好的粒度。但是,这也增加了您放置在CPU上的开销。 |
|||||||||||||||||||||
F7-1(5) |
当RTU定时器中断发生,每个RTU模式通道的超时计数器开始向下计数。当计数器为0时,向“Modbus Rx Task”发送一个信号。告诉“Modbus Rx Task”哪一个通道收到了数据需要处理。信号也可以调用MB_OS_RxSignal()执行。 |
为了提供上述的RTOS功能,您需要在MB_OS.c文件中定义3个函数:
MB_OS_Init()
MB_OS_Exit()
MB_OS_RxSignal()
MB_OS_RxWait()
7.01 RTOS接口, MB_OS_Init()
该函数由uC/Modbus调用,初始化所用RTOS的RTOS接口。通常要创建“Modbus Rx Task”任务,并设置在接收到数据包或通道RTU超时时通知该任务所需的机制。
原型
void MB_OS_Init(void);
参数
无
返回值
无
注意事项/警告
无
调用方
mb.c中的MB_Init()
示例
7.02 RTOS接口,MB_OS_Exit()
该函数由MB_Exit()调用,正常的终止Modbus任务。在uC/OS-II中,只需要删除“Modbus Rx Task”和消息队列就可以。在uC/OS-III中,删除“Modbus Rx Task”即可,消息队列是内置在任务中的。
原型
void MB_OS_Exit(void);
参数
无
返回值
无
注意事项/警告
无
调用方
mb.c中的MB_Exit()
示例
7.03 RTOS接口,MB_OS_RxSignal()
该函数发出接收到完成数据包的信号。可以被超时时间内未接到任何字符的通道的RTU定时器中断调用,或者被接收到换行符(0x0A)的Modbus ASCII通道调用。
原型
void MB_OS_RxSignal(MODBUS_CH *pch);
参数
pch |
指定一个指向与接收到的数据包相关联的Modbus通道道数据结构的指针。 |
返回值
无
注意事项/警告
无
调用方
mb.c文件中的MB_RTU_TmrUpdate() 或 MB_ASCII_RxByte()。
示例
7.04 RTOS接口,MB_OS_RxWait()
该函数等待从机的应答。MB_OS_RxWait()在Modbus主机任务向从机发送命令后等待从机应答的时候被调用。如果在配置通道时指定的超时时间内未收到应答,函数将返回给调用方并通知其超时。
原型
void MB_OS_RxWait(MODBUS_CH *pch, CPU_INT16U *perr);
参数
pch |
指定一个指向与接收到的数据包相关联的Modbus通道道数据结构的指针。 |
perr |
指向错误代码的指针,指示调用结果,可以是如下错误: MODBUS_ERR_NONE:调用成功 MODBUS_ERR_TIMED_OUT:指定超时时间内未收到应答 MODBUS_ERR_NOT_MASTER:在非主机通道中调用了该函数 MODBUS_ERR_INVALID:发送无效的错误。详细信息请参考MB_OS.C |
注意事项/警告
无
调用方
MBM_CORE.C文件中的MBM_FC??_???()
示例
7.05 RTOS接口,配置
如果使用uC/OS-II,需要配置以下#define常量:
OS_Q_EN |
大小需要与Modbus通道一样 |
OS_SEM_EN |
如果使用Modbus主机,需要使能信号量服务 |
MB_OS_CFG_RX_TASK_ID |
|
MB_OS_CFG_RX_TASK_PRIO |
|
MB_OS_CFG_RX_TASK_STK_SIZE |
如果使用uC/OS-III,需要配置以下#define常量:
OS_CFG_Q_EN |
消息队列的大小被设置为mb_os.c中通道的大小(即,MODBUS_CFG_MAX_CH) |
OS_CFG_SEM_EN |
如果使用Modbus主机,需要使能信号量服务 |
MB_OS_CFG_RX_TASK_PRIO |
|
MB_OS_CFG_RX_TASK_STK_SIZE |
这些常量需要在您的应用中声明。