Linux串口编程_termios
来源:互联网 发布:灯光设计软件 编辑:程序博客网 时间:2024/05/21 10:14
一、简介
1.1 Linux串口编程主要是设置structtermios结构体的个成员值。Termios是在POSIX规范中定义的标准接口,表示终端设备(包括虚拟终端丶串口等),串口是一种终端设备,一般通过终端编程接口对其进行配置和控制。
串口的配置最重要的是以下结构体定义中标明红色的条目,配置方法如下:
某几位清0:struct_name.flag&= ~(MASK1 | MASK 2….)
某几位置1:struc_name.flag|= (MASK1 | MASK2…)
1.2例如:设置115200的波特率:
Structtermios new_cfg;
New_cfg.c_cflag|= B115200
1.3本文写作目的旨在方便查阅串口设置结构体的组成,方便开发
二、结构体定义
#include<termios.h>
Struct termios{
Unsigned short c_iflag; //输入模式标志
Unsigned short c_oflag; //输出模式标志
Unsigned short c_cflag; //控制模式标志
Unsigned short c_lflag; //本地模式标志
Unsigned char c_line; //线路规程
Unsigned char c_cc[NCC]; //控制特性
Speed_t c_ispeed; //输入速度
Speed_t c_ospreed; //输出速度
}
2.1 输入模式标志(c_iflag:16bit)
INPCK
奇偶校验使能
IGNPAR
忽略奇偶校验错误
PARMRK
奇偶校验错误掩码
ISTRIP
裁剪掉第8比特
IXON
启动输出软件控制流
IXOF
启动输入软件控制流
IXANY
输入任意字符可以重新启动输入(默:起始字符)
IGNBRK
忽略输入终止条件
BRKINT
当检测到输入终止条件时发送SIGINT信号
INLCR
当收到NL(换行符)转换CR(回车符)
IGNCR
忽略收到的CR
ICRNL
当收到CR转换为NL
IUCLC
讲接收到的大写字符映射为小写字符
IMAXBEL
当输入队列满时响铃
2.2输出模式标志(c_oflag :16bit)
OPOST
启动输出处理功能,如果不设置,其他位忽略
OLCUC
将输出中的大写字符转换成小写字符
ONLCR
将输出中的换行符(‘\n’)转换成回车符(‘\r’)
ONOCR
如果当前列号为0,则不输出回车字符
OCRNL
将输出中的回车符转换成换行
ONLRET
不输出回车符
OFILL
发送填充字符以提供延时
OFDEL
如果设置该标志,则表示填充字符为DEL字符,否则为NUL
NLDLY
换行延时掩码
CRDLY
回车延时掩码
TABDLY
制表符延时掩码
BSDLY
水平退格符延时掩码
VTDLY
垂直退格符延时掩码
FFLDY
换页符延时掩码
2.3控制模式标志(c_cflag:16bit)
CBAUD
波特率的位掩码
B0
0波特率(放弃DTR)
…
…
B1800
1800的波特率
B2400
2400的波特率
B4800
4800的波特率
B9600
9600的波特率
B19200
19200的波特率
B38400
38400的波特率
B57600
57600的波特率
B115200
115200的波特率
EXTA
外部时钟率
EXTB
外部时钟率
CSIZE
数据位的位掩码
CS5
5个数据位
CS6
6个数据位
CS7
7个数据位
CS8
8个数据位
CSTOPB
2个停止位(不设置则是一个)
GREAD
接收使能
PARENB
PARODD
校验使能位
使用奇校验而不是偶校验
HUPCL
最后关闭时挂线(放弃DTR)
CLOCAL
本地连接(不改变端口所有者)
CRTSCTS
硬件流控
2.4本地模式标志(c_lflag:16bit)
ISIG
若收到信号字符(INTR,QUIT等)则会产生相应的信号
ICANON
启动规范模式
ECHO
启动本地回显功能
ECHOE
若设置ICANON则允许退格操作
ECHOK
若设置ICANON,则KILL字符会删除当前行
ECHONL
若设置ICANON,则允许回显换行符
ECHOCTL
若设置ECHO,则控制字符会显示成^x,其中x的ASCII码等于给相应的控制字符的ASCII码加上0x40.
ECHOPRT
若设置ICANON和IECHO,则删除字符和被删除的字符都会被显示
ECHOKE
若设置ICANON,则允许回显在ECHOE和ECHOPRT中设定的KILL字符
NOFLASH
在通常情况下,当接收到INTR,QUIT,SUSP控制字符时,会清空输入和输出队列。如果设置改标志,则所有的队列不会被清空
TOSTOP
若一个后台进程师徒向他的控制终端进行写操作,则系统向改后台进程的进程组发送SIGTTOU信号。该信号通常终止进程的执行
IEXTEN
启动输入处理功能
2.5控制特性(c_cc[])
VINTR
中断控制字符,对应的键位ctrl+c
VQUIT
退出操作符,对应的键为ctrl+z
VERASE
删除操作符,对应Backspace
VKILL
删除行符,对应的键为ctrl+u
VEOF
文件结尾符,对应的键为ctrl+d
VEOL
附加行结尾符,对应的键为carriage return
VEOL2
第二行结尾符,对应的键为line feed
VMIN
指定最少读取的字符数
VTIME
指定读取的每个字符之间的超时时间
三、串口配置基本流程
3.1保存串口配置
int tcgetattr(int fd, struct termios *termios_p);
3.2激活选项
CLOCAL和CREAD分别用于本地连接和接收使能,因此要先通过位掩码的方式激活这两个选项:
newtio.c_cflag |=CLOCAL |CREAD;
3.3设置波特率
波特率的设置不能直接通过掩码来设定,有提供设置函数:
cfsetispeed(&new_cfg,B115200);
cfsetospeed(&new_cfg,B115200);
3.4设置数据位
首先去掉数据位中的位掩码,再重新按要求设置:
New_cfg.c_cflag &=~CSIZE;
New_cfg.c_cflag |=CS8;
3.5设置奇偶校验位
New_cfg.c_cflag|=(PARODD | PARENB) //激活校验位使能
New_cfg.c_iflag //激活对输入数据的奇偶校验使能
3.6设置停止位
New_cfg.c_cflag &= ~CSTOPB //讲奇偶校验位设置一个比特
New_cfg.c_cflag |=CSTOPB //讲奇偶校验位设置两个比特
3.7设置最少字符和等待时间
New_cfg.c_cc[VTIME]=0;
New_cfg.c_cc[VMIN]=0;
3.8清除串口缓存
由于串口在重新设置之后,需要对当前的串口设备进行适当的处理,这时就可以调用在<termios.h>中声明的tcdrain(),tcflow(),tcflush()等函数来处理目前串口缓冲中的数据,格式如下:
int tcdrain(int fd) //使程序阻塞,直到输出缓冲区的数据全部发送完毕
int tcflow(int fd,int action) //用于暂停或者重新开始输出
int tcflush(int fd,int queue_selector) //用于清空输入输出缓冲区
3.9激活配置
tcsetattr(int fd,int option_action,conststruct terios *termrios_p)
Param :
Optional_options:
TCSCANOW:配置的修改立即生效
TCSADRAIN:配置的修改在所有写入fd的输出都传输完毕之后生效
TCSAFLUSH:所有已接受但未读入的输出都将在修改生效之前被丢弃
Return:
0:成功
-1:失败
3.10使用串口
串口配置完成后就可以像文件一样读写数据,使用read(),write()函数
四、串口配置实例(通用函数封装)
#include <stdio.h>#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include<stdbool.h>
#include <termios.h>
/*@ Fn uartOpen
@param uartDevicePath 设备文件
@param speed 波特率,默认115200
@param dataWidth 数据位宽,默认8bit
@param stopBit 停止位,true:2bit; false:1bit;
@return fd 打开文件描述符
*/
int uartOpen(char *uartDevicePath,int speed,int dataWidth,bool stopBit){
//Info
int fd=-1;
struct termios new_cfg,old_cfg;
printf("uart path=%s\n",uartDevicePath);
//open device
fd=open(uartDevicePath,O_RDWR | O_NOCTTY );
if(fd==-1)
printf("open failed!\n");
//preserve the old configuration
if(tcgetattr(fd,&old_cfg)!=0)
printf("Old config preserve failed!\n");
//set mode
new_cfg.c_cflag |=CLOCAL |CREAD;
//set baudrate
switch(speed){
case 1800:{
cfsetispeed(&new_cfg,B1800);
cfsetospeed(&new_cfg,B1800);
}break;
case 2400:{
cfsetispeed(&new_cfg,B2400);
cfsetospeed(&new_cfg,B2400);
}break;
case 4800:{
cfsetispeed(&new_cfg,B4800);
cfsetospeed(&new_cfg,B4800);
}break;
case 9600:{
cfsetispeed(&new_cfg,B9600);
cfsetospeed(&new_cfg,B9600);
}break;
case 19200:{
cfsetispeed(&new_cfg,B19200);
cfsetospeed(&new_cfg,B19200);
}break;
case 38400:{
cfsetispeed(&new_cfg,B38400);
cfsetospeed(&new_cfg,B38400);
}break;
case 57600:{
cfsetispeed(&new_cfg,B57600);
cfsetospeed(&new_cfg,B57600);
}break;
case 115200:{
cfsetispeed(&new_cfg,B115200);
cfsetospeed(&new_cfg,B115200);
}break;
default:{
cfsetispeed(&new_cfg,B115200);
cfsetospeed(&new_cfg,B115200);
}break;
}
//set size of data
new_cfg.c_cflag &=~CSIZE;
switch(dataWidth){
case 5:{
new_cfg.c_cflag |=CS5;
}break;
case 6:{
new_cfg.c_cflag |=CS6;
}break;
case 7:{
new_cfg.c_cflag |=CS7;
}break;
case 8:{
new_cfg.c_cflag |=CS8;
}break;
default :{
new_cfg.c_cflag |=CS8;
}break;
}
//set stopbit:true 2 stopbit,false 1 stopbit
if(stopBit)
new_cfg.c_cflag |=(CSTOPB);
else
new_cfg.c_cflag &=~(CSTOPB);
//set others
new_cfg.c_cc[VTIME]=0;
new_cfg.c_cc[VMIN]=0;
//start
if(-1==tcsetattr(fd,TCSANOW,&new_cfg))
printf("Uart setting failed!\n");
return fd;
}
void main()
{
int fd=uartOpen("/dev/ttyUSB0",115200,8,true);
while(1){
;
//handle here
}
}
- Linux串口编程_termios
- Linux 串口编程
- Linux下串口编程
- Linux串口编程分析
- Linux串口编程
- Linux串口编程
- Linux串口编程
- Linux串口编程
- Linux 下串口编程
- Linux串口编程
- Linux串口编程
- linux串口通信编程
- linux串口编程
- linux 串口编程
- linux串口编程
- linux串口编程
- linux 串口编程
- Linux串口编程分析
- Things to follow
- 这家伙去年赚了45万美金,可他却不会写一行代码。
- MySQL授权解决不能远程登录的问题
- Linux下编译安装PCRE库
- 自定义ViewGroup实现垂直滑屏
- Linux串口编程_termios
- Scramble String -- leetcode
- 欢迎使用CSDN-markdown编辑器
- 第十六章 内存管理(1)====高质量程序设计指南C/C++编程
- zoj 1648 Grandpa's Estate(判断线段是否相交(不考虑端点相交))
- ADB操作常见问题汇总
- 关于react native运用的简单总结
- mysql数据备份导入导出详解
- 编程之美8:链表常见面试笔试题集合