跳转至

RS485 SDK

RS485协议

概述

RS485(全称:Recommended Standard 485)是一种用于串行数据通信的标准,广泛应用于工业自动化、传感器网络、楼宇控制、远程设备通信等领域。RS485支持多个设备(通常为32个)在同一总线上进行数据通信,具有较长的传输距离和较强的抗干扰能力。

特点

  • 多点通信:RS485支持多点通信,可以在同一总线上连接多个设备。通常,最多可连接32个设备(更高的连接数量需要采用驱动器和接收器的特殊设计)。
  • 差分信号传输:RS485使用差分信号传输数据,即信号通过两根线路(A和B)传输,具有较强的抗干扰能力。这使得RS485非常适合在有噪声的环境中使用。
  • 长距离通信:RS485可以支持远距离的通信,通常可以达到1200米(在9600 bps下),高传输速率下可能需要较短的距离。
  • 半双工通信:通信双方交替进行数据发送和接收,RS485最常见的应用模式。
  • 通信速率:RS485的最大通信速率取决于线缆长度和电气特性,但通常可以达到10 Mbps。

RS485的工作原理

RS485协议采用差分信号传输,这意味着数据在两根线路(A和B)上通过电压差传输。当数据传输时,A线和B线上的电压差决定了传输的数据位。

数据传输

  • 逻辑“1”:A线电压高于B线电压。
  • 逻辑“0”:A线电压低于B线电压。

通信模式

  • 半双工通信:在半双工模式下,RS485总线上的设备交替发送和接收数据。在发送数据时,设备的驱动器将信号驱动到总线上,其他设备则处于接收状态。

驱动器与终端电阻

RS485总线的两端通常需要加上终端电阻(通常为120Ω),以避免信号反射,确保信号质量。

RS485的应用

RS485广泛应用于各种需要远距离数据传输的场景,如:

  • 工业自动化:用于PLC、传感器、执行器等设备的远程控制和数据采集。
  • 楼宇控制系统:如智能楼宇控制器、消防报警系统、监控系统等。
  • 智能电表:RS485常用于与智能电表进行数据通信。
  • 传感器网络:如温湿度传感器、气体传感器等设备的集成与监控。

硬件接口

接口说明

BK1000设备共提供6路RS485接口,BK1000设备共提供8路RS485端口,其接口定义为

端口序号 端口丝印 系统文件名
RS485-1 RS485-A1/RS485-B1 /dev/ttyAS2
RS485-2 RS485-A2/RS485-B2 /dev/ttyAS3
RS485-3 RS485-A3/RS485-B3 /dev/ttyAS4
RS485-4 RS485-A4/RS485-B4 /dev/ttyAS5
RS485-5 RS485-A5/RS485-B5 /dev/ttyCHUSB0
RS485-6 RS485-A6/RS485-B6 /dev/ttyCHUSB1
RS485-7 RS485-A7/RS485-B7 /dev/ttyCHUSB2
RS485-8 RS485-A8/RS485-B8 /dev/ttyCHUSB3

接线方式

AB 分别连接到目标设备的对应端子

API说明

请您确保已经将SDK引入到项目中,SDK的相关引入可参考SDK安装章节。

SDK中封装了基础的串口操作,开发人员可以通过相关API快速的控制串口的打开、关闭,进行串口消息的读写。

使用串口相关操作函数,需要引用 rs485.h头文件。

rs485_init

功能

初始化指定485接口

函数原型

/**
 * @brief 485接口初始化
 *
 * @param[in] ch     485接口序号,BK1000设备1~6,BK2000设备1~8
 * @param[in] bps    485接口波特率
 *
 * @return
 *      -  1: 成功
 *      - -1: 初始化失败
 *      - -2: 授权校验失败
 *
 */
int rs485_init(int ch, int bps);

参数

参数名 类型 说明
ch int 485接口序号,BK1000设备1\~6,BK2000设备1\~8
baudrate int 端口波特率,如115200

返回值

  • 成功:1
  • 失败:
    • 初始化失败:-1
    • 授权校验失败:-2

rs485_write

功能

485接口发送数据

函数原型

/**
 * @brief 485接口发送数据
 *
 * @param ch[in]    485接口序号,BK1000设备1~6,BK2000设备1~8
 * @param buf[in]   发送的数据
 * @param len[in]   发送的数据长度
 *
 * @return
 *      - >0:  写入数据长度
 *      - -1:  失败
 */
int rs485_write(int ch, u8 *buf, int len);

参数

参数名 类型 说明
ch int 485接口序号,BK1000设备1\~6,BK2000设备1\~8
data u8 发送的数据
len int 发送的数据长度

返回值

  • 成功:>0,写入的数据长度
  • 失败:-1

rs485_read

功能

发送串口消息

函数原型

/**
 * @brief 485接口发送数据
 *
 * @param ch[in]    485接口序号,BK1000设备1~6,BK2000设备1~8
 * @param buf[out]  读取的数据
 *
 * @return
 *      - >0:  读取数据长度
 *      - -1:  失败
 */
int rs485_read(int ch, u8 *buf);

参数

参数名 类型 说明
ch int 485接口序号,BK1000设备1\~6,BK2000设备1\~8
buf u8 读取的数据

返回值

  • 成功:>0,读取的数据长度
  • 失败:-1

rs485_close

功能

485接口释放

函数原型

/**
 * @brief 485释放
 *
 * @param ch[in]    485接口序号,BK1000设备1~6,BK2000设备1~8
 *
 * @return
 *      - 1:  成功
 *      - -1:  失败
 */
int rs485_close(int ch);

参数

参数名 类型 说明
ch int 485接口序号,BK1000设备1\~6,BK2000设备1\~8

返回值

  • 成功:1
  • 失败:-1

示列代码

以下以控制第1路485串口为例,进行相关API操作的说明

#include "rs485.h"
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>

/**
 * 循环写操作线程函数
 */
void *rs485_test_write(void *arg)
{
    // 发送消息的接口序号
    int ch = *(int *)arg;
    // 发送消息长度
    int buffer_size = 32;
    // 发送的消息体
    uint8_t write_buffer[buffer_size];
    // 填充消息体数据
    for (int i = 0; i < buffer_size; ++i)
    {
        write_buffer[i] = (uint8_t)i;
    }
    // 循环发送数据
    while (1)
    {
        // 调用SDK 写函数进行消息发送
        int bytes_written = rs485_write(ch, write_buffer, buffer_size);
        // 发送失败
        if (bytes_written < 0)
        {
            printf("Write failed!\n");
        }
        // 发送成功
        else
        {
            printf("Written %d bytes.\n", bytes_written);
        }
        // 休眠1秒
        sleep(1);
    }
}

/**
 * 循环读操作线程函数
 */
void *rs485_test_read(void *arg)
{
    // 读取消息的接口序号
    int ch = *(int *)arg;
    // 读书数据缓冲区
    uint8_t read_buffer[64];
    // 循环读取数据
    while (1)
    {
        // 调用SDK 读函数进行消息读取
        int bytes_read = rs485_read(ch, read_buffer);
        // 读取消息失败
        if (bytes_read < 0)
        {
            printf("Read failed!\n");
        }
        // 读取消息成功
        else
        {
            // 以16进制形式打印读取到的消息体
            printf("Read %d bytes:\n", bytes_read);
            for (int i = 0; i < bytes_read; ++i)
            {
                printf("0x%02x ", read_buffer[i]);
            }
            printf("\n");
        }
        // 休眠500毫秒
        usleep(500 * 1000);
    }
}

int main()
{
    // 定义RS485接口序号
    int channel = 1;
    // 初始化RS485接口
    int rc = rs485_init(channel, 115200);
    // 初始化失败
    if (rc < 0)
    {
        printf("Failed to initialize RS485!\n");
        return -1;
    }
    // 声明循环读写线程
    pthread_t write_thread, read_thread;
    // 创建写线程
    if (pthread_create(&write_thread, NULL, rs485_test_write, (void *)&channel) != 0)
    {
        printf("Failed to create write thread!\n");
        return -1;
    }

    // 创建读线程
    if (pthread_create(&read_thread, NULL, rs485_test_read, (void *)&channel) != 0)
    {
        printf("Failed to create read thread!\n");
        return -1;
    }

    // 等待线程结束
    pthread_join(write_thread, NULL);
    pthread_join(read_thread, NULL);
    // 释放端口
    rs485_close(channel);
    return 0;
}