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 |
接线方式
A 和 B 分别连接到目标设备的对应端子
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;
}