当前位置:网站首页>RS-485总线通信应用
RS-485总线通信应用
2022-07-26 22:49:00 【李今天摸鱼了嘛?】
概述:
掌握总线基础知识
了解Modbus通讯协议基本知识
能够进行基于Modbue串行通信协议软件开发
能够搭建RS-485总线并编程实现组网通信
一、Modbus概述
1.什么是Modbus通信协议
Modbus通信协议由Modicon(现为施耐德电气公司的一个品牌)在1979年开发,是全球第一个真正用于工业现场的总线协议。为了更好地普及和推动Modbus在以太网上的分布式应用,目前施耐德公司已将Modbus协议的所有权移交给IDA(Interface for DistributedAutomation,分布式自动化接口)组织,并专门成立了Modbus-IDA组织。该组织的成立为Modbus未来的发展奠定了基础。
Modbus通信协议是应用于电子控制器上的一种通用协议,目前已成为一通用工业标准。通过此协议,控制器之间或者控制器经由网络(例如,以太网)与其他设备之间可以通信。Modbus使不同厂商生产的控制设备可以连成工业网络,进行集中监控。Modbus通信协议定义了一个消息帧结构,并描述了控制器请求访问其他设备的过程,控制器如何响应来自其他设备的请求,以及怎样侦测错误并记录。
在Modbus网络上通信时,每个控制器必须知道它们的设备地址,识别按地址发来的消息,决定要做何种动作。如果需要响应,则控制器将按Modbus消息帧格式生成反馈信息并发出。
2.Modbus通信协议的版本
Modbus通信协议有多个版本:基于串行链路的版本、基于TCP/IP的网络版本以及基于其他互联网协议的网络版本,其中前面两者的实际应用场景较多。
基于串行链路的Modbus通信协议有两种传输模式,分别是Modbus RTU与ModbusASCII,这两种模式在数值数据表示和协议细节方面略有不同。Modbus RTU是一种紧凑的、采用二进制数据表示的方式,而Modbus ASCII的表示方式更加冗长。在数据校验方面.Modbus RTU采用循环冗余校验方式,而Modbus ASCII采用纵向冗余校验方式。另外,配置为Modbus RTU模式的节点无法与Modbus ASCII模式的节点通信。
3.5.2 Modbus通信的请求与响应
Modbus是一种单主/多从的通信协议,即在同一段时间内总线上只能有一个主设备,但可以有一个或多个(最多247个)从设备。主设备是指发起通信的设备,从设备是接收请求并做出响应的设备。在Modbus网络中,通信总是由主设备发起,而从设备没有收到来自主设备的请求时不会主动发送数据。
二、Modbus寄存器
寄存器是Modbus通信协议的一个重要组成部分,它用于存放数据。
Modbus寄存器最初借鉴于PLC(Programmable Logical Controller,可编程控制器)。后来随着Modbus通信协议的发展,寄存器这个概念也不再局限于具体的物理寄存器,而是逐渐拓展到了内存区域范畴。根据存放的数据类型及其读写特性,Modbus寄存器被分为4种类型。

三、Modbus功能码
1.功能码分类
Modbus功能码是Modbus消息帧的一部分,它代表将要执行的动作。以RTU模式为例,见表3-7,RTU消息帧的Modbus功能码占用一个字节,取值范围为1~127。
Modbus标准规定了3类Modbus功能码:公共功能码、用户自定义功能码和保留功能码。公共功能码是经过Modbus协会确认的,被明确定义的功能码,具有唯一性。

四、实验
(1)485主机每隔0.5S查询从传感器数据的Modbus帧。
(2)485网络中从机收到通讯帧后,解析内容,判断是否是发给自己的,然后根据功能码要求采集响应传感数据给主机。
(3)主机收到传感数据后,上报网关
(4)网关通过TCP上报网关
1.定义Modbus帧与Modbus协议管理结构体
在portocol.h中定义:
//类modbus 接收帧定义
__packed typedef struct {
u8 address; //设备地址:0,广播地址;1~255,设备地址。
u8 function; //帧功能,0~255
// u8 count; //帧编号
// u8 datalen; //有效数据长度
u8 *data; //数据存储区
u16 chkval; //校验值
} m_rev_frame_typedef;
//Modbus协议管理结构体
typedef struct {
u8* rxbuf; //接收缓存区
u16 rxlen; //接收数据的长度
u8 frameok; //一帧数据接收完成标记:0,还没完成;1,完成了一帧数据的接收
u8 checkmode; //校验模式:0,校验和;1,异或;2,CRC8;3,CRC162.Modbus通讯帧解析函数
//解析一帧数据,解析结果存储在fx里面
//注意:本函数会用到malloc给fx数据指针申请内存,后续用完fx,一定要释放内存!!
//否则会引起内存泄露!!!
//fx:帧指针
//buf:输入数据缓冲区(串口接收到的数据)
//len:输入数据长度
//返回值:解析结果,0,OK,其他,错误代码。
m_result mb_unpack_frame(m_send_frame_typedef *tx,m_rev_frame_typedef *rx)
{
u16 rxchkval=0; //接收到的校验值
u16 calchkval=0; //计算得到的校验值
u8 cmd = 0 ; //计算功能码
u8 datalen=0; //有效数据长度
u8 address=0;
u8 recbyte=0;
u8 res;
DBG_B_INFO("主机解析包程序 ");
// fx->datalen=0; //数据长度清零
if(m_ctrl_dev.rxlen>M_MAX_FRAME_LENGTH||m_ctrl_dev.rxlen<M_MIN_FRAME_LENGTH) {
m_ctrl_dev.rxlen=0; //清除rxlen
m_ctrl_dev.frameok=0; //清除framok标记,以便下次可以正常接收
return MR_FRAME_FORMAT_ERR;//帧格式错误
}
datalen=m_ctrl_dev.rxlen;
DBG_B_INFO("当前数据长度 %d",m_ctrl_dev.rxlen);
switch(m_ctrl_dev.checkmode) {
case M_FRAME_CHECK_SUM: //校验和
calchkval=mc_check_sum(m_ctrl_dev.rxbuf,datalen+4);
rxchkval=m_ctrl_dev.rxbuf[datalen+4];
break;
case M_FRAME_CHECK_XOR: //异或校验
calchkval=mc_check_xor(m_ctrl_dev.rxbuf,datalen+4);
rxchkval=m_ctrl_dev.rxbuf[datalen+4];
break;
case M_FRAME_CHECK_CRC8: //CRC8校验
calchkval=mc_check_crc8(m_ctrl_dev.rxbuf,datalen+4);
rxchkval=m_ctrl_dev.rxbuf[datalen+4];
break;
case M_FRAME_CHECK_CRC16: //CRC16校验
calchkval=mc_check_crc16(m_ctrl_dev.rxbuf,datalen-2);
rxchkval=((u16)m_ctrl_dev.rxbuf[datalen-2]<<8)+m_ctrl_dev.rxbuf[datalen-1];
break;
}
DBG_B_INFO("calchkval = 0x%x 、rxchkval = 0x%x 、datalen = 0x%x",calchkval,rxchkval,datalen);
// DBG_B_INFO("cmd = 0x%x ",cmd);
m_ctrl_dev.rxlen=0; //清除rxlen
m_ctrl_dev.frameok=0; //清除framok标记,以便下次可以正常接收
if(calchkval==rxchkval) { //校验正常
address=m_ctrl_dev.rxbuf[0];
if (address!= tx->address) {
DBG_R_E("返回地址与发送地址不统一");
return MR_FRAME_SLAVE_ADDRESS; //地址错误
}
cmd=m_ctrl_dev.rxbuf[1];
if (cmd!=tx->function) {
DBG_R_E("发送命令与返回命令不统一");
return MR_FRANE_ILLEGAL_FUNCTION; //命令帧错误
}
switch (cmd) {
case 0x02:res=unpack_disc_reg(tx,rx);
break;
case 0x03:res=unpack_readhold_reg(tx,rx);
break;
case 0x04:res=unpack_readinput_reg(tx,rx);
break;
case 0x06:res=unpack_writehold_reg(tx,rx);
break;
default :
break;
}
} else {
return MR_FRAME_CHECK_ERR;
}
return MR_OK;
}
3.编写读取传感器数据并回复响应帧函数
主机发送读取传感器数据命令,从机解析完主机请求帧后,编写响应的函数。
u8 ReadInputRegister(void)
{
u16 regaddress;u16 regcount;
u16 *input_value_p;
u16 iregindex;
//发送缓冲区
u8 sendbuf|20];
u8 send_cnt=0;
//计算得到的校验值
u16 calchkval=0;
//取出主机请求帧中的素统
regaddress=(u16)(m_ctrl_dev.rxbuf|2)<<8);14.
regaddress|=(u16/(m_ctrl_dev.rxbuf|3]);
//取出主机请求帧中的素
regcount=(u16)(m_ctrl_dev.rxbuf(4]<<8);17.
regcount|=(u16)(m_ctrl_dev.rxbuf(5]);
input_value_p=inbuf;
//组建响应帧
if((1<=regcount)&&(regcount<4)){
if((regaddress>=0)&&(regaddress<=3)){
sendbuf[send_cnt]=SLAVE_ADDRESS;
//从机地址
send_cnt++;
sendbuf[send_cnt]=0x04;
//功能码0x04
send_cnt++;
sendbuf[send_cnt]=regcount*2;
//字节长度
send_cnt++;
iregindex=regaddress-0;
//将寄存器内容赋值给响应帧
while(regcount>0){
sendbuf[send_cnt]=(u8)(input_value_pliregindex]>>8);
send_cnt++;
sendbuf[send_cnt]=(u8)(input_value_pliregindex]&0xFF);
send_cnt++;
iregindex++;
regcount--;
}
switch(m_ctrl_dev.checkmode)
{
case M_FRAME_CHECK_SUM:
//校验和
calchkval=mc_check_sum(sendbuf,send_cnt);
break;
calchkval=me_check_xor(sendbuf,send_cnt);
case M_FRAME_CHECK_XOR://异或校验48.49.break;
case M_FRAME_CHECK_CRC8://CRC8校验
calchkval=me_check_crc8(sendbuf,send_cnt);break;
case M_FRAME_CHECK_CRC16:
//CRC16校验
calchkval=mc_check_crc16(sendbuf,send_cnt);
break;
}
if(m_ctrl_dev.checkmode==M_FRAME_CHECK_CRC16) //如果是CRC16,则有2个字节的CRC
{
sendbuf[send_cnt]=(calchkval>>8)&0XFF; //高字节在前
send_cnt++;
sendbuf[send_cnt]=calchkval&0XFF; //低字节在后
}
RS4851_Send_Buffer(sendbuf,send_cnt+1); //发送这一帧数据
}
}
else
{
return 1;
}
return 0;
}4.程序结构框架



边栏推荐
- 高度塌陷解决方法
- 2022年最新文本生成图像研究 开源工作速览(Papers with code)
- TCP的三次握手与四次挥手(简述)
- 动态路由ofps协议配置
- 7.7 SHEIN希音笔试
- STM32入门教程第一讲
- Solution: various error reporting and pit stepping and pit avoiding records encountered in the alchemist cultivation plan pytoch+deeplearning (III)
- C语言——赋值运算符、复合的赋值运算符、自增自减运算符、逗号运算符、条件运算符、goto语句、注释
- The basic configuration of static routing (planning of IP address and configuration of static routing) realizes the accessibility of the whole network.
- Three methods that can effectively fuse text and image information -- feature stitching, cross modal attention, conditional batch normalization
猜你喜欢

TCP的三次握手与四次挥手(简述)
![[explain C language in detail] takes you to play with loop structure (for_while_do while)](/img/d9/75053297873a5b5458514e7f557cdc.png)
[explain C language in detail] takes you to play with loop structure (for_while_do while)

STM32入门教程第一讲
![[volatile principle] volatile principle](/img/d4/adb4b43aaccecd506065ce838c569e.png)
[volatile principle] volatile principle

Dynamic routing ofps protocol configuration

HCIA(网络初级综合实验练习)

OSPF的重发布及路由策略

a元素的伪类

Brief introduction of VLAN principle and specific experimental configuration

TIM输出比较——PWM
随机推荐
2022 open source work of the latest text generated image research (papers with code)
动态路由ofps协议配置
Brief introduction of VLAN principle and specific experimental configuration
初识C语言(1)
STM32入门教程第一讲
Dynamic routing ofps protocol configuration
二层封装技术(HDLC、PPP--PAP\CHAP、GRE)实验练习
[explain C language in detail] takes you to play with functions
2022年最新文本生成图像研究 开源工作速览(Papers with code)
HCIA基础知识(1)
6.30滴滴面经(一面+二面)
Unity Huatuo revolutionary hot update series [1]
OSPF的重发布及路由策略
Unity Huatuo hot update environment installation and sample project
2022最新直播监控24小时监控(三)直播间弹幕解析
Static comprehensive experiment (comprehensive exercise of static route, loopback interface, default route, empty interface, floating static)
C language implementation of the small game [sanziqi] Notes detailed logic clear, come and have a look!!
First knowledge of Web Design
(CF1691D) Max GEQ Sum
[explain C language in detail] this article takes you to know C language and makes you impressed