串口通信的概念与实现

article/2025/10/6 19:43:15
  • uart串口通信概念
  • 数据结构
  • termios作用与设置
  • 串口读写实现

UART串口通信概念

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作uart,是一种异步收发传输器,uart作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。

数据结构

起始位 :表示传输字符的开始

数据位 :数据位的个数可以设置为4,5,6,7,8,构成一个字符。

奇偶校验位: 数据位加上奇偶校验位后,逻辑“1”的数量为偶数则为偶校验。为奇数则为奇校验。在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位为1,这样就有3个逻辑高位。高位和低位不是真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

停止位:它是一帧数据的结束标志。用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

空闲位:没有数据传输时,为逻辑1

传输方向:数据从高位(msb)开始传输还是从低位(lsb)开始传输

这里写图片描述

termios作用与设置

函数描述了用于控制异步通信端口的通用终端接口。参见Linux API termios描述

引用头文件

#include "termios.h"

结构体:

struct termios {tcflag_t c_iflag;  /* 输入模式标志*/tcflag_t c_oflag;  /* 输出模式标志*/tcflag_t c_cflag;  /* 控制模式标志*/tcflag_t c_lflag;  /* 区域模式标志或本地模式标志或局部模式*/cc_t c_line;       /* 行控制line discipline */cc_t c_cc[NCCS];   /* 控制字符特性*/
};

c_iflag : 控制终端输入方式

参数参数说明
IGNBRK忽略BREAK键输入
BRKINT如果设置了IGNBRK,BREAK键输入将被忽略
IGNPAR忽略奇偶校验错误
PARMRK标识奇偶校验错误
INPCK允许输入奇偶校验
ISTRIP去除字符的第8个比特
INLCR将输入的NL(换行)转换成CR(回车)
IGNCR忽略输入的回车
ICRNL将输入的回车转化成换行(如果IGNCR未设置的情况下)
IUCLC将输入的大写字符转换成小写字符(非POSIX)
IXON允许输入时对XON/XOFF流进行控制
IXANY输入任何字符将重启停止的输出
IXOFF允许输入时对XON/XOFF流进行控制
IMAXBEL当输入队列满的时候开始响铃
IUTF9当输入是UTF8时,能够允许字符擦除在加工模式下正确执行

c_oflag:输出模式标志,控制终端输出方式

参数参数说明
OPOST处理后输出
OLCUC将输入的小写字符转换成大写字符(非POSIX)
ONLCR将输入的NL(换行)转换成CR(回车)及NL(换行)
OCRNL将输入的CR(回车)转换成NL(换行)
ONOCR第一行不输出回车符
ONLRET不输出回车符
OFILL发送填充字符以延迟终端输出
OFDEL以ASCII码的DEL作为填充字符,如果未设置该参数,填充字符为NUL
NLDLY换行输出延时,可以取NL0(不延迟)或NL1(延迟0.1s)
CRDLY回车延迟,取值范围为:CR0、CR1、CR2和 CR3
TABDLY水平制表符输出延迟,取值范围为:TAB0、TAB1、TAB2和TAB3
BSDLY空格输出延迟,可以取BS0或BS1
VTDLY垂直制表符输出延迟,可以取VT0或VT1
FFDLY换页延迟,可以取FF0或FF1

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

参数参数说明
CBAUD波特率(4+1位)(非POSIX)
CBAUDEX附加波特率(1位)(非POSIX)
CSIZE数据位长度,取值范围为CS5、CS6、CS7或CS8
CSTOPB设置两个停止位
CREAD使用接收器
PARENB使用奇偶校验
PARODD对输入使用奇偶校验,对输出使用偶校验
HUPCL关闭设备时挂起
CLOCAL忽略调制解调器线路状态
CRTSCTS使用RTS/CTS流控制

c_lflag:本地模式标志,控制终端编辑功能

参数参数说明
ISIG当输入INTR、QUIT、SUSP或DSUSP时,产生相应的信号
ICANON使用标准输入模式
XCASE在ICANON和XCASE同时设置的情况下,终端只使用大写。
ECHO显示输入字符
ECHOE如果ICANON同时设置,ERASE将删除输入的字符
ECHOK如果ICANON同时设置,KILL将删除当前行
ECHONL如果ICANON同时设置,即使ECHO没有设置依然显示换行符
ECHOPRT如果ECHO和ICANON同时设置,将删除打印出的字符(非POSIX)
TOSTOP向后台输出发送SIGTTOU信号

c_cc[NCCS]:控制字符,用于保存终端驱动程序中的特殊字符,如输入结束符等

NCCS参数说明
VINTRInterrupt字符
VEOL附加的End-of-file字符
VQUITQuit字符
VTIME非规范模式读取时的超时时间
VERASEErase字符
VSTOPStop字符
VKILLKill字符
VSTARTStart字符
VEOFEnd-of-file字符
VSUSPSuspend字符
VMIN非规范模式读取时的最小字符数

注意:控制符VTIME和VMIN之间有复杂的关系。VTIME定义要求等待的时间(百毫米,通常是unsigned
char变量),而VMIN定义了要求等待的最小字节数(相比之下,read函数的第三个参数指定了要求读的最大字节数)。
如果VTIME=0,VMIN=要求等待读取的最小字节数,read必须在读取了VMIN个字节的数据或者收到一个信号才会返回。
如果VTIME=时间量,VMIN=0,不管能否读取到数据,read也要等待VTIME的时间量。
如果VTIME=时间量,VMIN=要求等待读取的最小字节数,那么将从read读取第一个字节的数据时开始计时,并会在读取到VMIN个字节或者VTIME时间后返回。
如果VTIME=0,VMIN=0,不管能否读取到数据,read都会立即返回

tcsetattr函数用于设置终端的相关参数。

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); 

参数fd为打开的终端文件描述符
参数optional_actions用于控制修改起作用的时间,而结构体termios_p中保存了要修改的参数optional_actions可以取如下的值:

参数参数说明
TCSANOW不等数据传输完毕就立即改变属性。
TCSADRAIN等待所有数据传输结束才改变属性。
TCSAFLUSH清空输入输出缓冲区才改变属性。
返回值参数说明
EBADF非法的文件描述符。
EINTRtcsetattr函数调用被信号中断。
EINVAL参数optional_actions使用了非法值,或参数termios中使用了非法值。
ENCTTY非终端的文件描述符。

tcgetattr获取与fd终端关联的termios

int tcgetattr(int fd, struct termios *termios_p); 

tcsetattr重新设置与fd终端关联的termios

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); 

设置波特率

int cfsetispeed(struct termios *termios_p, speed_t speed); //输入波特率
int cfsetospeed(struct termios *termios_p, speed_t speed); //输出波特率

常见配置:
8位数据位、无校验位

c_cflag &= ~PARENB;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS8;

7位数据位、奇校验

c_cflag |= PARENB;
c_cflag |= PARODD;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7;

7位数据位、偶校验

c_cflag |= PARENB;
c_cflag &= ~PARODD;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7;

7位数据位、Space校验

c_cflag &= ~PARENB;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7

串口读写实现

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <termios.h>
#include <cerrno>
#include <cstdio>
#include <ctime>
#include <ctime>
#include <libgen.h>
#include <thread>
#include <cerrno>//串口设备路径
#define DEV_PATH "/dev/ttyS2"
typedef void (*SerialDataReport)(size_t len, uint8_t* data);struct SerialDevice{SerialDataReport dataReportFunc = nullptr;int fd = -1;bool readStop = false;
};static SerialDevice myDevice;/*** 设置波特率* @param fd 文件句柄* @return 设置结果 true / false*/
static int setSpeed(int fd){struct termios options{};tcgetattr(fd, &options);tcflush(fd, TCIOFLUSH);cfsetispeed(&options, B38400);cfsetospeed(&options, B38400);options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);options.c_oflag &= ~OPOST;int status = tcsetattr(fd, TCSANOW, &options);if(status != 0){return 0;}tcflush(fd, TCIOFLUSH);return 1;
}/*** 设置串口数据位,停止位和校验位* @param fd 串口设备文件描述符* @return 设置结果 true / false*/
static int setParity(int fd){struct termios options{};if(tcgetattr(fd, &options) != 0){return 0;}options.c_cflag &= ~CSIZE;options.c_cflag |= CS8;     //8bitoptions.c_cflag &= ~PARENB; //无校验位options.c_iflag &= ~INPCK;options.c_cflag &= ~CSTOPB; //stop 1bittcflush(fd, TCIFLUSH);options.c_cc[VTIME] = 150;options.c_cc[VMIN] = 0;if(tcsetattr(fd, TCSANOW, &options) != 0){return 0;}return 1;
}static void serialReading(){int  _select_ret;uint8_t _buf[256];struct timeval _dy_time{};fd_set _fd_set;int fd = myDevice.fd;if(fd < 0){return;}while(!myDevice.readStop){FD_ZERO(&_fd_set);FD_SET(fd, &_fd_set);_dy_time.tv_sec = 5;_dy_time.tv_usec = 0;memset(_buf, 0, 256);_select_ret = select(fd + 1, &_fd_set, nullptr, nullptr, &_dy_time);if(_select_ret <= 0){continue;}ssize_t _len = read(fd, _buf,256);if(_len > 0){if(myDevice.dataReportFunc){myDevice.dataReportFunc(_len, _buf);}}}
}static int startSerial(SerialDataReport report){int fd = open(DEV_PATH, O_RDWR);if(fd == -1){printf("open device [%s] failed: %s\n", DEV_PATH, strerror(errno));return 0;}if(!setSpeed(fd) || !setParity(fd)){return false;}myDevice.fd = fd;myDevice.dataReportFunc = report;myDevice.readStop = false;std::thread read_t(serialReading);read_t.detach();printf("Serial Device[%s] open successes", DEV_PATH);return 1;
}static void closeSerial(){myDevice.readStop = true;
}static int write(size_t len, uint8_t* data){if(myDevice.fd > 0){ssize_t _len = write(myDevice.fd, data, len);printf("write data len %zu", _len);return _len;}return -1;
}

http://chatgpt.dhexx.cn/article/1Afbm7eU.shtml

相关文章

java基于RXTXcomm的串口程序

准备工作 首先下载官方提供的jar包和.dll文件&#xff0c;dll文件有两个&#xff0c;一个是rxtxSerial&#xff0c;一个是rxtxParallel&#xff0c;分别表示串口和并口。因为我开发串口&#xff0c;所以把rxtxSerial.dll放到了jdk1.8.0_171/jre/bin和jre1.8.0_171/bin目录下&a…

51单片机串口多机通信的原理与编程实现

51单片机串口多机通信 需要用的的寄存器 (了解的可直接跳到下一节&#xff09; TMOD 定时器/计数器模式控制寄存器TCON 定时器控制寄存器SCON 串口控制寄存器PCON 电源控制位寄存器IE 中断中断使能寄存器 补充说明&#xff0c;TH1 预置值计算&#xff0c;中断源 波特率计算公式…

Java串口通信详解

序言 说到开源&#xff0c;恐怕很少有人不挑大指称赞。学生通过开源代码学到了知识&#xff0c;程序员通过开源类库获得了别人的成功经验及能够按时完成手头的工程&#xff0c;商家通过开源软件赚到了钱……&#xff0c;总之是皆大欢喜。然而开源软件或类库的首要缺点就是大多缺…

Java串口通信(RXTX)

这几天要用到串口通信,而我最会的Java,所以我就去学了一下怎么用Java进行串口通信 用的jar包是RXTX官网:http://rxtx.qbang.org/ 下载地址:http://fizzed.com/oss/rxtx-for-java 下载好Jar包后,首先需要配置,这里我用的Eclipse Window->Preferences->Java->Build …

十一、串口通信的基本原理与应用

通常用&#xff1a;SMOD 0&#xff0c;0xfd 利用51单片机的串行接口与上位机建立传输信道进行数据的收发。采用8位UART模式&#xff0c;即模式1&#xff0c;波特率为9600BPS。数据发送采用查询方式&#xff0c;数据接收采用中断方式。 系统上电初始化之后&#xff0c;单片机向…

【超简单的串口通信的工作原理】

下图是电脑收到单片机经过串口发送的信息&#xff0c; 那么电脑是如何与单片机进行串口通信的呢&#xff1f; 首先&#xff0c;任何一种通信都要包括硬件物理接口和软件通信协议。 串口通信物理接口如下图。单片机通过发送端将数据从左往右一位一位按顺序发送&#xff1b;且在…

串口通信基本原理

目录 串口通信连线&#xff1a; 串口通信时序&#xff1a; 起始位&#xff1a; 数据位&#xff1a; 校验位&#xff1a; 停止位&#xff1a; 总结&#xff1a; 串口通信特点&#xff1a; 基于串口的通讯接口&#xff1a; 串口通信连线&#xff1a; 任何通信都要有信息…

一篇短文让你彻底理解什么是串口通信

1 并行与串行通信 机器的通信方式有两种&#xff0c;分别是并行通信与串行通信。 并行通信&#xff1a;并行通信是指多比特数据同时通过并行线进行传送&#xff0c;这样数据传送速度大大提高&#xff0c;但并行传送的线路长度受到限制&#xff0c;因为长度增加&#xff0c;干…

Java RXTX 实现串口通信

目录 串口&#xff08;通信&#xff09;概述 串口调试助手 RXTX 下载与依赖 Java 开发实战 串口(通信)概述 1、串口通信是指串口按位&#xff08;bit&#xff09;发送和接收字节 2、串口通信可以在使用一根线发送数据的同时用另一根线接收数据 3、串口通信常用的协议包括…

串口通信原理

并行通信是指数据的各个位用多条数据线同时进行传输 优点&#xff1a;传输速度快 缺点&#xff1a;占用引脚资源多 串行通信是将数据分成一位一位的形式在一条传输线上逐个传输 优点&#xff1a;通信线路简单、占用引脚资源少 缺点&#xff1a;传输速度慢 同步通信&#xf…

串口通讯基本原理 【详细】

串口通信的基本知识 本文介绍了串口通讯的基本概念、数据格式、通讯方式、典型的串口通讯标准等内容。 串口通讯&#xff0c;RS232,RS485&#xff0c;停止位&#xff0c;奇校验&#xff0c;偶校验 1 串口通讯 串口通讯(Serial Communication)&#xff0c;是指外设和计算…

串口通信的基本原理详解

目录 串口通信 串口通信的两种基本方式 异步数据的数据发送过程 异步通信的数据接收过程 9针串口&#xff08;DB9&#xff09; TTL与RS232区别 TTL: RS232&#xff1a; 串口通信的数据格式 通讯方式 偶校验与奇校验 停止位 波特率&#xff08;波特率就是每秒钟传输…

串口通信原理详解

串口通信是一种串行异步通信&#xff0c;通信双方以字符帧作为数据传输单位&#xff0c;字符帧按位依次传输&#xff0c;每个位占固定的时间长度。两个字符帧之间的传输时间间隔可以是任意的&#xff0c;即传输完一个字符帧之后&#xff0c;可以间隔任意时间再传输下一个字符帧…

14_串口通信原理

通信方式的两种: 并行通讯: 传输原理:数据各个位同时传输。 优点:速度快 缺点:占用引脚资源多 串行通信: 传输原理:数据按位顺序传输。 优点:占用引脚资源少 缺点:速度相对较慢 串行通信: 按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输。 半双工:…

【Linux】基于美信串行解串器实现UART串口通信

文章目录 前言一、环境介绍二、硬件配置1. MAX967632. MAX96752F 三、串口通信协议1. 帧格式2. 同步帧3. 应答帧4. 包格式&#xff08;包由帧组成&#xff09; 四、内核模块实现 前言 车载项目中串行/解串器是十分常见的外设&#xff0c;目前常用的有两种标准&#xff1a;GMSL…

毫米波雷达图解算法原理(基于TI雷达)

毫米波雷达数据处理原理 前言基础bin文件解读 以下我们取1帧进行操作&#xff1a;对数据矩阵进行操作前的转换——开始计算结果矩阵一维FFT&#xff08;距离&#xff09;二维FFT&#xff08;速度&#xff09;角度维FFT &#xff08;假设利用结果已经获取目标&#xff09;对目标…

【阵列信号处理】DOA估计算法

DOA估计中的ESPRIT算法 ESPRIT算法时一种利用子空间旋转法估计DOA参数的方法&#xff0c;其算法的基本思想是将阵列在结构上分成两个完全一致的子列&#xff0c;两个子列相应阵元偏移的距离相等&#xff0c;也就是说阵列的阵元被分成一对对的形式&#xff0c;而且每一对之间具…

Hector SLAM 原理详解、算法解析

目录 1.原理详解 2.算法解析 1.原理详解 Hector整体算法很直接&#xff0c;就是将激光点与已有的地图“对齐”&#xff0c;即扫描匹配。扫描匹配就是使用当前帧与已经有的地图数据构建误差函数&#xff0c;使用高斯牛顿法得到最优解和偏差量。其工作是实现激光点到栅格地图的转…

MPU 6050姿态角度融合算法

1、介绍 1.1 姿态角&#xff08;Euler角&#xff09;pitch yaw roll介绍 飞行器的姿态角并不是指哪个角度&#xff0c;是三个角度的统称。它们是&#xff1a;俯仰、滚转、偏航。你可以想象是飞机围绕XYZ三个轴分别转动形成的夹角。 地面坐标系&#xff08;earth-surface inert…

linemod算法过程理解

一、提取模板 1、预处理 使用高斯模糊预处理将要作为模板的RGB图 2、模板梯度计算 分别计算RGB三个通道中每个像素点x和y方向的梯度&#xff08;sobel算子&#xff09;&#xff0c;取幅值最大的作为该像素的梯度&#xff0c;若梯度幅度值小于阈值&#xff0c;则被舍弃 3、梯度离…