硬件
控制器
SOC MPU或者MCU端必须集成UART控制器,当前也有用软件模拟的情况
收发器
LTC2859设计参考

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

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

操作
配置串口设备波特率: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
| while true; do echo "Hello RS485!\\r\\n" > /dev/ttyLP2; sleep 1; done;
|
编码
打开串口设备
1 2 3 4 5 6
| 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
| struct termios ts; memset(&ts, 0, sizeof ts); if(tcgetattr(fd, &ts) != 0) { perror("Error from tcgetattr"); return -1; }
cfsetispeed(&ts, B9600);
ts.c_cflag &= ~PARENB; ts.c_cflag &= ~CSTOPB; ts.c_cflag &= ~CSIZE; ts.c_cflag |= CS8; ts.c_cflag &= ~CRTSCTS; ts.c_cflag |= CREAD | CLOCAL; 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;
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; 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); } }
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
| 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); }
|