FreeModbus笔记doc文档格式.docx

上传人:b****5 文档编号:21428080 上传时间:2023-01-30 格式:DOCX 页数:19 大小:20.14KB
下载 相关 举报
FreeModbus笔记doc文档格式.docx_第1页
第1页 / 共19页
FreeModbus笔记doc文档格式.docx_第2页
第2页 / 共19页
FreeModbus笔记doc文档格式.docx_第3页
第3页 / 共19页
FreeModbus笔记doc文档格式.docx_第4页
第4页 / 共19页
FreeModbus笔记doc文档格式.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

FreeModbus笔记doc文档格式.docx

《FreeModbus笔记doc文档格式.docx》由会员分享,可在线阅读,更多相关《FreeModbus笔记doc文档格式.docx(19页珍藏版)》请在冰豆网上搜索。

FreeModbus笔记doc文档格式.docx

Modbus数据帧

也就是串口在静默了

T3.5秒以后收到的第一个字节作为一个

Modbus

数据帧的首字节,然

后收到的字符间隔只要不超出

T3.5的时间间隔,都作为这一帧数据来处理。

当串口在>

没有收到数据时,则认为当前主站

发送完了一个数据帧。

可以进行后面的

数据帧处理了。

再收到的数据回作为下一个

数据帧的首字节。

接收一个字节,是由串口中断来进行完成的,判断是否超时是由定时器中断来完成的。

因此

以上看是很清楚的一个协议流程需要串口和定时器配合共同完成。

所以在看RTU实现协议

时一定要记住这点。

从站主要是接收,被动响应,所以先分析接收机的状态:

接收状态机

接收状态包含以下几种:

STATE_RX_INIT,/*!

<

接收机在初始态*/

STATE_RX_IDLE,/*!

接收机在空闲态*/

STATE_RX_RCV,/*!

接收到一帧数据*/

STATE_RX_ERROR/*!

错误数据帧*/

状态机转换图:

串口收到一个字节

eMBEnable()

重启T3.5开始下一个

T3.5延迟

发送一个EV_READY

事件

eMBRTUStart()

设置初态

T3.5超时

超时

STATE_RX_INIT

STATE_RX_IDLE

启动T3.5定时

T3.5超时

串口收到一

个字节

发送一个EV_FRAME_RECEIVED

STATE_RX_RCV

串口收到一个新字

节,且总字节数不

超过最大帧长

串口收到一个新字节,但总字节数超过最大帧长

STATE_RX_ERROR

串口收到一个新字节

状态机的转换不是由一个函数来确定的,是由多个函数共同作用的结果。

主要要T3.5的定

时中断和串口的接收中断。

所以在程序一开始要对串口和定时器进行正确的设置。

当初始化完毕后,接收状态机初始态是STATE_RX_INIT,同时T3.5定时器启动。

如果在T3.5

定时到来之前,串口收到了一个字节,则认为是还没准备好的情况下,总线发起的一次

Modbus传输,此时这帧数据是不处理的,所以,要等到这一帧数据传送完(T3.5超时)。

当发生T3.5超时事件时,说明总线上的数据帧已经传完,处于空闲状态,为发起下一帧数

据传输做好了准备。

所以接收状态机转换为STATE_RX_IDLE,同时发送一个EV_READY事件,

告诉Modbus以及准备好接收数据了。

同时关闭T3.5定时。

在STATE_RX_IDLE状态下,只会接收串口数据来触发状态转换(定时被关闭)。

当接收到一

个字节时,认为总线开始了一个新的数据帧的传输,把这个字节保存在Modbus数据缓冲区,并将缓冲区指针加1,并将接收状态机转换为STATE_RX_RCV。

在STATE_RX_RCV状态下,接收到一个新字节,将该字节保存在缓冲区,并将缓冲区指针加

1,判断接收的字节总长是否>最大帧长,如果不大于,继续保持STATE_RX_RCV状态,等待

接收下一个字节或超时(接收完成)。

当大于最大帧长,说明接收到了错误帧。

状态转到

STATE_RX_ERROR。

在STATE_RX_RCV状态下,产生了一个T3.5超时,此时认为总线已经发送完成一个Modbus

数据帧,将状态转换到STATE_RX_IDLE,等待下一个数据帧到来。

同时触发EV_FRAME_RECEIVED事件,告诉ModbusPoll已经成功接收一帧数据,可以解析并处理了。

在STATE_RX_ERROR状态下,接收到再多的字节都认为是错误的,所以一直停留在错误态,直到来了一个T3.5超时事件,此时认为总线上错误的数据帧发送完毕,总线静默,为下一

个数据帧准备好!

接收状态机转换为STATE_RX_IDLE。

Modbus的初始化流程:

eMBRTUInit()

调用

eMBInit()

ModBus初始化:

1、设置从机号

eQueuedEvent为空

2、设置eMode(RTU)

eMBState=

3、设置波特率

STATE_DISABLED

Uart_Init()

xMBPortTimersInit()

4、设置T35定时器

ModBus使能:

1、置端口为接收状态

STATE_ENABLED

2、开端口定时功能

eRcvState=

此时串口中断开,定时中断开

STATE_RX_INIT;

以下是FreeModbus的各个功能函数解析:

1、//-----初始化Modbus协议------------------------

eMBInit(MB_RTU,Slave_Adress,0,115200,MB_PAR_NONE);

eMBInit()

状态码=无错误

地址号是否有效

状态码=非法参数

MB_RTU

eMBRTUInit

返回状态码

设备号=地址号

eMode=?

MB_ASCII

eMBASCIIInit

xMBPortEventInit

正确

default

错误

状态码

=MB_EPORTERR

eMBRTUInit(UCHARucSlaveAddress,UCHARucPort,ULONGulBaudRate,eMBParityeParity)

eMBRTUInit()

调用库函数对串口初始化

uart_init(ulBaudRate);

usTimerT35_50us

=更长些

根据超时时间

初始化定时器

3.5个字符时间区分不同的帧,即接收到的两个字符之间时间间隔小于3.5个字符时间时认为是同一个帧的,如果间隔大于3.5个字符时间则认为是不同帧的,在一般的串口通信中,发送1个字符需要:

1位起始位,8位数据位,1位校验位(可无),1位停止位,总共1+8+1+1=11位,3.5个字符时间

就是3.5*11=38.5位,假如波特率是9600,那么传输1位的时间是1000/9600=0.10416667(ms),这

样,3.5个字符时间就大约是4ms,即定时器需要的中断时间

xMBPortSerialInit()

初始化是否成功

根据波特率设

定超时时间

波特率>

19200

=35

至此,Modbus的初始化工作完成。

串口中断被打开,超时定时器配置好。

该函数指针指向

eMBRTUStart

eStatus状态码=无错误

初始化时

的状态否

eMBState==

pvMBFrameStartCur()

返回eStatus状态码

eMBRTUStart()

eStatus=

MB_EILLSTATE

置接收状态位初

始化状态

置端口为接收状态

开端口定时功能

vMBPortSerialEnable(TRUE,FALSE);

在端口使能函数中

vMBPortTimersEnable();

设置485的收发状态

返回

当串口接收到数据时发生中断,由串口中断程序处理USART1_IRQHandler()

USART1_IRQHandler

()

接收事件?

调用prvvUARTRxISR()

处理

发送准备好事件?

调用prvvUARTTxReadyISR()

pxMBFrameCBByteReceived();

在RTU模式,该函数指针指向

xMBRTUReceiveFSM()

实际调用的是

pxMBFrameCBTransmitterEmpty();

xMBRTUTransmitFSM()

xMBRTUTransmitFSM

实际调用的是xMBRTUTransmitFSM()

实际是调用函数:

USART_ReceiveDa

ta(USART1);

xMBRTUReceiveFSM()

确认当前发送为空闲状态

xMBPortSerialGetByte()

接收一个字节数据

判断当前接收状态

eRcvState

STATE_RX_ERRORSTATE_RX_IDLESTATE_RX_RCV

接收第一个字节,并将状

将当前接收字节加入到接收缓冲

态置为STATE_RX_RCV

区,当接收字节数大于最大帧

同时,启动T3.5定时器

长,将放弃该帧(eRcvState=

STATE_RX_ERROR)

每收到一个字节复位T3.5定时器

确认当前接收为空闲状态

eSndState

STATE_TX_IDLE

由发变收

产生一个发送完毕事件

xNeedPoll=xMBPortEventPost(

EV_FRAME_SENT);

STATE_TX_XMIT

发送缓冲区不为零

发送当前字节

xMBPortSerialPutByte((CHAR

)*pucSndBufferCur)

USART_SendData(USART1,ucByte);

更新缓冲器指针和大小

TIM2_IRQHandler

中断函数调用

TIMERExpiredISR(void)

pxMBPortCBTimerExpired()

RTU模式下,该函数指针指向

xMBRTUTimerT35Expired()

Default

置返回值为错误态

产生一个准备好事件

xMBPortEventPost(

产生一个接收一帧事件

确认各参数正常?

EV_READY);

xMBPortEventPost(

EV_FRAME_RECEIVED)

vMBPortTimersDisable();

eRcvState=STATE_RX_IDLE;

Modbus的主查询函数eMBPoll()

eMBPoll()

ModBus是否使能协议栈出错,并返回错误码

EV_READY

获取当前MB_EVENT成功

判断当前EVENT

EV_FRAME_SENT

EV_FRAME_RECEIVEDEV_EXECUTE

peMBFrameReceiveCur(

//从接收缓冲取出功能码

&

ucRcvAddress,

ucMBFrame,&

usLength

Break;

);

//查询接收结果,并将结

依次查询各个功能码

果保存到ucMBFrame

查询接收结果无错误

本机支持该功能码

判断当前数据帧是本机

调用该功能码处理函数

数据或是广播数据

派送一个执行事件

地址不等于广播地址

EV_EXECUTE);

按照MB协议,发送应答帧

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1