uC/Modbus 用户手册——第九节 uC/Modbus程序流程

目录

9.00 uC/Modbus程序流程

9.01 uC/Modbus-S,ASCII Rx与Tx

9.02 uC/Modbus-S,RTU Rx与Tx

9.03 uC/Modbus-M,ASCII Rx与Tx

9.04 uC/Modbus-M,RTU Rx与Tx

10.00首字母缩写、缩写和助记符


9.00 uC/Modbus程序流程

本节描述了由Modbus通道接收和响应的消息所采取的途径。每个通道包含4个缓存区以及用于管理这些缓存区的变量,如图9-1所示。

uC/Modbus 用户手册——第九节 uC/Modbus程序流程

图9-1,uC/Modbus Buffer管理

​​​​​​​9.01 uC/Modbus-S,ASCII Rx与Tx

遵循以下提供的代码可能是有用的。

MB_CommRxTxISR_Handler() – mb_bsp.c

UART上接收的字符由MB_CommRxTxISR_Handler()处理,除非UART的Rx和Tx分别有单独的中断。这种情况下,函数将调用MB_CommRxISR_Handler()。从UART提取已接收的字符并传递给MB_RxByte()进行处理。

MB_RxByte() – mb.c

MB_RxByte()决定接收的字符需要传递给ASCII还是RTU进行处理。如果是ASCII,字符将传递给MB_ASCII_RxByte()。

MB_ASCII_RxByte() – mb.c

MB_ASCII_RxByte()将接收到的字符放置到 .RxBuf[]。如果接收的字符是“冒号”(即,‘:’),会将指针复位为 .RxBuf[]头部,因为这表示接到了主机的新消息。如果接收到的是“换行”(即,0x0A),将会通知Rx Task,接收的消息发往与通道匹配的节点地址。通过调用MB_OS_RxSignal() (mb_os.c)通知任务。

MB_OS_RxTask() – mb_os.c

所有的Modbus通信都由一个名为MB_OS_RxTask()的Rx任务来处理。该任务等待MB_ASCII_RxByte()向其发送消息。消息实际上是一个指向接收到消息的Modbus通道的指针。MB_OS_RxTask()调用MB_RxTask() (mb.c)进而调用MBS_RxTask() (mbs_core.c)。MBS_RxTask()决定消息是ASCII或RTU消息,并调用MBS_ASCII_Task() (mbs_core.C)或MBS_RTU_Task() (mbs_core.C),分别对接收到的消息进行实际处理。

MBS_ASCII_Task() – mbs_core.c

此时,我们收到了一条来自Modbus主机的消息,该消息指向通道的节点地址。但是,我们不知道消息是否有效。MBS_ASCII_Task()调用MB_ASCII_Rx() (mb.c)将ASCII格式转换为二进制格式。转换后的消息存放在.RxFrameData[]中。

MBS_ASCII_Task()然后调用MB_ASCII_RxCalcLRC()确定接收到的作为消息一部分的LRC是否与计算的LRC一致。注意,LRC是通过将接收到的消息中除冒号外的所有ASCII字符相加来计算的,LRC与CR/LF然后进行两个补充。也就是,LRC仅包含由Modbus主机发送的节点地址、功能码与数据。

如果有一个有效的消息,然后调用MBS_FCxx_Handler()解析接收的消息并向主机返回应答。

应答通过MB_ASCII_Tx()发送到主机。

MBS_FCxx_Handler() – mbs_core.c

此函数通过查看接收消息中的“功能码”来确定主机的内容,从而调用相应的Modbus功能码处理函数:MBS_FC??_???()。应答已二进制格式存放在.TxFrameData[]缓存中。

MB_ASCII_Tx() – mb.c

当需要向Modbus主机发送应答时调用该函数。MB_ASCII_Tx()将存放在.TxFrameData[]中的应答转换为ASCII。转换后的数据存放在.TxBuf[]中。

通过调用MB_ASCII_TxCalcLRC()来计算传出帧的LRC。注意,LRC是通过将接收到的消息中除冒号外的所有ASCII字符相加来计算的,LRC与CR/LF然后进行两个补充。也就是,LRC仅包含发送给Modbus主机的节点地址、功能码与数据。

MB_ASCII_Tx()然后调用MB_Tx()设置发送。

MB_Tx() – mb.c

通过调用该函数向Modbus主机发送消息。在这里,我们只是将 .TxBufPtr指向 .TxBuf[]的起始位置,通过调用MB_TxByte()(mb.c)传输第一个字节来“启动”传输中断。注意,在多数情况下,传输中断仅在一个字符传输完成后发生。

MB_TxByte() – mb.c

MB_TxByte()转而调用MB_CommTx1() (mb_bsp.c),后者向UART发送一个字节并使能Tx中断。

​​​​​​​9.02 uC/Modbus-S,RTU Rx与Tx

遵循以下提供的代码可能是有用的。

MB_CommRxTxISR_Handler() – mb_bsp.c

UART上接收的字节由MB_CommRxTxISR_Handler()处理,除非UART的Rx和Tx分别有单独的中断。这种情况下,函数将调用MB_CommRxISR_Handler()。从UART提取已接收的字节并传递给MB_RxByte()进行处理。

MB_RxByte() – mb.c

MB_RxByte()决定接收的至字节需要传递给ASCII还是RTU进行处理。如果是ASCII,字符将传递给MB_RTU_RxByte()。

MB_RTU_RxByte() – mb.c

MB_RTU_RxByte()将接收到的字节放入 .RxBuf[]。因为在RTU模式中,帧分割是通过时间实现的,MB_RTU_RxByte()会重置通道的RTU定时器,表示还未收到帧结束标志。接收的字节存放在接收缓存.RxBuf[]中。完整帧的信号通过该通道的RTU计时器超时来完成(请参阅通信中的MB_RTU_TmrUpdate())。

MB_OS_RxTask() – mb_os.c

所有的Modbus通信都由一个名为MB_OS_RxTask()的Rx任务来处理。该任务等待RTU定时器发出的指示已接收到完整帧的消息。消息实际上是一个指向接收到消息的Modbus通道的指针。MB_OS_RxTask()调用MB_RxTask() (mb.c)进而调用MBS_RxTask() (mbs_core.c)。MBS_RxTask()决定消息是ASCII或RTU消息,并调用MBS_ASCII_Task() (mbs_core.C)或MBS_RTU_Task() (mbs_core.C),分别对接收到的消息进行实际处理。

MBS_RTU_Task() – mbs_core.c

此时,我们收到了一条来自Modbus主机的消息,该消息指向通道的节点地址。但是,我们不知道消息是否有效。MBS_RTU_Task()调用MB_RTU_Rx() (mb.c)将接收的数据从.RxBuf[]中复制到.RxFrameData[]中。

MBS_RTU_Task()然后调用MB_RTU_RxCalcLRC()确定接收到的作为消息一部分的CRC是否与计算的CRC一致。注意,CRC是通过将接收到的消息中除CRC本身的所有字节进行CRC计算得到的,也就是,CRC仅包含由Modbus主机发送的节点地址、功能码与数据。

如果有一个有效的消息,然后调用MBS_FCxx_Handler()解析接收的消息并向主机返回应答。

应答通过MB_RTU_Tx()发送到主机。

MBS_FCxx_Handler() – mbs_core.c

此函数通过查看接收消息中的“功能码”来确定主机的内容,从而调用相应的Modbus功能码处理函数:MBS_FC??_???()。应答已二进制格式存放在.TxFrameData[]缓存中。

MB_RTU_Tx() – mb.c

当需要向Modbus主机发送应答时调用该函数。MB_RTU_Tx()将存放在.TxFrameData[]中的应答复制到.TxBuf[]中。

通过调用MB_RTU_TxCalcCRC()来计算传出帧的CRC。注意,CRC是通过将接收到的消息中除CRC本身的所有字节进行CRC计算得到的,也就是,CRC仅包含发送到Modbus主机的节点地址、功能码与数据。

MB_RTU_Tx()然后调用MB_Tx()设置发送。

MB_Tx() – mb.c

通过调用该函数向Modbus主机发送消息。在这里,我们只是将 .TxBufPtr指向 .TxBuf[]的起始位置,通过调用MB_TxByte()(mb.c)传输第一个字节来“启动”传输中断。注意,在多数情况下,传输中断仅在一个字符传输完成后发生。

MB_TxByte() – mb.c

MB_TxByte()转而调用MB_CommTx1() (mb_bsp.c),后者向UART发送一个字节并使能Tx中断。

​​​​​​​9.03 uC/Modbus-M,ASCII Rx与Tx

遵循以下提供的代码可能是有用的。

MBM_FC??_????() – mbm_core.c

Modbus主机应用调用MBM_FC??_????()向从机发送命令。该函数生成一个命令帧,通过调用MBM_TxCmd()发送。

MBM_TxCmd() – mbm_core.c

该函数根据主机通道配置为ASCII或RTU分别调用MB_ASCII_Tx() 或 MB_RTU_Tx()。

MB_ASCII_Tx() – mb.c

在ASCII模式,调用该函数将命令发送至Modbus从机。MB_ASCII_Tx()将.TxFrameData[]中的命令转换为ASCII格式,转换后的数据存储在.TxBuf[]中。

通过调用MB_ASCII_TxCalcLRC()来计算传出帧的LRC。注意,LRC是通过将接收到的消息中除冒号外的所有ASCII字符相加来计算的,LRC与CR/LF然后进行两个补充。也就是,LRC仅包含由Modbus主机发送的节点地址、功能码与数据。

MB_ASCII_Tx()然后调用MB_Tx()设置传输。

MB_Tx() – mb.c

调用该函数向Modbus从机发送消息。在这里,我们只是将 .TxBufPtr指向 .TxBuf[]的起始位置,通过调用MB_TxByte()(mb.c)传输第一个字节来“启动”传输中断。注意,在多数情况下,传输中断仅在一个字符传输完成后发生。

MB_TxByte() – mb.c

MB_TxByte()转而调用MB_CommTx1() (mb_bsp.c),后者向UART发送一个字节并使能Tx中断。

MB_OS_Wait() – mb_os.c

命令发送完成后,MBM_FC??_???()调用MB_OS_Wait()等待从机的应答,后者会附带一个超时时间。如果超时时间(见MB_CfgCh())内未接收到应答将会刷新Rx缓存区。如果接收到应答,将调用MBM_RxReply()处理应答。

MB_CommRxTxISR_Handler() – mb_bsp.c

UART上接收的字符由MB_CommRxTxISR_Handler()处理,除非UART的Rx和Tx分别有单独的中断。这种情况下,函数将调用MB_CommRxISR_Handler()。从UART提取已接收的字符并传递给MB_RxByte()进行处理。

MB_RxByte() – mb.c

MB_RxByte()决定接收的字符需要传递给ASCII还是RTU进行处理。如果是ASCII,字符将传递给MB_ASCII_RxByte()。

MB_ASCII_RxByte() – mb.c

MB_ASCII_RxByte()将接收到的字符放置到 .RxBuf[]中。如果接收的字符是“冒号”(即,‘:’),会将指针复位为 .RxBuf[]头部,因为这表示接到了主机的新消息。如果接收到的是“换行”(即,0x0A)表示应答接收完成,将会调用MB_OS_RxSignal() (mb_os.c),将唤醒向从机发送命令的任务,MBM_FC??_???()函数将恢复(在B_OS_RxWait()调用之后)。

MBM_RxReply() – mbm_core.c

MBM_RxReply()确定通道被配置为ASCII或RTU并分别调用MB_ASCII_Rx()或MB_RTU_Rx()接收数据包。

MB_ASCII_Rx() – mb.c

MB_ASCII_Rx()确定接收到的数据包是否包含正确的格式和校验和。如果接收到有效的数据包,MB_ASCII_Rx()返回到MBM_RxReply()然后返回至MBM_FC??_???()函数。

MBM_FC??_???() – mbm_core.c

MBM_FC??_???()解析应答并向调用方返回请求的信息。

​​​​​​​9.04 uC/Modbus-M,RTU Rx与Tx

遵循以下提供的代码可能是有用的。

MBM_FC??_????() – mbm_core.c

Modbus主机应用调用MBM_FC??_????()向从机发送命令。该函数生成一个命令帧,通过调用MBM_TxCmd()发送。

MBM_TxCmd() – mbm_core.c

该函数根据主机通道配置为ASCII或RTU分别调用MB_ASCII_Tx() 或 MB_RTU_Tx()。

MB_RTU_Tx() – mb.c

需要向Modbus从机发送命令时调用该函数。MB_RTU_Tx()将.TxFrameData[]中的命令复制到.TxBuf[]中。

通过调用MB_RTU_TxCalcCRC()来计算传出帧的CRC。注意,CRC是通过将接收到的消息中除CRC本身的所有字节进行CRC计算得到的,也就是,CRC仅包含发送到Modbus主机的节点地址、功能码与数据。

MB_RTU_Tx()然后调用MB_Tx()设置传输。

MB_Tx() – mb.c

调用该函数向Modbus从机发送消息。在这里,我们只是将 .TxBufPtr指向 .TxBuf[]的起始位置,通过调用MB_TxByte()(mb.c)传输第一个字节来“启动”传输中断。注意,在多数情况下,传输中断仅在一个字符传输完成后发生。

MB_TxByte() – mb.c

MB_TxByte()转而调用MB_CommTx1(),后者向UART发送一个字节并使能Tx中断。

MB_OS_Wait() – mb_os.c

命令发送完成后,MBM_FC??_???()调用MB_OS_Wait()等待从机的应答,后者会附带一个超时时间。如果超时时间(见MB_CfgCh())内未接收到应答将会刷新Rx缓存区。如果接收到应答,将调用MBM_RxReply()处理应答。

MB_CommRxTxISR_Handler() – mb_bsp.c

UART上接收的字符由MB_CommRxTxISR_Handler()处理,除非UART的Rx和Tx分别有单独的中断。这种情况下,函数将调用MB_CommRxISR_Handler()。从UART提取已接收的字符并传递给MB_RxByte()进行处理。

MB_RxByte() – mb.c

MB_RxByte()决定接收的字符需要传递给ASCII还是RTU进行处理。如果是RTU,字符将传递给MB_RTU_RxByte()。

MB_RTU_RxByte() – mb.c

MB_RTU_RxByte()将接收到的字符放置到 .RxBuf[]中。因为在RTU模式中,帧分割是通过时间实现的,MB_RTU_RxByte()会重置通道的RTU定时器,表示还未收到帧结束标志。接收的字节存放在接收缓存.RxBuf[]中。完整帧的信号通过该通道的RTU计时器超时来完成(请参阅mb.c中的MB_RTU_TmrUpdate())。

MBM_RxReply() – mbm_core.c

MBM_RxReply()确定通道被配置为ASCII或RTU并分别调用MB_ASCII_Rx()或MB_RTU_Rx()接收数据包。

MB_RTU_Rx() – mb.c

MB_RTU_Rx()确定接收到的数据包是否包含正确的格式和校验和。如果接收到有效的数据包,MB_RTU_Rx()返回到MBM_RxReply()然后返回至MBM_FC??_???()函数。

MBM_FC??_???() – mbm_core.c

MBM_FC??_???()解析应答并向调用方返回请求的信息。

​​​​​​​10.00首字母缩写、缩写和助记符

uC/Modbus包含一些首字母缩写,缩写和助记符,如表10-1。

This …

Means …

An

Analog

App

Application

Buf

Buffer

Cfg

Configuration

Ch

Channel

Comm

Communication

Ctr

Counter

DI

Discrete Input

Dis

Disable

DO

Discrete Output

En

Enable

Err

Error

FC

Function Code

FP

Floating Point

Id

Identifier

In

Input

Init

Initialization

ISR

Interrupt Service Routine

Ix

Index

MB

Modbus

MBM

Modbus Master

MBS

Modbus Slave

Nbr

Number

OS

Operating System

Out

Output

Pkt

Packet

Prio

Priority

Rd

Read

Reg

Register

RTU

Remote Terminal Unit

Rx

Receive

Stk

Stack

Tmr

Timer

Tx

Transmit

Val

Value

Wr

Write

上一篇:centos6.5下安装Nginx


下一篇:C语言实现Linux下od -tx -tc XXX的功能