单片机通过Modbus协议与HMI通信Word格式.docx
《单片机通过Modbus协议与HMI通信Word格式.docx》由会员分享,可在线阅读,更多相关《单片机通过Modbus协议与HMI通信Word格式.docx(7页珍藏版)》请在冰豆网上搜索。
字符,当有一个冒号接收到时,每个设备都解码下个域(地址域)来判断是否发给自己的。
消息中字符间发送的时间间隔最长不能超过1秒,否则接收的设备将认为传输错误。
一个典型消息帧如下所示:
模式
起始
地址
功能
数据
校验
结束
ASCII
:
设备地址
功能代码
起地址
数据数
数据n
LRC高字节
LRC低字节
<
CR>
例如
06
03
006B
0003
使用RTU模式,两个消息间至少要有3.5个字符时间的停顿间隔,整个消息帧必须作为一连续的流转输,如果在帧完成之前有超过1.5个字符时间的停顿时间,接收设备将假定下一字节是一个新消息的地址域。
同样,如果一个新消息在小于3.5个字符时间内接着前个消息开始,接收的设备将会认为它是前一消息的延续。
这将导致一个错误,所以每一帧间的间隔必须大于3.5个字符时间,而在一帧内每个数据间隔不应大于1.5个字符时间.
RTU
(4T)
CRC高字节
CRC低字节
三.参考程序:
下面以MCS-51单片机作为ModbusRTU从站与eViewMD204L通信例子.
1.联接方式
通信按RS232可RS485方式联接.通信速率为19200,数据位为8位,停止位1位,无校验.
2.MD204L选用ModbusRTU协议,按相同方式设置好通信参数.
3.工作原理
MCU处理事务的过程中,串口处于侦听状态,当收到数据时,启动计时器,在发现一个大于3.5T的间隔后,判断报文的地址域是否与本身的设备地址一致,如果是的话,对收到的缓冲区内容进行校验,如果通过校验则认为是一个合法的Modbus报文帧,对该报文进行解释,并产生回送报文.
4.示例报文
发出:
010400020001900A解释:
01为站号,0002为起地址,0001为长度(1个字)
回复:
0104021000B4F0
解释:
01为回复站,02为字节数,1000为数据
5.参考程序
如下对MCU串口进行设置
voidprotocol_init(void)
{
//波特率19200,8,1,odd
//都用工作方式3,不需要第9位时就将TB8赋1
SCON
=0xD0;
//工作方式3
PCON&
=0X7F;
//确保smod1=0;
TMOD
=0x21;
//0x21,timer1,mode2,timer0mode1
TH1
=0xfd;
TR1
=1;
//TR1:
timer1run
//超时等待3.5个字符位以判断帧结束。
//则3.5个字符至多需要12*3.5=42个位,就是42*stop_times
t2_time_out=(signedchar)TH1*(42*6);
if(!
(PCON&
0x80))t2_time_out<
=1;
T2CON=0;
T2MOD=0;
TI=0;
RI=0;
EA=1;
ES=1;
prepare_recv();
}
初始化接收状态的函数如下
voidprepare_recv(void)small
{//准备接收
TR2=0;
//初始化T2
ET2=1;
T2REG=RCAP2=t2_time_out;
receiving=1;
frame_timeout=0;
recv_index=0;
recv_error=0;
RW485=Rs485Rx;
REN=1;
串行通信中断处理程序
voidprotocol_serial_process(void)small
unsignedchartmp;
if(_testbit_(TI))
trans_index++;
//下一个字节
if(trans_index<
protocol.buff_len)
format_trans_send();
//按约写的规格发送一个字节
else
trans_finished=1;
//发送完毕,转为接收状态
if(_testbit_(RI))
RI=0;
if(receiving)
TH2=RCAP2H;
//重新装载计时器,等侍3.5T的中断
TR2=1;
tmp=SBUF;
CommBuf[recv_index++]=tmp;
if(recv_index>
=BUF_MAX_LEN)
{
//帧越界,出错,重收
receiving=0;
recv_error=1;
T2定时器用于作为帧结束判断定时器,当发生中断时,意味已经有超过了3.5T的间隔
voidtimer2(void)interrupt5
//计时中断2,用于帧超时计时
TF2=0;
if(receiving)
receiving=0;
receive_finished=1;
if((recv_index>
7)&
&
(CommBuf[0]==protocol.device_addr)&
(!
recv_error))
{//如果与当前设备地址一致并且报文长度有效,则报文进一步分析
protocol.buff_len=recv_index;
TH2=RCAP2H=DELAY_TIME_H;
TL2=RCAP2L=DELAY_TIME_L;
REN=0;
else
//否则丢弃这次接收,重新开始
recv_error)
AnalyzeRecieve();
//分析并生成回复报文
send_frame_comm();
//开始回复报文,按设定的参数格式进行发送
elseprepare_recv();
校验采用CRC校验,函数代码如下
/*TableOfCRCValuesforhigh-orderbyte*/
unsignedcharcode
auchCRCHi[]={
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,