RS485通信和Modbus通信协议汇总

1. 主从模式

RS-485上的软件层协议ModBus主要依赖于主从模式。主从模式是指在半双工通讯方式上,2个或者2个以上的设备组成的通讯系统中:


这里写图片描述
(1) 至少且只有一个主机,其他的都是从机
(2) 不管任何时候,从机都不能主动向主机发送数据
(3) 主机具有访问从机的权限,从机不可以主动访问从机,任何一次数据交换,都要由主机发起
(4)不管是主机还是从机,系统一旦上电,都要把自己置于接收状态(或者称为监听状态)
主从机的数据交互,需要:
a. 主机将自己转为发送状态
b. 主机按照预先约定的格式发出寻址数据帧。
所谓的约定,可是主机开发者和从机开发者约定好的规约,好,例如主机要通过从机控制接在从机的电机,主机要启动电机就往从机发0x1,停止电机就往从机发0x2。这就是一种预
先约定好的格式,但是这样做,互换性、兼容性、通用性差,例如其他公司是约定发送0x03让电机转动,发0x04让电机停止。导致不同厂家的主机、从机不能相互通讯。用户需要的,就像网络操作,只要接入有网的网线那么计算机都能上网。
所以说,我们需要一种大家都共同遵循的规则(可以是ModBus,也可以是TCP/IP等上层协议),这种大家认可,共同遵循的软件层协议。软件层协议主要是解决如何解析传输的数据,即传输的目的或者更加可靠的传输数据。
半双工通讯中,都是主机寻找从机,主机的目的无非有: 主机要发数据给从机,或者主机要从从机中获取数据。
c. 主机恢复自身的接收状态
主机等待自身所寻址的从机作回应,也就是说从机接收到主机的寻址命令、数据后一定要回应主机,不然主机会认为从机通讯异常。回应数据包也是要按照ModBus协议规约(其实不局限ModBus,像TCP/IP也需要回应是吧!~)

2. ModBus通讯协议

通俗点来讲,ModBus规约了起停电机,主机要分别发送什么命令给从机。ModBus规定主从机之间数据的交互,需要遵循什么样的格式,如何保证数据在传输过程中不发生冲突。只要都遵循这个协议,那么不同厂家的主从机就可以共用了。
ModBus一般是工作在一主多从的场景,还是这个图:

  • 71
    点赞
  • 460
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个基于RS485通信Modbus通信协议的C语言例程: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #define RS485_DEV "/dev/ttyUSB0" // 串口设备文件路径 #define BAUD_RATE B9600 // 波特率 #define DATA_BITS CS8 // 数据位数 #define STOP_BITS 1 // 停止位数 #define PARITY_NONE 0 // 校验位 int fd; // 串口文件描述符 // 打开串口函数 int open_port(char *port) { int fd; fd = open(port, O_RDWR | O_NOCTTY); if (fd < 0) { perror("open_port: Unable to open serial port"); return -1; } struct termios options; tcgetattr(fd, &options); // 设置波特率 cfsetispeed(&options, BAUD_RATE); cfsetospeed(&options, BAUD_RATE); // 设置数据位、停止位和校验位 options.c_cflag &= ~CSIZE; options.c_cflag |= DATA_BITS; options.c_cflag &= ~(PARENB | PARODD); options.c_cflag |= PARITY_NONE; options.c_cflag &= ~CSTOPB; // 设置为非规范模式和无缓冲模式 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10; // 设置为原始模式 options.c_oflag &= ~OPOST; options.c_iflag &= ~(INLCR | ICRNL | IGNCR); options.c_iflag &= ~(IXON | IXOFF | IXANY); tcsetattr(fd, TCSANOW, &options); return fd; } // 发送Modbus命令函数 int send_modbus_cmd(unsigned char *cmd, int cmd_len, unsigned char *rx_buf, int rx_len) { // 设置RS485为发送模式 ioctl(fd, TIOCMGET, &status); status |= TIOCM_RTS; ioctl(fd, TIOCMSET, &status); // 发送Modbus命令 write(fd, cmd, cmd_len); // 等待接收Modbus响应 usleep(10000); // 设置RS485为接收模式 ioctl(fd, TIOCMGET, &status); status &= ~TIOCM_RTS; ioctl(fd, TIOCMSET, &status); // 接收Modbus响应 int rxed = read(fd, rx_buf, rx_len); return rxed; } int main(int argc, char *argv[]) { unsigned char cmd[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A}; // Modbus命令 unsigned char rx_buf[1024]; // 接收缓冲区 fd = open_port(RS485_DEV); // 打开串口 if (fd < 0) { printf("Failed to open serial port\n"); return -1; } int rxed = send_modbus_cmd(cmd, sizeof(cmd), rx_buf, sizeof(rx_buf)); // 发送Modbus命令并接收响应 if (rxed < 0) { printf("Failed to send Modbus command\n"); return -1; } printf("Modbus response: "); for (int i = 0; i < rxed; i++) { printf("%02X ", rx_buf[i]); } printf("\n"); close(fd); // 关闭串口 return 0; } ``` 以上例程实现了发送一个读取线圈状态的Modbus命令并接收响应。其中,`open_port`函数用于打开串口并设置其通信参数,`send_modbus_cmd`函数用于发送Modbus命令并接收响应。在发送Modbus命令前,需要将RS485设置为发送模式,接收响应后需要将其设置为接收模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值