ModBus RTU协议 -->c语言实现

ModBus RTU协议 -->c语言实现 易百纳用户53690 2023-11-23 15:02:28 332

文章目录

ModBus RTU协议

前言: 最近在SS528上适配传感器,其中就有一款传感器是rs485通信,于是就接触到ModBus RTU协议,我赶紧上网查找相应的资料,发现相关代码多还是多,就是全都要money,经过一小段时间的摸索和尝试,基本完成了通信功能,能够实现数据的接收与发送,代码我就放在最后啦,有需要的朋友可以自取

1 ModBus RTU协议简介

Modbus RTU(Remote Terminal Unit,远程终端单元)是一种串行通信协议,用于在自动化领域中的设备之间进行通信。它通常用于工业控制系统和自动化领域中的设备之间进行数据传输。
ModBus RTU协议格式:
帧格式: Modbus RTU协议的数据帧包含了地址、功能码、数据、CRC(循环冗余校验)和结束位。它可以被分为发送方和接收方。
地址: 每个设备在总线上都有一个唯一的地址,用于识别通信的目标设备。
功能码: 它指示了设备执行的特定功能,如读取寄存器、写入寄存器、读取输入状态等。
数据: 数据部分包含了传输的实际信息。
CRC校验: 用于检测数据传输的错误,以保证数据的准确性。

2 ModBus RTU数据帧示例

示例数据问询帧如下图所示:

示例数据应答帧如下图所示:

3 ModBus RTU 具体代码实现

我们根据2 的数据帧示例来进行编写代码,具体代码如下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdint.h>


int init_port(int serialPort)
{
const char *serialPort = "/dev/ttyAMA3";
    int serial_fd ;

    // Open the serial port
    serial_fd = open(serialPort, O_RDWR | O_NOCTTY);
    if (serial_fd == -1) {
        handleError("Error opening serial port");
    }
 struct termios tty;
    if (tcgetattr(serial_fd, &tty) != 0) {
        perror("Error from tcgetattr");
        close(serial_fd);
        return -1;
    }

    // 设置为非规范模式(二进制模式)
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_oflag &= ~OPOST;
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_cflag &= ~(CSIZE | PARENB);
    tty.c_cflag |= CS8;

    // 设置波特率
    cfsetospeed(&tty, B9600);
    cfsetispeed(&tty, B9600);

 if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
        perror("Error from tcsetattr");
        close(serial_fd);
        return -1;
    }
    return serial_fd;

}


int pm_get(int serialPort)
{
    unsigned char modbus_setframe[] = {0x01,0x03,0x00,0x07,0x00,0x03,0xB4,0x0A};
     write(serialPort, modbus_setframe, 8);
// Read data from the serial port
    char buffer[20];
    ssize_t bytesRead=0;
    bytesRead = read(serialPort, buffer, 20);
     if (bytesRead == 0) {
        printf("No data received.\n");
    } else {
        handleError("Error reading from serial port");
    }
    uint8_t address =  buffer[0];
    uint8_t functioncode = buffer[1];
    uint16_t PM1_0 = (buffer[3] << 8) | buffer[4];
    uint16_t PM2_5 = (buffer[5] << 8) | buffer[6];
    uint16_t PM10_0 = (buffer[7] << 8) | buffer[8];

    //此处省略crc校验

    printf("addr:0x%02X,Funcode:0x%02X \n",address,functioncode);
    printf("PW1.5 data is %d ,PWD2.5 data is %d,PWD10 data is %d\n",PM1_0,PM2_5,PM10_0);
    return 0;
}


int main() {
    int ret;
    int len;
    int serialPort = open("/dev/ttyAMA3", O_RDWR);
    if (serialPort == -1) {
        perror("Error opening serial port");
        exit(1);
    }
    // 配置串口参数
   ret=init_port(serialPort);

   pm_get(serialPort );
   close(serialPort);
}
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 1 1 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
易百纳用户53690
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区