linux下的串口通信原理及编程实例
概述
一、串口的基本原理
1 串口通讯
串口通讯(Serial Communication
),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。
2 串口通讯的数据格式
一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束,字符之间没有固定的时间间隔要求。
每一个字符的前面都有一位起始位(低电平),字符本身由7位数据位组成,接着字符后面是一位校验位(检验位可以是奇校验、偶校验或无校验位),最后是一位或一位半或二位停止位,停止位后面是不定长的空闲位,停止位和空闲位都规定为高电平。实际传输时每一位的信号宽度与波特率有关,波特率越高,宽度越小,在进行传输之前,双方一定要使用同一个波特率设置。
3 通信方式
- 单工通信(
Simplex
)
定义:数据只能单向传输,一方固定为发送端,另一方为接收端。
特点:无法反向传输;成本低,适用于单向数据流场景。
示例:交通灯系统(信号灯→车辆/行人)、广播电台→收音机。 - 半双工通信(
Half-Duplex
)
定义:数据可双向传输,但同一时间仅允许单向传输,需切换方向。
特点:通过收发切换(如PTT按键)控制方向;存在传输延迟。
示例:对讲机(一方讲话时另一方只能收听)。 - 全双工通信
定义:数据可同时双向传输,无需切换方向。
特点:需独立收发通道(如双绞线);效率高、无延迟。
示例:电话通话(双方可同时说话和收听)、以太网通信
4 偶校验与奇校验
在标准ASCII码中,其最高位(b7
)用作奇偶校验位。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1
的个数必须是奇数,若非奇数,则在最高位b7
添1
;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7
添1。
5 停止位
停止位是按长度来算的。串行异步通信从计时开始,以单位时间为间隔(一个单位时间就是波特率的倒数),依次接受所规定的数据位和奇偶校验位,并拼装成一个字符的并行字节;此后应接收到规定长度的停止位“1”
。所以说,停止位都是“1”,1.5
是它的长度,即停止位的高电平保持1.5个
单位时间长度。一般来讲,停止位有1,1.5,2
个单位时间三种长度。
6 波特率
波特率就是每秒钟传输的数据位数。
波特率的单位是每秒比特数(bps
),常用的单位还有:每秒千比特数Kbps
,每秒兆比特数Mbps
。串口典型的传输波特率600bps
,1200bps
,2400bps
,4800bps
,9600bps
,19200bps
,38400bps
。
二、串口通讯软件设置要点
- 主机与从机:在通讯系统中起主要作用、发布主要命令的称为主机,接受命令的称为从机;
- 连续方式:指主机不需要发布命令,从机就能自动地向主机发送数据;
- 指令方式:指主机向从机发布命令,从机根据指令执行动作,并将结果“应答”给主机的模式;
//串口的操作
//1 open()
/**
O_RDWR 读写方式打开;
O_NOCTTY 不允许进程管理串口(不太理解,一般都选上);
O_NDELAY 非阻塞(默认为阻塞,打开后也可以使用fcntl()重新设置)
*/
fd = open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NDELAY);
//2 write()
n = write(fd, "linux", 5);
//n实际写入字节数;
//3 read()
res = read(fd,buf,len);
//res 读取的字节数;
//4 other
fcntl(fd, F_SETFL, FNDELAY); //非阻塞
fcntl(fd, F_SETFL, 0); // 阻塞
//5 close()
//close(fd);//串口配置
struct termios options; // 串口配置结构体
tcgetattr(fd,&options); //获取当前设置
bzero(&options,sizeof(options));
options.c_cflag |= B115200 | CLOCAL | CREAD; // 设置波特率,本地连接,接收使能
options.c_cflag &= ~CSIZE; //屏蔽数据位
options.c_cflag |= CS8; // 数据位为 8 ,CS7 for 7
options.c_cflag &= ~CSTOPB; // 一位停止位, 两位停止为 |= CSTOPB
options.c_cflag &= ~PARENB; // 无校验
//options.c_cflag |= PARENB; //有校验
//options.c_cflag &= ~PARODD // 偶校验
//options.c_cflag |= PARODD // 奇校验
options.c_cc[VTIME] = 0; // 等待时间,单位百毫秒 (读)。后有详细说明
options.c_cc[VMIN] = 0; // 最小字节数 (读)。后有详细说明
tcflush(fd, TCIOFLUSH); // TCIFLUSH刷清输入队列。//TCOFLUSH刷清输出队列。 //TCIOFLUSH刷清输入、输出队列。
tcsetattr(fd, TCSANOW, &options); // TCSANOW立即生效;
TCSADRAIN:Wait until everything has been transmitted;
TCSAFLUSH:Flush input and output buffers and make the change//VTIME 和 VMIN
//VTIME 定义要求等待的零到几百毫秒的值(通常是一个8位的unsigned char变量)。
//VMIN 定义了要求等待的最小字节数, 这个字节数可能是0。
//只有设置为阻塞时这两个参数才有效,仅针对于读操作。
参考
linux下的串口通信原理及编程实例