单片机通过Modbus协议与HMI通信.docx
《单片机通过Modbus协议与HMI通信.docx》由会员分享,可在线阅读,更多相关《单片机通过Modbus协议与HMI通信.docx(7页珍藏版)》请在冰豆网上搜索。
![单片机通过Modbus协议与HMI通信.docx](https://file1.bdocx.com/fileroot1/2023-1/30/e82a202b-f3f9-41a3-9620-80b7919a8108/e82a202b-f3f9-41a3-9620-80b7919a81081.gif)
单片机通过Modbus协议与HMI通信
如何用单片机通过MODBUS协议与HMI通信
一.Modbus简介
Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(SchneiderAutomation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。
此协议支持传统的RS-232、RS-422、RS-485和以太网设备。
许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。
Modbus协议包括ASCII、RTU、TCP等,并没有规定物理层。
Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave端的数据,实现双向读写。
Modbus协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC校验,RTU模式采用16位CRC校验。
ASCII协议和RTU协议相比拥有开始和结束标记,因此在进行程序处理时能更加方便,而且由于传输的都是可见的ASCII字符,所以进行调试时就更加的直观,另外它的LRC校验也比较容易。
但是因为它传输的都是可见的ASCII字符,RTU传输的数据每一个字节ASCII都要用两个字节来传输,比如RTU传输一个十六进制数0xF9,ASCII就需要传输’F’’9’的ASCII码0x39和0x46两个字节,这样它的传输的效率就比较低。
所以一般来说,如果所需要传输的数据量较小可以考虑使用ASCII协议,如果所需传输的数据量比较大,最好能使用RTU协议。
二.ModBus消息帧
使用ASCII模式,消息以冒号(:
ASCII码3AH)开始,以回车换行(ASCII码0DH,0AH)符结束。
其它域可以使用的传输字符0...9,A...F。
网络上的设备不断侦测:
字符,当有一个冒号接收到时,每个设备都解码下个域(地址域)来判断是否发给自己的。
消息中字符间发送的时间间隔最长不能超过1秒,否则接收的设备将认为传输错误。
一个典型消息帧如下所示:
模式
起始
地址
功能
数据
校验
结束
ASCII
:
设备地址
功能代码
起地址
数据数
数据
数据n
LRC高字节
LRC低字节
例如
:
06
03
006B
0003
使用RTU模式,两个消息间至少要有3.5个字符时间的停顿间隔,整个消息帧必须作为一连续的流转输,如果在帧完成之前有超过1.5个字符时间的停顿时间,接收设备将假定下一字节是一个新消息的地址域。
同样,如果一个新消息在小于3.5个字符时间内接着前个消息开始,接收的设备将会认为它是前一消息的延续。
这将导致一个错误,所以每一帧间的间隔必须大于3.5个字符时间,而在一帧内每个数据间隔不应大于1.5个字符时间.
模式
起始
地址
功能
数据
校验
结束
RTU
(4T)
设备地址
功能代码
起地址
数据数
数据
数据n
CRC高字节
CRC低字节
(4T)
例如
06
03
006B
0003
三.参考程序:
下面以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;
TR1 =1; //TR1:
timer1run
//超时等待3.5个字符位以判断帧结束。
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{
format_trans_send();//按约写的规格发送一个字节
}
else
{
trans_finished=1;
prepare_recv(); //发送完毕,转为接收状态
}
}
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,用于帧超时计时
{
TR2=0;
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;
ET2=1;
TR2=1;
REN=0;
}
else
prepare_recv(); //否则丢弃这次接收,重新开始
}
else
{
{
if(!
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,