硬件

控制器

SOC MPU或者MCU端必须集成UART控制器,当前也有用软件模拟的情况

收发器

LTC2859设计参考

img

NSI83085A设计参考,SOC侧引脚:TXD、RXD、DE/RE(半双工接法),通信引脚:A、B

img

引脚接线

实际接法也很简单,只需接A和B两根线就可以了

img

操作

配置串口设备波特率:9600

1
stty -F /dev/ttyLP2 9600 cs8 -parenb -cstopb raw -echo

使能引脚xxx,这个引脚编号对应485收发器的DE/RE引脚

1
2
echo xxx > /sys/class/gpio/export
echo out > /sys/class/gpio/gpioxxx/direction

半双工工作模式切换:置高电平意味着给RS485发送数据,低电平意味着从RS485接收数据

1
2
echo 1 > /sys/class/gpio/gpioxxx/value  # 发送模式
echo 0 > /sys/class/gpio/gpioxxx/value # 接收模式

查看接收数据(接收模式)

1
cat /dev/ttyLP2

发送数据(发送模式)

1
while true; do echo "Hello RS485!\\r\\n" > /dev/ttyLP2; sleep 1; done;

编码

打开串口设备

1
2
3
4
5
6
// open ttyLP2
int fd = open("/dev/ttyLP2", O_RDONLY);
if (fd == -1) {
printf("Unable to open dev!\n");
return -1;
}

配置参数:9600 8N1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// uart config
struct termios ts;
memset(&ts, 0, sizeof ts);
if(tcgetattr(fd, &ts) != 0) {
perror("Error from tcgetattr");
return -1;
}

// cfsetospeed(&ts, B9600);
cfsetispeed(&ts, B9600);

ts.c_cflag &= ~PARENB; // 清除校验位
ts.c_cflag &= ~CSTOPB; // 停止位为1
ts.c_cflag &= ~CSIZE;
ts.c_cflag |= CS8; // 8位数据位
ts.c_cflag &= ~CRTSCTS; // 无硬件流控
ts.c_cflag |= CREAD | CLOCAL; // 打开接收器,忽略modem控制线
ts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始输入
ts.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控
ts.c_oflag &= ~OPOST; // 原始输出
ts.c_cc[VMIN] = 0; // 读取时不等待
ts.c_cc[VTIME] = 5; // 0.5秒超时

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

配置收发模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
int configure_rs485_gpio(void) {
int fd;

// 导出 GPIO
fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd == -1) {
perror("无法导出 GPIO");
return -1;
}
write(fd, "142", 3);
close(fd);

// 设置为输出模式
fd = open("/sys/class/gpio/gpio142/direction", O_WRONLY);
if (fd == -1) {
perror("无法设置 GPIO 方向");
return -1;
}
write(fd, "out", 3);
close(fd);

// 打开值文件用于读写
gpio_fd = open("/sys/class/gpio/gpio142/value", O_RDWR);
if (gpio_fd == -1) {
perror("无法打开 GPIO 值文件");
return -1;
}

// 初始设置为接收模式
set_rs485_receive_mode();

return 0;
}

// 设置为发送模式
void set_rs485_transmit_mode(void) {
if (gpio_fd != -1) {
lseek(gpio_fd, 0, SEEK_SET);
write(gpio_fd, "1", 1);
// 延时确保硬件切换完成(根据实际硬件调整)
usleep(500); // 500 微秒,可根据实际情况调整
}
}

// 设置为接收模式
void set_rs485_receive_mode(void) {
if (gpio_fd != -1) {
lseek(gpio_fd, 0, SEEK_SET);
write(gpio_fd, "0", 1);
// 延时确保硬件切换完成
usleep(500);
}
}

读取UART数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// receive data from PC
set_rs485_receive_mode();

while(1) {
char buf[256];
int ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
printf("Reading error!\n");
return -1;
}
buf[ret] = '\0';
printf("Receive %d bytes : %s\n", ret, buf);
sleep(1);
}

『 下里巴人 』
海纳百川,文以载道
hywing技术自留地
总访问 113701 次 | 本页访问 326