第 65 / 120 课 · 常见外设的 Linux 用法。返回课程合集。
机制与资源关系
串口 fd 的行为受 termios 控制,规范模式可能等待换行,回显和字符转换会修改字节流。二进制协议通常需要明确原始模式、波特率、字长、校验、停止位和流控。
实际用法与观察入口
以下是操作说明;先确认执行环境、工具帮助和目标对象。设备名、PID、地址及项目名示例需要按实际替换,不能将整段命令当通用板端脚本执行。
|
输出解读与排查顺序
先确认端口没被控制台或其他进程占用。VMIN、VTIME 与非阻塞模式的组合影响读取;协议层仍要处理拆包、粘包和校验。发送测试会影响外设,不能对未知设备随意写数据。
情境推演
二进制报文含 0x0a 却被转换或等待整行,先检查规范模式和输入输出标志。伪终端可复现这类用户态设置,物理乱码仍需额外检查串口参数与电平。
练习与参考分析
用本课伪终端实验验证原始字节收发,无需真实串口。参考结论:PTY 验证 termios 和应用读写,不验证物理波特率、RS-485 方向或电气质量。
独立实验包
主机 Linux 的有界 C 实验;不访问真实外设,不代表板端时序或性能。 默认入口、源文件和实际运行记录都在下载包中。
实验:UART、termios 与串口使用
查看完整代码:main.c
int main(void) {
int master=posix_openpt(O_RDWR | O_NOCTTY); CHECK(master >= 0);
CHECK(grantpt(master) == 0 && unlockpt(master) == 0);
char *name=ptsname(master); CHECK(name != NULL);
int slave=open(name,O_RDWR | O_NOCTTY); CHECK(slave >= 0);
struct termios options; CHECK(tcgetattr(slave,&options) == 0);
cfmakeraw(&options); CHECK(tcsetattr(slave,TCSANOW,&options) == 0);
const unsigned char input[]={0,0x0a,0x7f,0xff};
CHECK(write(master,input,sizeof(input)) == (ssize_t)sizeof(input));
unsigned char output[sizeof(input)]; size_t offset=0;
while (offset < sizeof(output)) {
struct pollfd watch={.fd=slave,.events=POLLIN};
CHECK(poll(&watch,1,1000) == 1 && (watch.revents & POLLIN));
ssize_t n=read(slave,output+offset,sizeof(output)-offset);
CHECK(n > 0); offset+=(size_t)n;
}
CHECK(memcmp(input,output,sizeof(input)) == 0);
CHECK(close(slave) == 0 && close(master) == 0);
puts("PTY raw bytes preserved: 00 0a 7f ff; no electrical UART test");
return 0;
}
在项目根目录执行;下载包解压后,在解压目录执行 sh run.sh。
cd 'content/posts/驱动、bootloader、文件系统/嵌入式Linux系统工程/065-UART、termios 与串口使用/code' && sh run.sh
官方资料与版本边界
内核、工具和厂商 BSP 的支持范围需分别核对。参考资料可能对应较新版本;不要据此推定旧 BSP 支持所有接口。