# UART ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 功能概述 通用异步收发器(UART)是一种用于异步串行通信的硬件外设,负责处理通信中的时序控制和数据组帧,常配合RS-232、RS-422、RS-485等接口标准使用。UART实现简单、成本低廉,广泛用于不同设备之间的全双工或半双工数据交换。 每个UART控制器均可独立配置波特率、数据位长度、位顺序、停止位数量、奇偶校验位等参数。各制造商生产的常规UART控制器相互兼容,可与任何支持UART的设备通信。 UART通信由两个UART直接对接完成:发送UART将来自CPU等控制设备的并行数据转换为串行数据发送出去,接收UART收到后再转换回并行数据,交给接收设备使用。两个UART之间只需两根线即可传输数据,数据从发送UART的Tx引脚流向接收UART的Rx引脚: ```{image} images/image_NHmebxYg7or7XGx165bctBlenle.webp :width: 511px :height: 261px :align: center ``` UART异步传输数据,收发双方之间没有时钟信号来对齐发送端的位输出与接收端的位采样。发送UART不使用时钟信号,而是在数据前后添加起始位和停止位来标示一帧的边界:起始位标记数据包的开始,停止位标记结束,接收UART据此判断何时开始读取数据。 接收UART检测到起始位后,便按约定的频率逐位读取数据,该频率称为波特率。波特率衡量数据传输速度,以每秒位数(bps)表示。收发双方必须使用大致相同的波特率,误差不能超过约10%,否则位时序偏差过大,会导致数据接收错误。 此外,收发双方还必须配置相同的数据包结构。 ## 工作原理 ```{image} images/image_VqcPbS74uofEGDxPtCMcMwQ1nnh.webp :width: 768px :height: 331px :align: center ``` 发送流程从数据总线开始:CPU、内存或微控制器等设备通过数据总线将并行数据送入发送UART。发送UART取得并行数据后,为其添加起始位、奇偶校验位和停止位,组成数据包,然后在Tx引脚上逐位串行输出。接收UART在Rx引脚上逐位读入数据包,去掉起始位、奇偶校验位和停止位,将数据还原为并行形式,最后通过接收端的数据总线交给接收设备。 ## 框图 UART由发送器和接收器两部分组成,框图如下所示。发送器包含发送保持寄存器、移位寄存器和控制逻辑三个模块;接收器同样包含接收保持寄存器、移位寄存器和控制逻辑。两部分共用一个波特率发生器,在发送或接收数据时由它产生相应的时钟速率。 发送器中的保持寄存器暂存待发送的数据字节;发送器和接收器中的移位寄存器逐位移入或移出数据,直到完成一个字节的发送或接收;读/写控制逻辑负责控制读写时机。 波特率发生器可生成110 bps至230,400 bps范围内的速率。通常,微控制器使用的波特率为9600 bps至115200 bps。 ```{image} images/image_EDkjbIhwFoFqyxxYgLycNS5rnDb.webp :width: 650px :height: 477px :align: center ``` ## 帧结构 UART以数据包为单位传输数据。每个数据包包含1个起始位、5至9个数据位(取决于具体UART)、1个可选的奇偶校验位以及1或2个停止位: ```{image} images/image_OafXbFdwNogxMlxRjylcDdNcnnd.webp :width: 610px :height: 175px :align: center ``` - 空闲状态:高电平,表示当前线路上无数据传送。 - 起始位:传输线在空闲时保持高电平。开始传输时,发送UART将传输线拉低并保持一个时钟周期;接收UART检测到这个由高到低的跳变后,便开始按波特率逐位读取数据帧。 - 数据位:数据位承载实际传输的数据。若使用奇偶校验位,数据位长度可为5至8位;若不使用,最多可为9位。大多数情况下,数据从最低有效位开始发送。 - 奇偶校验位:奇偶校验位用于让接收UART检查数据在传输过程中是否发生改变——数据位可能因电磁干扰、波特率不匹配或长距离传输而出错。接收UART读取数据帧后,统计其中值为1的位数:偶校验时(校验位为0),值为1的位总数应为偶数;奇校验时(校验位为1),总数应为奇数。校验结果与数据相符,说明传输无误;若校验位为0而总数为奇数,或校验位为1而总数为偶数,则说明数据帧中有位发生了改变。 - 停止位:停止位位于数据包末尾,可为1位或2位,常用1位。发送UART将数据线拉回高电平并保持,表示一帧传输结束。 ## 波特率 波特率指线路中信号调制的频率,单位为bps或b/s(位每秒)。时钟信号以固定频率不断振荡,每个时钟周期发送一位数据。 ```{image} images/image_AjR1b4lm7oc02fxG62Tc6AqTnad.webp :width: 155px :height: 307px :align: center ``` UART通信双方须使用相同的波特率。由于UART是异步通信,通信双方之间没有时钟线连接,各自根据内部时钟调制出理论上相等的波特率。受硬件误差影响,实际波特率往往无法严格等于理论值,因此要求双方波特率误差不超过10%,否则己方会读取到乱码数据。 ## 硬件流控 流控,即流量控制。 任何通信协议的双方,都会分配存储空间有限的缓冲区,用来接收对方发送的数据。一旦对方发送数据过快,而己方处理速度较慢,就可能出现缓冲区满无法处理、甚至丢数据的严重情况。 因此需要流量控制机制:己方无法接收更多数据时,通知发送方暂停发送;等到可以继续接收时,再通知发送方恢复发送。 ```{image} images/image_M7sAbLK61oTW8CxKUiTctwicn8c.webp :width: 637px :height: 519px :align: center ``` 上图为带硬件流控引脚的UART接口连接图,相比前面的连接方式多了RTS和CTS两个引脚,此二者是UART硬件接口的常规功能引脚。 RTS:输出功能,连接对方的CTS。当己方RTS拉高时,通知对方UART暂停发送数据;当RTS恢复低电平时,通知对方继续发送数据。 CTS:输入功能,连接对方的RTS。当己方CTS检测到高电平时暂停发送数据;当检测到低电平时继续发送数据。 ## FIFO FIFO(First-In, First-Out)是一种基本的数据结构,其核心思想是先进入的数据先出去(先进先出)。FIFO可以在硬件和软件中实现,且有同步和异步之分。 ```{image} images/image_RfXjbluy4oXo81xTXiQcnVFXnsb.webp :width: 1200px :height: 785px :align: center ``` ### 软件FIFO - **定义**:在软件中使用编程数据结构(如数组、链表)实现的FIFO。 - **应用**:常见于操作系统中的任务调度、网络中的数据包处理或任何需要队列的场合。 - **操作**:主要操作包括入队(添加到队列尾部)和出队(从队列头部移除)。 - **优点**:灵活,可以灵活调整大小或实现优先级排队等高级功能。 - **缺点**:由于在软件中实现,速度可能不如硬件FIFO。 **实现:** 软件FIFO最常见的实现是环形缓冲区(ring buffer)。 与线性缓冲区相比,环形缓冲区不需要频繁分配内存,内存可以反复使用,能以更少的内存块完成更多工作,且内存管理更方便、更安全,一般应用于需要频繁读写数据缓冲区的场合。 ```{image} images/image_YOaAbfstXo9F8DxnAOycEwArnNc.webp :width: 717px :height: 454px :align: center ``` 环形缓冲区并不是指物理意义上首尾相连成"环"的缓冲区,而是逻辑意义上的环。因为内存空间是线性结构,所以环形缓冲区实际上仍是一段有长度的内存空间,是一个具备先进先出功能的缓冲区,并支持通信进程对该缓冲区的互斥访问。 **实现原理:** 环形缓冲区的长度是固定的。使用时不需要清除已有数据,只需调整head、tail和write pointer的指针位置。write pointer最初指向head位置(缓冲区开头),数据从write pointer处开始存储;每存储一个数据,write pointer向后移动一个位置。当write pointer到达tail位置时,将重新指向head位置(回卷处理),并覆盖原有数据,直到数据存储完毕。环形缓冲区的好处是减少内存分配从而降低系统开销,减少内存碎片数量,有利于程序长期稳定运行。 ```{image} images/image_JNgubuWeToiR2nxxb9uc3cain3d.webp :width: 610px :height: 175px :align: center ``` 一般构建一个环形缓冲区需要一段连续的内存空间以及4个指针: - **head指针:** 指向内存空间中的首地址; - **tail指针:** 指向内存空间的尾地址; - **read pointer:** 指向内存空间存储数据的起始位置(读指针); - **write pointer:** 指向内存空间存储数据的结尾位置(写指针)。 内存申请和指针定义完毕后,环形缓冲区的使用规则如下: 1. 该段内存空间的长度是Len = tail - head; 2. write pointer是写数据的起始位置,每存入N个数据后向后移动N个单位长度的偏移。当有addlen长度的数据要存入环形缓冲区时,若addlen + write pointer > tail,write pointer先存入len1 = tail - write pointer个数据长度,然后回到head位置,将剩下的len2 = addlen - len1个数据从head开始存储,并覆盖原来的数据内容; 3. read pointer是读数据的起始位置,每读取N个数据后向后移动N个单位长度的偏移。当要从环形缓冲区读取addlen长度的数据时,若addlen + read pointer > tail,read pointer先读取len1 = tail - read pointer个数据长度,然后回到head位置,将剩下的len2 = addlen - len1个数据从head开始读取完毕。 ### 硬件FIFO - **定义**:在硬件中,特别是在数字电路中实现的FIFO。 - **应用**:常见于通信接口(如UART、SPI等)中,用于数据缓冲。 - **实现**:通常使用寄存器阵列或双口RAM实现,具有读指针和写指针。 - **优点**:速度快,可以与其他硬件模块并行工作,提供高效的数据流。 - **缺点**:大小固定,不如软件FIFO灵活。 ### 同步FIFO - **定义**:同步FIFO的读和写操作都在相同的时钟下进行。 - **工作原理**:使用一个共同的时钟信号控制数据的读写。当有新的数据可写入时,写指针移动;当有数据可读时,读指针移动。 - **应用**:常见于同一时钟域中的数据流缓冲。 ```{image} images/image_H8N2bPoPOoBts7xbNCicLPuDnxh.webp :width: 716px :height: 291px :align: center ``` **写入操作:** FIFO根据w_en信号在每个时钟沿写入wr_data,直到FIFO满。每写入一个数据,写指针递增。 **读取操作:** FIFO根据rd_en信号在每个时钟沿读出数据,直到FIFO空。每读取一个数据,读指针递增。 FIFO内部通过对写请求、读请求计数产生读、写指针,读写指针即为存储器的读、写地址。写指针指向下一个要写入的地址,读指针指向下一个要读取的地址,写请求使写指针递增,读请求使读指针递增。 FIFO模块输出empty和full信号指示其状态:fifo_full表示FIFO内空间已满,不能再写入数据;fifo_empty表示FIFO内没有可供读取的有效数据。 **同步FIFO空满信号的产生:** 复位时FIFO读、写指针都归零。此时fifo_empty拉高,只能写不能读;一旦有数据写入,fifo_empty被拉低,允许读取数据。当FIFO的写指针指向fifo_depth - 1时,再进行一次写操作会使写指针归零(此时无读操作),并拉高fifo_full。 读写指针相等时,FIFO要么空要么满,因此需要区分这两种情况。 1. FIFO满信号产生 2. FIFO满状态由写操作触发:若一次写操作使读、写指针在下个时钟相等,则FIFO为满。更通俗的解释是"**写操作让写指针追上了读指针,即写指针套了读指针一圈(跑步的角度)**"。 3. FIFO空信号产生 4. FIFO空状态由读操作触发:若一次读操作使读、写指针在下个时钟相等,则FIFO为空。更通俗的解释是"**读操作让读指针追上了写指针**"。 ### 异步FIFO - **定义**:异步FIFO的读和写操作在不同的时钟域中进行。 - **工作原理**:使用两个独立的时钟,一个用于写操作,另一个用于读操作。这需要特殊的设计,以确保跨时钟域的数据完整性和同步。 - **应用**:用于两个有不同操作频率或来自不同源的时钟域之间的数据传输。 ## DMA DMA(Direct Memory Access,直接内存访问)技术允许外部设备(如硬盘、音频接口、网络适配器等)绕过中央处理器(CPU),直接与系统内存交换数据。这种机制可以显著提高数据传输效率,因为设备传输数据时不占用CPU时间。 **特点:** DMA和CPU之间并不是并行关系:因为主存只有一个,CPU和DMA无法同时访问主存,只能交替访问。DMA之所以效率高、速度快,是因为省去了现场保护和现场恢复。 DMA传输本身并不会中断程序,但它会占用系统资源,比如IO或RAM。一旦CPU需要访问相同的IO或RAM,就需要长时间等待,直到DMA传输完毕、释放资源。从软件角度来看,这和中断程序非常相似,但本质截然不同:CPU一直在工作,从未发生任务切换,只是偶尔暂停,因此无需现场保护。 此外,如果CPU拥有一定容量的cache,而DMA传输的颗粒度又恰到好处,那么即使访问同一块RAM,软件也感觉不到程序停顿。 **工作过程:** 1. **请求与授权:** 当一个外部设备(如硬盘控制器)需要与内存交换数据时,它会向DMA控制器发出DMA请求(DMA Request,也称为DRQ)。 DMA控制器收到请求后,等待系统总线空闲的时机来执行数据传输。 时机到来时,DMA控制器向CPU发出DMA授权信号(DMA Grant,也称为DACK)。CPU通常在当前指令执行完毕后暂停,并释放总线控制权。 2. **传输数据:** DMA控制器接管总线并开始数据传输。根据设置,可以传输单个字节或一整块数据。 DMA控制器更新源和目的地址,以及还需传输的字节计数。 在数据传输过程中,CPU不参与数据传输,处于"隔离"状态。 3. **传输完成:** DMA控制器完成所有数据传输后,取消DMA授权信号。 若已设置中断,DMA控制器会向CPU发送中断信号,告知数据传输完成。随后CPU恢复操作,例如处理数据或执行其他任务。 4. **中断服务:** 如果启用了DMA完成中断,CPU在数据传输完成后会收到中断请求。 CPU随后调用相应的中断服务程序,处理传输后的任务,例如数据后处理、错误检查等。 5. **重置与准备下一次DMA:** DMA控制器重置状态,准备响应下一个DMA请求。 ## 特点与应用 **特点:** 1. **简单性:** UART通信的硬件和编程复杂度相对较低。UART本身通常在微控制器或其他处理器的硬件中实现,硬件层面不需要额外的芯片。 2. **无需时钟同步:** UART是异步通信,发送和接收设备不需要共享时钟信号,降低了硬件设计的复杂性。 3. **灵活性:** UART可以调整数据位长度、停止位数量和奇偶校验等参数,以适应不同的通信需求。 4. **可靠性:** UART通信虽然没有纠错功能,但奇偶校验能提供一定程度的错误检测。 5. **限制:** UART的通信速度(波特率)有一定限制,且速度越高,数据出错的可能性越大。此外,UART的通信距离也有限,长距离通信可能需要使用RS-422或RS-485等差分信号标准。 **应用:** 1. **嵌入式系统:** UART常用于微控制器与其他低级硬件设备的通信,例如传感器、存储卡、GPS模块等。 2. **串行通信:** UART可用于RS-232、RS-422和RS-485接口的串行通信,连接打印机、调制解调器、显示器等设备。 3. **计算机硬件:** 在早期的计算机硬件中,UART用于鼠标和键盘等外设的接口。 4. **电信设备:** 在无线通信和电信设备中,UART用于与SIM卡和其他设备通信。 5. **蓝牙模块:** 在蓝牙模块中,UART用于与主设备进行通信。 6. **IoT设备:** 在物联网设备中,UART用于低速的设备间通信。 ## 注意事项 1. **波特率选择:** 设置UART波特率时,需确保发送和接收设备的波特率一致。波特率的选择应兼顾数据传输速度需求和系统时钟频率。需要注意,波特率越高,数据传输速度越快,但误码率也可能随之增加。 2. **数据格式设置:** UART通信的数据格式,包括数据位、奇偶校验位和停止位,需要在发送和接收设备之间保持一致。常见的设置是8个数据位、无奇偶校验、1个停止位(8N1)。 3. **缓冲区管理:** UART接收数据时,通常使用接收缓冲区存储数据。需确保缓冲区足够大,防止数据溢出丢失。此外,缓冲区的读写需要正确同步,避免在多任务环境下产生冲突。 4. **流量控制:** 在高速数据传输或处理能力有限的情况下,可能需要使用硬件或软件流量控制来防止数据丢失。 5. **中断管理:** UART通常使用中断收发数据。中断服务程序(ISR)应尽可能短,以减少对其他系统任务的干扰;通常,ISR只负责在UART与缓冲区之间搬运数据。 6. **并发和多线程环境:** 在并发或多线程环境中使用UART时,可能需要使用信号量、互斥锁等机制保护UART资源,防止多个任务同时访问造成数据混乱。 7. **电源和地线:** 嵌入式系统中通常有多个电源电压级别和地线。需确保UART设备的电源电压和地线正确连接,防止通信故障或设备损坏。 8. **错误处理:** UART通信可能出现帧错误、奇偶校验错误、数据溢出等问题,需设计合适的错误处理机制来处理或报告这些错误。 9. **物理接口:** UART设备可能通过RS-232、RS-485、TTL等不同的物理接口连接,需确保使用正确的接口电平和连接方式。 10. **设备驱动和操作系统兼容性:** 使用嵌入式操作系统时,需确保UART设备驱动与操作系统兼容,必要时根据具体的操作系统和硬件平台编写或修改设备驱动。 11. **实时性:** 嵌入式系统通常需要满足一定的实时性要求,需考虑UART通信对系统实时性的影响,例如中断响应时间、数据处理时间等。 12. **功耗:** 在电池供电的嵌入式系统中,需考虑UART通信的功耗。例如,系统进入低功耗模式时,可能需要关闭UART设备或将其设置为低功耗模式。 ## 常见问题和故障 UART是一种非常简单直接的通信协议,但在实际应用中也可能遇到一些问题。以下是常见问题及对应的故障排查步骤: 1. **数据接收不正确或无法接收数据** 可能的原因包括:波特率设置错误、硬件连接问题、中断处理程序问题、缓冲区溢出等。故障排查步骤: 检查发送端和接收端的波特率设置是否一致。波特率不匹配会导致接收的数据出错。 检查硬件连接,确保TX和RX线正确连接,地线(GND)也正确连接。 如果使用了中断处理程序,确保它能正确处理接收到的数据,不会遗漏数据。 检查接收缓冲区。缓冲区太小或处理速度太慢都可能导致数据丢失,可考虑增大缓冲区或优化处理程序。 2. **数据发送不正确或无法发送数据** 可能的原因包括:硬件连接问题、发送缓冲区问题、发送程序问题等。故障排查步骤: 检查硬件连接,确保TX线正确连接,地线(GND)也正确连接。 检查发送缓冲区和发送程序,确保数据被正确放入缓冲区,且发送程序能正确地从缓冲区取出数据并发送。 3. **通信距离问题** UART的通信距离有限,距离过长会导致信号衰减,影响数据接收。若需要更长距离的通信,可使用RS-422或RS-485等差分信号标准。 4. **干扰问题** 在有电磁干扰的环境中,UART通信可能受到影响。应尽量减少电磁干扰,例如使用屏蔽线或采用电容滤波来降低噪声;若干扰过大,可能需要使用差分信号标准或光电隔离。 在进行故障排查时,常用的方法是使用逻辑分析器或示波器观察UART的信号,帮助定位问题来源。在软件层面,也可以使用调试工具观察和分析程序的运行情况。 # UART API ## 头文件 *qosa_uart.h* ## 函数概览 | **函数名** | **描述** | | --- | --- | | *qosa_uart_open()* | 打开UART设备 | | *qosa_uart_close()* | 关闭UART设备 | | *qosa_uart_write()* | 向指定的UART设备写入数据 | | *qosa_uart_read()* | 从指定的UART设备读取数据 | | *qosa_uart_read_available()* | 查询指定UART设备读缓冲区中剩余可读数据的大小 | | *qosa_uart_write_available()* | 查询指定UART设备写缓冲区中剩余可写数据的大小 | | *qosa_uart_register_cb()* | 注册UART事件回调函数 | | *qosa_uart_check_support_baudrate()* | 检查指定UART设备是否支持某个波特率 | | *qosa_uart_ioctl()* | 通过控制命令对UART设备进行配置或查询 | ## 函数详解 ### qosa_uart_open - **功能描述** 打开UART设备。 - **函数原型** ```c qosa_uart_error_e qosa_uart_open(qosa_uart_port_number_e port) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | - **返回值说明** *QOSA_UART_SUCCESS*:函数执行成功 其他值(详见 [*qosa_uart_error_e*](#qosauarterror_e)):函数执行失败 ### qosa_uart_close - **功能描述** 关闭UART设备。 - **函数原型** ```c qosa_uart_error_e qosa_uart_close(qosa_uart_port_number_e port) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | - **返回值说明** *QOSA_UART_SUCCESS*:函数执行成功 其他值(详见 [*qosa_uart_error_e*](#qosauarterror_e)):函数执行失败 ### qosa_uart_write - **功能描述** 向指定的UART设备写入数据。 - **函数原型** ```c int qosa_uart_write(qosa_uart_port_number_e port, unsigned char *data, unsigned int data_len) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *data* | 输入 | unsigned char * | 指向要写入数据的缓冲区 | | *data_len* | 输入 | unsigned int | 要写入的数据长度;单位:字节 | - **返回值说明** ≥ 0:实际写入的字节数 < 0:写入过程中发生错误,返回错误码 ### qosa_uart_read - **功能描述** 从指定的UART设备读取数据。 - **函数原型** ```c int qosa_uart_read(qosa_uart_port_number_e port, unsigned char *data, unsigned int data_len) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *data* | 输出 | unsigned char * | 用于存储读取数据的缓冲区指针 | | *data_len* | 输入 | unsigned int | 最多读取的数据长度;单位:字节 | - **返回值说明** ≥ 0:实际读取的字节数 < 0:读取过程中发生错误,返回错误码 ### qosa_uart_read_available - **功能描述** 查询指定UART设备读缓冲区中剩余可读数据的大小。 - **函数原型** ```c int qosa_uart_read_available(qosa_uart_port_number_e port) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | - **返回值说明** ≥ 0:读缓冲区中剩余可读数据的大小;单位:字节 < 0:查询过程中发生错误,返回错误码 ### qosa_uart_write_available - **功能描述** 查询指定UART设备写缓冲区中剩余可写数据的大小。 - **函数原型** ```c int qosa_uart_write_available(qosa_uart_port_number_e port) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | - **返回值说明** ≥ 0:写缓冲区中剩余可写数据的大小;单位:字节 < 0:查询过程中发生错误,返回错误码 ### qosa_uart_register_cb - **功能描述** 注册UART事件回调函数,当UART事件发生时通过该函数注册的回调函数将被调用。 - **函数原型** ```c qosa_uart_error_e qosa_uart_register_cb(qosa_uart_port_number_e port, qosa_uart_status_monitor_t *arvg) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *arvg* | 输入 | *qosa_uart_status_monitor_t* * | 回调函数信息的配置指针;详见 [*qosa_uart_status_monitor_t*](#qosauartstatusmonitort) | - **返回值说明** *QOSA_UART_SUCCESS*:函数执行成功 其他值(详见 [*qosa_uart_error_e*](#qosauarterror_e)):函数执行失败 ```{note} *arvg* 传入 *NULL* 时可取消已注册的回调函数。 ``` #### qosa_uart_callback - **功能描述** UART事件回调函数原型,当UART事件发生时该回调函数被调用。 - **函数原型** ```c typedef void (*qosa_uart_callback)(qosa_uart_cb_param_t *param); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *param* | 输入 | *qosa_uart_cb_param_t \** | 回调函数携带参数;详见 [*qosa_uart_cb_param_t*](#qosauartcbparamt) | ### qosa_uart_check_support_baudrate - **功能描述** 检查指定UART设备是否支持某个波特率。 - **函数原型** ```c qosa_bool_t qosa_uart_check_support_baudrate(qosa_uart_port_number_e port, qosa_uint32_t baudrate) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *baudrate* | 输入 | qosa_uint32_t | 要检查的波特率;单位:bps | - **返回值说明** *QOSA_TRUE*:支持该波特率 *QOSA_FALSE*:不支持该波特率 ### qosa_uart_ioctl - **功能描述** 通过指定的控制命令对UART设备进行配置或查询。 - **函数原型** ```c qosa_uart_error_e qosa_uart_ioctl(qosa_uart_port_number_e port, qosa_uart_ioctl_cmd_e cmd, void *arg) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *port* | 输入 | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *cmd* | 输入 | *qosa_uart_ioctl_cmd_e* | 对应的ioctl命令;详见 [*qosa_uart_ioctl_cmd_e*](#qosauartioctlcmde) | | *arg* | 输入/输出 | void * | 对应ioctl命令的参数;具体类型和取值随命令而定 | - **返回值说明** *QOSA_UART_SUCCESS*:函数执行成功 其他值(详见 [*qosa_uart_error_e*](#qosauarterror_e)):函数执行失败 ## 结构体定义 ### qosa_uart_config_t UART串口属性配置结构体定义如下: ```c typedef struct { qosa_uart_baud_e baudrate; qosa_uart_databit_e data_bit; qosa_uart_stopbit_e stop_bit; qosa_uart_paritybit_e parity_bit; qosa_uart_flowctrl_e flow_ctrl; } qosa_uart_config_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *baudrate* | *qosa_uart_baud_e* | 波特率;详见 [*qosa_uart_baud_e*](#qosauartbaud_e) | | *data_bit* | *qosa_uart_databit_e* | 数据位;详见 [*qosa_uart_databit_e*](#qosauartdatabit_e) | | *stop_bit* | *qosa_uart_stopbit_e* | 停止位;详见 [*qosa_uart_stopbit_e*](#qosauartstopbit_e) | | *parity_bit* | *qosa_uart_paritybit_e* | 校验位;详见 [*qosa_uart_paritybit_e*](#qosauartparitybit_e) | | *flow_ctrl* | *qosa_uart_flowctrl_e* | 流控模式;详见 [*qosa_uart_flowctrl_e*](#qosauartflowctrl_e) | ### qosa_uart_status_monitor_t 回调函数信息配置结构体定义如下: ```c typedef struct { qosa_uint32_t event_mask; qosa_uart_callback callback; void *user_data; } qosa_uart_status_monitor_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *event_mask* | qosa_uint32_t | 需要监控的事件类型;详见 [qosa_uart_event_e](#qosauartevent_e) | | *callback* | *qosa_uart_callback* | 回调函数指针 | | *user_data* | void* | 自定义参数指针 | ### qosa_uart_cb_param_t 回调函数接收参数结构体定义如下: ```c typedef struct { qosa_uart_port_number_e port; qosa_uint32_t event_id; void *user_data; } qosa_uart_cb_param_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *port* | *qosa_uart_port_number_e* | 串口选择;详见 [*qosa_uart_port_number_e*](#qosauartportnumbere) | | *event_id* | qosa_uint32_t | 串行端口自行生成事件集,按位取值;详见 [*qosa_uart_event_e*](#qosauartevent_e) | | *user_data* | void* | 自定义参数指针 | ## 枚举定义 ### qosa_uart_error_e UART操作错误码枚举定义如下: ```c typedef enum { QOSA_UART_SUCCESS = 0, QOSA_UART_EXECUTE_ERR = 1 | QOSA_UART_ERRCODE_BASE, QOSA_UART_MEM_ADDR_NULL_ERR, QOSA_UART_INVALID_PARAM_ERR, QOSA_UART_OPEN_REPEAT_ERR, QOSA_UART_NOT_OPEN_ERR, } qosa_uart_error_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_SUCCESS* | 函数执行成功 | | *QOSA_UART_EXECUTE_ERR* | 串口执行错误 | | *QOSA_UART_MEM_ADDR_NULL_ERR* | 内存地址为空 | | *QOSA_UART_INVALID_PARAM_ERR* | 参数无效 | | *QOSA_UART_OPEN_REPEAT_ERR* | 串口重复打开 | | *QOSA_UART_NOT_OPEN_ERR* | 串口未打开 | ### qosa_uart_port_number_e UART端口号枚举定义如下: ```c typedef enum { QOSA_PORT_NONE = -1, QOSA_UART_PORT_0, QOSA_UART_PORT_1, QOSA_UART_PORT_2, QOSA_UART_PORT_3, QOSA_USB_PORT_AT, QOSA_USB_PORT_MODEM, QOSA_USB_PORT_NMEA, QOSA_USB_PORT_ACM0, QOSA_PORT_MAX, } qosa_uart_port_number_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_PORT_NONE* | 无效端口 | | *QOSA_UART_PORT_0* | UART0 | | *QOSA_UART_PORT_1* | UART1 | | *QOSA_UART_PORT_2* | UART2 | | *QOSA_UART_PORT_3* | UART3 | | *QOSA_USB_PORT_AT* | USB AT端口 | | *QOSA_USB_PORT_MODEM* | USB Modem端口 | | *QOSA_USB_PORT_NMEA* | USB NMEA端口 | | *QOSA_USB_PORT_ACM0* | USB ACM0端口 | | *QOSA_PORT_MAX* | 端口数量上限 | ### qosa_uart_baud_e UART波特率枚举定义如下: ```c typedef enum { QOSA_UART_BAUD_AUTO = 0, QOSA_UART_BAUD_1200 = 1200, QOSA_UART_BAUD_2400 = 2400, QOSA_UART_BAUD_4800 = 4800, QOSA_UART_BAUD_9600 = 9600, QOSA_UART_BAUD_10400 = 10400, QOSA_UART_BAUD_14400 = 14400, QOSA_UART_BAUD_19200 = 19200, QOSA_UART_BAUD_28800 = 28800, QOSA_UART_BAUD_33600 = 33600, QOSA_UART_BAUD_38400 = 38400, QOSA_UART_BAUD_57600 = 57600, QOSA_UART_BAUD_115200 = 115200, QOSA_UART_BAUD_187500 = 187500, QOSA_UART_BAUD_230400 = 230400, QOSA_UART_BAUD_460800 = 460800, QOSA_UART_BAUD_921600 = 921600, QOSA_UART_BAUD_1000000 = 1000000, QOSA_UART_BAUD_1843200 = 1843200, QOSA_UART_BAUD_2000000 = 2000000, QOSA_UART_BAUD_2100000 = 2100000, QOSA_UART_BAUD_3686400 = 3686400, QOSA_UART_BAUD_4000000 = 4000000, QOSA_UART_BAUD_4468750 = 4468750 } qosa_uart_baud_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_BAUD_AUTO* | 自动检测波特率 | | *QOSA_UART_BAUD_1200* | 1200 bps | | *QOSA_UART_BAUD_2400* | 2400 bps | | *QOSA_UART_BAUD_4800* | 4800 bps | | *QOSA_UART_BAUD_9600* | 9600 bps | | *QOSA_UART_BAUD_10400* | 10400 bps | | *QOSA_UART_BAUD_14400* | 14400 bps | | *QOSA_UART_BAUD_19200* | 19200 bps | | *QOSA_UART_BAUD_28800* | 28800 bps | | *QOSA_UART_BAUD_33600* | 33600 bps | | *QOSA_UART_BAUD_38400* | 38400 bps | | *QOSA_UART_BAUD_57600* | 57600 bps | | *QOSA_UART_BAUD_115200* | 115200 bps | | *QOSA_UART_BAUD_187500* | 187500 bps | | *QOSA_UART_BAUD_230400* | 230400 bps | | *QOSA_UART_BAUD_460800* | 460800 bps | | *QOSA_UART_BAUD_921600* | 921600 bps | | *QOSA_UART_BAUD_1000000* | 1000000 bps | | *QOSA_UART_BAUD_1843200* | 1843200 bps | | *QOSA_UART_BAUD_2000000* | 2000000 bps | | *QOSA_UART_BAUD_2100000* | 2100000 bps | | *QOSA_UART_BAUD_3686400* | 3686400 bps | | *QOSA_UART_BAUD_4000000* | 4000000 bps | | *QOSA_UART_BAUD_4468750* | 4468750 bps | ### qosa_uart_databit_e UART数据位枚举定义如下: ```c typedef enum { QOSA_UART_DATABIT_7 = 7, QOSA_UART_DATABIT_8 = 8, } qosa_uart_databit_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_DATABIT_7* | 7个数据位 | | *QOSA_UART_DATABIT_8* | 8个数据位 | ### qosa_uart_stopbit_e UART停止位枚举定义如下: ```c typedef enum { QOSA_UART_STOP_1 = 1, QOSA_UART_STOP_2 = 2, } qosa_uart_stopbit_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_STOP_1* | 1个停止位 | | *QOSA_UART_STOP_2* | 2个停止位 | ### qosa_uart_paritybit_e UART校验位枚举定义如下: ```c typedef enum { QOSA_UART_PARITY_NONE, QOSA_UART_PARITY_ODD, QOSA_UART_PARITY_EVEN, } qosa_uart_paritybit_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_PARITY_NONE* | 无校验 | | *QOSA_UART_PARITY_ODD* | 奇校验 | | *QOSA_UART_PARITY_EVEN* | 偶校验 | ### qosa_uart_flowctrl_e UART流控模式枚举定义如下: ```c typedef enum { QOSA_FC_NONE = 0, QOSA_FC_HW, QOSA_FC_HW_RTS, QOSA_FC_HW_CTS, } qosa_uart_flowctrl_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_FC_NONE* | 无流控 | | *QOSA_FC_HW* | 硬件流控 | | *QOSA_FC_HW_RTS* | 硬件流控(RTS) | | *QOSA_FC_HW_CTS* | 硬件流控(CTS) | ### qosa_uart_event_e UART事件枚举定义如下: ```c typedef enum { QOSA_UART_EVENT_RX_INDICATE = 1 << 0, QOSA_UART_EVENT_TX_COMPLETE = 1 << 1, QOSA_UART_EVENT_TX_LOW = 1 << 2, } qosa_uart_event_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_EVENT_RX_INDICATE* | 接收数据到达事件;仅通知一次,每次调用读函数后若接收缓冲区仍有数据,将再次上报该事件 | | *QOSA_UART_EVENT_TX_COMPLETE* | 发送完成事件;每次调用写接口,底层写完成后上报 | | *QOSA_UART_EVENT_TX_LOW* | 发送FIFO低于水位事件;每次发送FIFO低于水位时上报一次 | ### qosa_uart_mode_e UART工作模式枚举定义如下: ```c typedef enum { QOSA_UART_MODE_NORMAL = 1, QOSA_UART_MODE_AT = 2, } qosa_uart_mode_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_MODE_NORMAL* | UART模式;用于传输用户自定义数据 | | *QOSA_UART_MODE_AT* | AT模式;该模式下不能调用UART相关读写API | ### qosa_uart_ioctl_cmd_e UART控制命令枚举定义如下: ```c typedef enum { QOSA_UART_IOCTL_NONE, QOSA_UART_IOCTL_SET_DCB_CFG, QOSA_UART_IOCTL_GET_DCB_CFG, QOSA_UART_IOCTL_SET_CCIO_MODE, QOSA_UART_IOCTL_RI_GET, QOSA_UART_IOCTL_RI_SET, QOSA_UART_IOCTL_DTR_GET, QOSA_UART_IOCTL_RTS_SET, QOSA_UART_IOCTL_RTS_GET, QOSA_UART_IOCTL_CTS_GET, QOSA_UART_IOCTL_DCD_GET, QOSA_UART_IOCTL_DCD_SET, QOSA_UART_IOCTL_CHANGE_BAUDRATE, QOSA_UART_IOCTL_DROP_RX_CACHE, QOSA_UART_IOCTL_RECORD_DTR_FUNC, } qosa_uart_ioctl_cmd_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_UART_IOCTL_NONE* | 无操作 | | *QOSA_UART_IOCTL_SET_DCB_CFG* | 设置串口属性 | | *QOSA_UART_IOCTL_GET_DCB_CFG* | 获取串口属性 | | *QOSA_UART_IOCTL_SET_CCIO_MODE* | 设置CCIO模式;仅EIGEN平台UART可用 | | *QOSA_UART_IOCTL_RI_GET* | 获取RI状态 | | *QOSA_UART_IOCTL_RI_SET* | 设置RI状态 | | *QOSA_UART_IOCTL_DTR_GET* | 获取DTR状态 | | *QOSA_UART_IOCTL_RTS_SET* | 设置RTS状态 | | *QOSA_UART_IOCTL_RTS_GET* | 获取RTS状态 | | *QOSA_UART_IOCTL_CTS_GET* | 获取CTS状态 | | *QOSA_UART_IOCTL_DCD_GET* | 获取DCD状态 | | *QOSA_UART_IOCTL_DCD_SET* | 设置DCD状态 | | *QOSA_UART_IOCTL_CHANGE_BAUDRATE* | 修改波特率 | | *QOSA_UART_IOCTL_DROP_RX_CACHE* | 删除待处理的RX缓存 | | *QOSA_UART_IOCTL_RECORD_DTR_FUNC* | 设置DTR回调函数 | # 应用逻辑流程图 ```{figure} images/board_XsZDwDAjVh5dKnbzHZAckKg8nvg.jpg :align: center :alt: image ``` # 示例代码 完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/peripheral/uart/uart_demo.c