串口通信初始化过程是怎样的???
一、简介
本文简单介绍一下 Linux嵌入式开发中,串口通信的初始化过程。
二、串口通信的初始化过程
串口通信初始化过程涉及配置串行端口的参数,以确保设备间能够正确地进行数据传输。这通常包括设置波特率、数据位、停止位、校验位等。以下是一个详细的步骤指南,以及如何在 Linux 环境下通过 C 语言完成串口通信的初始化。
1. 初始化串口的基本步骤:
打开串口设备:
使用 open() 函数打开串口设备文件(例如 /dev/ttyS0 或 /dev/ttyUSB0),并指定适当的访问模式(读写权限)和标志。
获取当前串口属性:
使用 tcgetattr() 函数获取串口当前的配置信息到一个 termios 结构体中,以便后续修改。
修改串口属性:
设置波特率:cfsetspeed()设置波特率。
配置数据位。
配置停止位;
配置校验类型,也可以配置无校验(是否有奇偶校验)。
根据需要启用或禁用硬件流控(CRTSCTS)、或者软件流控(IXON, IXOFF, IXANY)等。
设置超时和最小读取字符数(目的是控制read()函数从串口读取数据的阻塞行为,这样非常重要,防止读取阻塞);
设置本地模式并启用接收。
禁用回显等等其他配置;
应用新的串口属性:
使用 tcsetattr() 函数将修改后的串口设置应用于串口设备。
2. 初始化过程中,控制从串口读取数据的阻塞行为
串口通信初始化过程中,设置超时和最小读取字符数配置是很重要的,这两个配置是为了控制read()函数从串口读取数据的阻塞行为!!!
在串口通信中,设置超时和最小读取字符数是非常重要的,这可以帮助你控制数据读取的行为,避免程序无限期等待数据或过早读取不完整的数据。这些设置是通过 termios
结构体中的 c_cc
成员来配置的,具体来说是使用 VMIN
和 VTIME
控制字符。
一、参数定义与作用
这两个参数位于 termios 结构体的 c_cc 数组中,用于配置串口的读取规则:
VMIN:最小读取字符数(c_cc[VMIN])
定义 read() 函数返回前需要接收到的最小字符数量。
VTIME:超时时间(c_cc[VTIME])
单位为 0.1 秒,定义等待数据的最长时间(与 VMIN 配合使用)。
二、常见配置组合及效果
VMIN 和 VTIME 的不同组合会产生完全不同的读取行为,需根据实际场景选择:
三、Linux应用层串口通信示例代码
下面是Linux应用层串口通信示例代码:
int initComm(char *ttyDir, unsigned speed)
{int retry = 60; // 设备锁定重试次数(60秒超时)// 以读写方式打开串口设备,不设为控制终端int mfd = open(ttyDir, O_RDWR | O_NOCTTY);if (mfd < 0){perror(ttyDir); return -1;}// 尝试获取设备锁,防止多进程同时访问while (lockf(mfd, F_TLOCK, 0) < 0){sleep(1); retry--; if (retry <= 0){printf("Device %s locked.\n", ttyDir); close(mfd); return -1;}}// 将数值波特率转换为系统定义的波特率常量switch (speed){case 4800:speed = B4800;break;case 9600:speed = B9600;break;case 19200:speed = B19200;break;case 38400:speed = B38400;break;case 57600:speed = B57600;break;case 115200:speed = B115200;break;case 230400:speed = B230400;break;case 460800:speed = B460800;break;default:printf("speed error"); return -1;}// 获取当前串口属性struct termios Opt;tcgetattr(mfd, &Opt);// 设置波特率cfsetispeed(&Opt, speed); // 输入速度cfsetospeed(&Opt, speed); // 输出速度tcsetattr(mfd, TCSANOW, &Opt); //立即应用设置tcflush(mfd, TCIOFLUSH); // 清空输入输出缓冲区// 重新获取属性以确保设置生效tcgetattr(mfd, &Opt);// 配置串口参数Opt.c_cflag &= ~CSIZE; // 清除数据位掩码Opt.c_cflag |= CS8; // 设置8位数据位// 启用软件流控(XON/XOFF)Opt.c_cflag |= IXON | IXOFF | IXANY; Opt.c_cflag &= ~PARENB; // 禁用奇偶校验Opt.c_cflag &= ~CSTOPB; // 设置1位停止位(清除2位停止位标志)// 设置本地模式标志// 原始模式(非规范模式),禁用回显和信号 Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 设置输入模式标志// 禁用特殊输入处理 Opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); // 设置输出模式标志// 原始输出(禁用输出处理)Opt.c_oflag &= ~OPOST; // 设置超时和最小读取字符数// 读取超时(单位:0.1秒,这里15秒)// 最小读取字符数(0表示非阻塞)Opt.c_cc[VTIME] = 150; Opt.c_cc[VMIN] = 0; // 应用新的串口属性设置if (tcsetattr(mfd, TCSANOW, &Opt) < 0){perror(ttyDir); close(mfd); return -1;}tcflush(mfd, TCIOFLUSH); //再次清空输入输出缓冲区return mfd; // 返回配置好的串口文件描述符
}