#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <termios.h>
#include <errno.h>
#define SERIAL_DEV "/dev/ttyS0" // 串口设备路径
#define BAUDRATE B115200 // 波特率
#define BUF_SIZE 1024 // 缓冲区大小
int exit_flag = 0; // 退出标志
int serial_fd; // 串口文件描述符
// 子线程:接收串口数据
void *recv_thread(void *arg) {
char buf[BUF_SIZE];
ssize_t len;
while (!exit_flag) {
// 读取串口数据(超时设置生效,无数据时返回-1,errno=EAGAIN)
len = read(serial_fd, buf, BUF_SIZE - 1);
if (len > 0) {
buf[len] = '\0';
printf("收到:%s\n", buf);
} else if (len == -1 && errno != EAGAIN) {
perror("串口接收失败");
break;
}
usleep(100000); // 短暂休眠,降低CPU占用
}
printf("接收线程退出\n");
return NULL;
}
// 配置串口函数
int serial_config(int fd) {
struct termios opt;
// 获取当前配置
if (tcgetattr(fd, &opt) != 0) {
perror("tcgetattr failed");
return -1;
}
// 设置波特率
cfsetispeed(&opt, BAUDRATE);
cfsetospeed(&opt, BAUDRATE);
// 配置数据位、校验位、停止位
opt.c_cflag &= ~PARENB; // 无奇偶校验
opt.c_cflag &= ~CSTOPB; // 1位停止位
opt.c_cflag &= ~CSIZE; // 清除数据位设置
opt.c_cflag |= CS8; // 8位数据位
// 禁用流控
opt.c_cflag &= ~CRTSCTS;
// 启用接收器,设置本地模式
opt.c_cflag |= (CLOCAL | CREAD);
// 禁用规范模式,不处理特殊字符(如回车换行)
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// 禁用输入处理(不转换回车换行)
opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
// 禁用输出处理(不转换换行)
opt.c_oflag &= ~OPOST;
// 设置超时:读取时等待10个十分之一秒(1秒),最小读取1字节
opt.c_cc[VTIME] = 10;
opt.c_cc[VMIN] = 0;
// 应用配置
if (tcsetattr(fd, TCSANOW, &opt) != 0) {
perror("tcsetattr failed");
return -1;
}
return 0;
}
int main() {
pthread_t tid;
char buf[BUF_SIZE];
// 打开串口
serial_fd = open(SERIAL_DEV, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_fd == -1) {
perror("打开串口失败");
return -1;
}
// 配置串口
if (serial_config(serial_fd) != 0) {
close(serial_fd);
return -1;
}
// 创建接收子线程
if (pthread_create(&tid, NULL, recv_thread, NULL) != 0) {
perror("创建线程失败");
close(serial_fd);
return -1;
}
// 主线程:发送数据
printf("请输入要发送的内容(输入exit退出):\n");
while (1) {
// 读取标准输入
if (fgets(buf, BUF_SIZE, stdin) == NULL) {
perror("读取输入失败");
break;
}
// 去除换行符
buf[strcspn(buf, "\n")] = '\0';
// 检查退出条件
if (strcmp(buf, "exit") == 0) {
exit_flag = 1;
break;
}
// 发送数据到串口
if (write(serial_fd, buf, strlen(buf)) == -1) {
perror("发送失败");
break;
}
printf("已发送:%s\n", buf);
}
// 回收子线程
pthread_join(tid, NULL);
// 关闭串口
close(serial_fd);
printf("程序退出\n");
return 0;
}