Linux环境下终端( 串口)接口应用

目录

概述

1 了解串口应用编程

1.1 认识 struct termios 结构体

1.1.1 认识c_iflag

1.1.2 认识c_oflag

1.1.3 认识 c_cflag 的配置参数

1.1.4 认识c_lflag

1.2 终端相关的函数库

2 编写串口应用接口

2.1 设置baud函数

2.2 设置停止位函数

2.3 设置奇偶校验函数

2.4 设置停止位函数

3 使用usr API接口

3.1 配置参数函数

3.2 初始化串口函数

3.3 关闭串口函数

4 参考资料


源代码下载地址: Linux环境下终端接口应用函数(serialport)资源-CSDN文库

概述

本文介绍linux环境下终端接口的相关知识,并介绍与其相关的数据结构的意义,重要参数的解释。还使用接口编写用户函数,以实现基于serial port的终端功能。

1 了解串口应用编程

在linux环境下,串口是终端的一种形式。对其操作,linux中已经定义了关于termios 的API 。在使用这些API之前,必须对其要有基本的认识。

1.1 认识 struct termios 结构体

其定义如下:

struct termios
{tcflag_t c_iflag; /* input mode flags */tcflag_t c_oflag; /* output mode flags */tcflag_t c_cflag; /* control mode flags */tcflag_t c_lflag; /* local mode flags */cc_t c_line;      /* line discipline */cc_t c_cc[NCCS]; /* control characters */speed_t c_ispeed; /* input speed */speed_t c_ospeed; /* output speed */
};

参数定义如下:

参数名称描述注释
c_iflag输入模式参数标志位
c_oflag输出模式参数标志位
c_cflag控制模式参数标志位
c_lflag本地模式参数标志位
c_line终端的行规程
c_cc[NCCS]终端的特殊字符
c_ispeed配置输入波特率参数
c_ospeed配置输出波特率参数

1.1.1 认识c_iflag

参数定义描述
IGNBRK忽略输入终止条件
BRKINT当检测到输入终止条件时发送 SIGINT 信号
IGNPAR忽略帧错误和奇偶校验错误
PARMRK对奇偶校验错误做出标记
INPCK对接收到的数据执行奇偶校验
ISTRIP将所有接收到的数据裁剪为 7 比特位、也就是去除第八位
INLCR将接收到的 NL(换行符)转换为 CR(回车符)
IGNCR忽略接收到的 CR(回车符)
ICRNL将接收到的 CR(回车符)转换为 NL(换行符)
IUCLC将接收到的大写字符映射为小写字符
IXON启动输出软件流控
IXOFF启动输入软件流控

1.1.2 认识c_oflag

参数定义描述
IGNBRK忽略输入终止条件
OPOST启用输出处理功能,如果不设置该标志则其他标志都被忽略
OLCUC将输出字符中的大写字符转换成小写字符
ONLCR将输出中的换行符(NL '\n')转换成回车符(CR '\r')
OCRNL将输出中的回车符(CR '\r')转换成换行符(NL '\n')
ONOCR在第 0 列不输出回车符(CR)
ONLRET不输出回车符
OFILL发送填充字符以提供延时
OFDEL如果设置该标志,则表示填充字符为 DEL 字符,否则为 NULL 字符

1.1.3 认识 c_cflag 

含义: 控制模式标志,指定终端硬件控制信息

参数定义描述
CBAUD波特率(4+1位)(非POSIX)
CBAUDEX附加波特率(1位)(非POSIX)
CSIZE字符长度,取值范围为CS5、CS6、CS7或CS8
CSTOPB2 个停止位,如果不设置该标志则默认是一个停止位
CREAD使用接收器
PARENB使用奇偶校验
PARODD对输入使用奇偶校验,对输出使用偶校验
HUPCL关闭设备时挂起
CLOCAL忽略调制解调器线路状态
CRTSCTS使用RTS/CTS流控制

CBAUD 参数定义如下

参数定义描述
CBAUD波特率的位掩码
B24002400 波特率
B96009600 波特率
B1920019200 波特率
B3840038400波特率
B5760057600波特率
B115200115200波特率
....其他波特率定义参看:termios.h

CSIZE参数定义如下

参数定义描述
CS55 个数据位
CS66 个数据位
CS77 个数据位
CS88个数据位

1.1.4 认识c_lflag

参数定义描述
ISIG若收到信号字符(INTR、 QUIT 等),则会产生相应的信号
ICANON启用规范模式
ECHO启用输入字符的本地回显功能。当我们在终端输入字符的时候,字符 会显示出来,这就是回显功能
ECHOE若设置 ICANON,则允许退格操作
ECHOK若设置 ICANON,则 KILL 字符会删除当前行
ECHONL若设置 ICANON,则允许回显换行符
ECHOCTL若设置 ECHO,则控制字符(制表符、换行符等)会显示成“^X”, 其中 X 的 ASCII 码等于给相应控制字符的 ASCII 码加上 0x40。例如, 退格字符(0x08)会显示为“^H”('H'的 ASCII 码为 0x48)
ECHOPRT若设置 ICANON 和 IECHO,则删除字符(退格符等)和被删除的字 符都会被显示
ECHOKE若设置 ICANON,则允许回显在 ECHOE 和 ECHOPRT 中设定的 KILL 字符
NOFLSH在通常情况下,当接收到 INTR、 QUIT 和 SUSP 控制字符时,会清空 输入和输出队列。如果设置该标志,则所有的队列不会被清空
TOSTOP若一个后台进程试图向它的控制终端进行写操作,则系统向该后台进 程的进程组发送 SIGTTOU 信号。该信号通常终止进程的执行
IEXTEN启用输入处理功能

1.2 终端相关的函数库

使用串口终端,必须包含下面两个图文件

 #include <termios.h>#include <unistd.h>

其提供的函数接口如下:

函数名功能介绍
tcgetattr获取与终端相关的参数取得终端介质(fd)初始值,并把其值 赋给temios_p;函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。
tcsetattr配置与终端相关的参数设置与终端相关的参数 (除非需要底层支持却无法满足),使用 termios_p 引用的 termios 结构。 optional_actions (tcsetattr函数的第二个参数)指定了什么时候改变会起作用: TCSANOW:改变立即发生 TCSADRAIN:改变在所有写入 fd 的输出都被传输后生效。这个函数应当用于修改影响输出的参数时使用。(当前输出完成时将值改变) TCSAFLUSH :改变在所有写入 fd 引用的对象的输出都被传输后生效,所有已接受但未读入的输入都在改变发生前丢弃(同TCSADRAIN,但会舍弃当前所有值)。
tcsendbreak在一个指定的时间区内发送连续的0位流传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义
tcdrain等待所有输出都被发送等待直到所有写入 fd 引用的对象的输出都被传输
tcflush清除输入缓冲区或输出缓冲区ueue_selector 的值: TCIFLUSH :刷新收到的数据但是不读 TCOFLUSH :刷新写入的数据但是不传送 TCIOFLUSH :同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送
tcflow对输入和输出流控制进行控制挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值:
cfmakeraw设置终端设置为原始模式(raw data )TCOOFF :挂起输出 TCOON :重新开始被挂起的输出 TCIOFF :发送一个 STOP 字符,停止终端设备向系统传送数据 TCION :发送一个 START 字符,使终端设备向系统传输数据 打开一个终端设备时的默认设置是输入和输出都没有挂起。
cfgetispeed返回存储在 TermiosPointer 参数指向的 termios 结构中的输入波特率
cfgetospeed返回存储在 TermiosPointer 参数所指向的 termios 结构中的输出波特率
cfsetispeed将存储在 TermiosPointer 参数指向的 termios 结构中的输入波特率设置为 Speed 参数指定的值设置 termios 结构中,输入和输出波特率的值。新值不会马上生效,直到成功调用了 tcsetattr() 函数。
cfsetospeed存储在 TermiosPointer 参数指向的 termios 结构中的输出波特率设置为 Speed 参数指定的值设置 termios 结构中,输入和输出波特率的值。新值不会马上生效,直到成功调用了 tcsetattr() 函数。

 函数原型声明如下:

int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);
int tcsendbreak(int fd, int duration);
int tcdrain(int fd);
int tcflush(int fd, int queue_selector);
int tcflow(int fd, int action);
void cfmakeraw(struct termios *termios_p);
speed_t cfgetispeed(const struct termios *termios_p);
speed_t cfgetospeed(const struct termios *termios_p);
int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);

2 编写串口应用接口

2.1 设置baud函数

static void set_baudrate (unsigned int baudrate)
{speed_t speed;speed = baudrate_to_Bxx (baudrate);  /* set baudrate */cfsetispeed(&termios_new, speed);    // set input speedcfsetospeed(&termios_new, speed);    // set output speed
}

使用cfsetispeed()设置波特率时,必须要要把其转换为 termios.h定义的类型,本例中使用baudrate_to_Bxx()函数实现这个功能。在 termios.h中定义的baud类型:

static speed_t baudrate_to_Bxx (unsigned int baudrate)
{switch (baudrate) {case 1200:return (B1200);case 2400:return (B2400);case 9600:return (B9600);case 19200:return (B19200);case 38400:return (B38400);case 57600:return (B57600);case 115200:return (B115200);default:return (B9600);}
}

2.2 设置停止位函数

static void set_stopbit (const char *stopbit)
{if (0 == strcmp (stopbit, "1")) {termios_new.c_cflag &= ~CSTOPB;    /* 1 stop bit */}else if (0 == strcmp (stopbit, "1.5")) {termios_new.c_cflag &= ~CSTOPB;     /* 1.5 stop bits */}else if (0 == strcmp (stopbit, "2")) {termios_new.c_cflag |= CSTOPB;       /* 2 stop bits */}else {termios_new.c_cflag &= ~CSTOPB;     /* 1 stop bit */}
}

2.3 设置奇偶校验函数

static void set_parity (char parity)
{switch (parity) {case 'N':                  /* no parity check */termios_new.c_cflag &= ~PARENB;break;case 'E':                  /* even */termios_new.c_cflag |= PARENB;termios_new.c_cflag &= ~PARODD;break;case 'O':                  /* odd */termios_new.c_cflag |= PARENB;termios_new.c_cflag |= ~PARODD;break;default:                   /* no parity check */termios_new.c_cflag &= ~PARENB;break;}
}

2.4 设置停止位函数

static void set_data_bit (unsigned int databit)
{termios_new.c_cflag &= ~CSIZE;switch (databit) {default:case 8:termios_new.c_cflag |= CS8;break;case 7:termios_new.c_cflag |= CS7;break;case 6:termios_new.c_cflag |= CS6;break;case 5:termios_new.c_cflag |= CS5;break;}
}

3 使用usr API接口

3.1 配置参数函数

编写一个函数,初始化串口参数,详细代码如下,其操作步骤:

step-1: 清空termios_new

step-2: 初始化termios_new数据结构

step-3: 填充用户参数

step-4: 调用tcsetattr使参数生效

static unsigned int set_portattr ( unsigned int baudrate,  // 2400 4800 9600 .. 115200unsigned int databit,   // 5, 6, 7, 8const char *stopbit,    //  "1", "1.5", "2"char parity)            // N(o), O(dd), E(ven)
{bzero(&termios_new, sizeof (termios_new));cfmakeraw (&termios_new);set_baudrate (baudrate);termios_new.c_cflag |= CLOCAL | CREAD;   /* | CRTSCTS */set_data_bit (databit);set_parity (parity);set_stopbit (stopbit);termios_new.c_cc[VTIME] = 1;            /* unit: 1/10 second. */termios_new.c_cc[VMIN]  = 255;          /* minimal characters for reading */return (tcsetattr (fd, TCSANOW, &termios_new));
}

3.2 初始化串口函数

在初始化函数中,其操作步骤如下:

step-1: 打开串口设备

step-2: 获取旧的终端参数,并将其保存在termios_old中

step-3: 调用set_portattr配置参数

int usr_serial_open( char *port, unsigned int baudrate, unsigned int databit, const char *stopbit, char parity)
{int err;fd = open (port, O_RDWR | O_NOCTTY | O_NDELAY);if (-1 == fd) {fprintf(stderr, "cannot open port %s\n", port);return (-1);}tcgetattr (fd, &termios_old);       /* save the form termios value */err = set_portattr (baudrate, databit, stopbit, parity);if ( err ) {fprintf ( stderr, "\nport %s cannot set baudrate at %d\n",port, baudrate);}return fd;
}

3.3 关闭串口函数

关闭串口函数,主要做如下事情:

step-1: 恢复termios_old参数

step-2: 关闭fd对应的端口

void usr_serial_close( void )
{/* flush output data before close and restore old attribute */tcsetattr(fd, TCSADRAIN, &termios_old);close(fd);
}

4 参考资料

《Linux/Unix系统编程手册(下册)》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722967.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot约定大于配置

什么是约定大于配置 "约定大于配置"&#xff08;Convention Over Configuration&#xff09;是一种理念&#xff0c;旨在通过默认约定和规则来减少开发人员需要做的配置工作。在Spring Boot框架中&#xff0c;这一原则得到了充分应用&#xff0c;帮助开发者更快地构…

Blender和3ds Max哪个会是行业未来?

Blender和3ds Max都是很强大的三维建模和渲染软件&#xff0c;各有各的好处。选择哪个软件更好&#xff0c;要看你的需求、预算、技术水平以及行业趋势等因素。 Blender最大的优点是免费且开源&#xff0c;这对预算有限的个人和小团队来说很有吸引力。它有很多建模工具和功能&…

在电脑桌面打开任意应用程序的快捷键

首先为某个程序&#xff08;比如谷歌浏览器&#xff09;创建一个快捷方式&#xff0c; 其次右键快捷方式&#xff0c;找到属性一栏 单击快捷键三个字右边的方框&#xff08;里面有一个“无”&#xff09;&#xff0c;然后按下你所需要设置的快捷键

【强化学习的数学原理-赵世钰】课程笔记(七)时序差分方法

一.内容概述 第五节课蒙特卡洛&#xff08;Mento Carlo&#xff09;方法是全课程中第一次介绍 model-free 的方法&#xff0c;本节课的 Temporal-difference learning&#xff08;TD learning&#xff09;是我们要介绍的第二种 model-free 的方法。基于蒙特卡洛&#xff08;Me…

【数据结构高阶】并查集

目录 一、什么是并查集 二、并查集的原理 三、并查集的作用 四、并查集的代码实现 一、什么是并查集 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个 单元素集合&#xff0c;然后按一定的规律将归于同一组元…

【LeetCode每日一题】【BFS模版与例题】【二维数组】1293. 网格中的最短路径

BFS基本模版与案例可以参考&#xff1a; 【LeetCode每日一题】【BFS模版与例题】863.二叉树中所有距离为 K 的结点 【LeetCode每日一题】【BFS模版与例题】【二维数组】130被围绕的区域 && 994 腐烂的橘子 思路&#xff1a; 特殊情况&#xff1a; 最短的路径是向下再向…

【电路笔记】-双极晶体管

双极晶体管 文章目录 双极晶体管1、概述2、双极晶体管结构3、双极晶体管配置3.1 共基极 (CB) 配置3.2 共发射极 (CE) 配置3.3 共集极 (CC) 配置4、总结1、概述 双极结型晶体管是一种可用于开关或放大的半导体器件。 与半导体二极管不同,半导体二极管由两片半导体材料组成,形…

【Java基础面试题2】

目录 前言 1.11 int和Integer有什么区别&#xff0c;二者在做运算时会得到什么结果&#xff1f; 1.12 说一说你对面向对象的理解 1.13 面向对象的三大特征是什么&#xff1f; 1.14 封装的目的是什么&#xff0c;为什么要有封装&#xff1f; 1.15 说一说你对多态的理解 1…

ElasticSearch|ES|架构介绍|原理浅析

架构介绍 节点 (Nodes): Elasticsearch 集群由多个节点组成&#xff0c;每个节点是一个独立运行的 Elasticsearch 实例。节点之间通过内部通信协议相互协作。 Master Node: 主节点负责管理集群范围的操作&#xff0c;例如创建或删除索引、分配和重新分配分片、维护集群状态等。…

StarUML6.0.1使用

1. 简介 作为一个软件开发人员&#xff0c;平时免不了做一定的软件设计&#xff0c;标准做法就是采用UML来设计&#xff1a; 讨论功能流程时采用时序图、活动图来表达&#xff1b;做业务功能架构时采用组件图来表达&#xff1b;做系统部署架构时采用部署图来表达&#xff1b;做…

因implements Interface书写顺序导致的Dubbo翻车实录

今天迁移Dubbo的代码&#xff0c;突然有个Service死活都找不到。 调用端报错&#xff1a; No provider available for the service org.ccframe.subsys.core.service.ITenantSearchService from registry 127.0.0.1:2181 on the consumer 192.168.1.88 using the dubbo version…

HTTPS如何保证数据传输的安全性 以及CA签发证书验签

暴力输出&#xff1a; 越看会越深入&#xff0c;睡前难以想通&#xff0c;后深入研究。得之。 有问题 请留言。 ----------追求内心的富足与平和。日行一善。 亓苏姑娘

Ollama--本地大语言模型LLM运行专家

文章目录 1、问题提出2、解决方案3、Ollama介绍3.1、Ollama的核心功能3.2、Ollama的独特之处 4、Ollama安装与使用4.1、Ollama的安装 5、使用Docker6、模型库和自定义模型7、应用场景展望8、结语 1、问题提出 使用chatgpt之类的闭源大语言模型时&#xff0c;我们与ai沟通的数据…

I.MX6ULL_Linux_驱动篇(54)linux 块设备驱动

前面我们都是在学习字符设备驱动&#xff0c;本章我们来学习一下块设备驱动框架&#xff0c;块设备驱动是Linux 三大驱动类型之一。块设备驱动要远比字符设备驱动复杂得多&#xff0c;不同类型的存储设备又对应不同的驱动子系统&#xff0c;本章我们重点学习一下块设备相关驱动…

【控制台警告】npm WARN EBADENGINE Unsupported engine

今天用webpack下载几个loader依赖&#xff0c;爆出了三个警告&#xff0c;大概的意思就是本地安装的node和npm的版本不是很匹配&#xff1f; 我的解决思路是&#xff1a; 先检查node和npm版本 然后去官网查找版本的对应 靠&#xff0c;官网404 Node.js (nodejs.org) 就找到…

操作系统:初识操作系统

目录 1.冯诺依曼体系结构 2.操作系统 2.1什么是操作系统 2.2为什么需要操作系统 2.3怎么实现操作系统 1.冯诺依曼体系结构 对于上图&#xff1a; 输入设备完成的是写入工作&#xff0c;输出设备完成输出工作&#xff0c;这两部分包含磁盘这类的外存。 存储器一般指的是内存…

Win UI3开发笔记(四)设置主题续2

本机深色主题下设置的背景颜色可以作用于整个对话框&#xff0c;本机浅色模式下设置的背景颜色只作用与下边的部分。 如果本机选深色&#xff0c;程序选浅色&#xff0c;设置为light只对上部分管用&#xff0c;下部分不管用。如图&#xff0c;左边那个hello按钮要看不见了。。…

协同办公大战再起,钉钉、飞书“决战”AI

对众多职场人来说&#xff0c;相信其对于钉钉、飞书、企业微信这些名字一定不会感到陌生&#xff0c;因为在当下的工作过程中&#xff0c;无论是考勤打卡&#xff0c;还是团队沟通协作&#xff0c;都离不开这些办公软件。而这些协同办公软件的出现&#xff0c;也为职场人的工作…

django学习记录06-Ajax的初识

Ajax请求 1.1Ajax请求与get、post请求的区别 form请求&#xff1a;浏览器向网站发送请求时&#xff0c;url和表单的形式提交 GET请求&#xff1a;url方式获取数据POST请求&#xff1a;以表单的形式提交数据 特点: 一次完整的GET或POST请求&#xff0c;会进行一次页面刷新 基于…

183基于matlab的非线性调频模态分解(VNCMD)

基于matlab的非线性调频模态分解(VNCMD)&#xff0c;一种基于变分方法的信号分解技术&#xff0c;它将信号分解为多个模式。能够处理非线性调频信号&#xff0c;且对噪声具有较好的鲁棒性。VNCMD的基本原理是通过最小化信号与模式之间的差异来实现信号的分解。程序已调通&#…