【ESP32】ESP-IDF开发 | UART通用异步收发传输器+串口收发例程
1. 简介
UART可以说是开发者使用得最多的外设之一了,打印log几乎都是使用串口来实现的。UART是一种异步全双工的通信方式,异步传输的特性使得它仅需2根线就可以完成全双工的传输,但这也要求发送端和接收端的速率、停止位、奇偶校验位等都要相同,通信才能成功。
一个典型的UART帧开始于一个起始位,紧接着是有效数据,然后是奇偶校验位(可有可无),最后是停止位。 ESP32上的UART控制器支持多种字符长度和停止位。另外,控制器还支持软硬件流控和 DMA,可以实现无缝高速的数据传输。
2. 硬件架构

ESP32中的UART有两个时钟源:80MHz APB_CLK和参考时钟REF_TICK,时钟源进来后会通过分频器调整到对应的频率,分频后的时钟会分别进到发送块和接收块。
发送器和接收器都各自有一个FIFO来缓存数据,每个FIFO有128字节的空间,ESP32中3个UART设备会共享一块1KB大小的内存作为FIFO空间。获取FIFO数据除了通过CPU来实现,还可以通过内部DMA实现,以提高效率。
UART设备也支持硬件流控和软件流控,以支持像RS-485、红外遥控等协议的开发。
3. 流控
3.1 硬件流控

硬件流控主要通过输出信号rtsn_out和输入信号dsrn_in进行数据流控制。
输出信号rtsn_out为高电平表示请求对方发送数据,rtsn_out为低电平表示通知对方中止数据发送直到rtsn_out恢复高电平。
当UART检测到输入信号ctsn_in的沿变化时会产生UART_CTS_CHG_INT中断并且在发送完当前数据后停止接下来的数据发送。
输出信号dtrn_out为高电平表示发送方数据已经准备完毕,UART在检测到输入信号dsrn_in 的沿变化时会产生UART_DSR_CHG_INT中断。软件在检测到中断后,通过读取UART_DSRN可以获取dsrn_in的输入信号电平,从而判断当前是否可以接收数据。
3.2 软件流控
软件流控主要通过在发送数据流中插入特殊字符以及在接收数据流中检测特殊字符来实现数据流控功能。
软件可以通过置位UART_FORCE_XOFF来强制停止发送器发送数据,也可以通过置位UART_FORCE_XON来强制发送器发送数据。
UART还可以通过传输特殊字符进行软件流控,当UART 接收的数据字节数超过UART_XOFF的阈值时,可以通过发送UART_XOFF_CHAR来告知对方停止发送数据。
软件也可以在任意时候发送流控字符。置位UART_SEND_XOFF,发送器会在发送完当前数据之后插入发送一个UART_XOFF_CHAR;置位 UART_SEND_XON,发送器会在发送完当前数据之后插入发送一个UART_XON_CHAR。
4. 例程
例程中使用ESP32的串口1和串口2,相互连接并实现数据收发。
#include "driver/gpio.h"
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "esp_log.h"#include <string.h>#define TAG "app"void app_main()
{uart_config_t uart_cfg = {0};uart_cfg.baud_rate = 115200,uart_cfg.data_bits = UART_DATA_8_BITS; // 8位数据uart_cfg.parity = UART_PARITY_DISABLE; // 无校检uart_cfg.stop_bits = UART_STOP_BITS_1; // 1位停止位uart_cfg.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; // 无硬件流控uart_cfg.source_clk = UART_SCLK_DEFAULT; // 默认时钟源,APB时钟/* 初始化串口1 */ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, 1024 * 2, 0, 0, NULL, 0));ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_cfg));ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, 17, 18, -1, -1));/* 初始化串口2 */ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, 1024 * 2, 0, 0, NULL, 0));ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_cfg));ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 21, 22, -1, -1));const char *str = "Hello, World!";while (1) {/* 串口1发送 */int send_len = uart_write_bytes(UART_NUM_1, str, strlen(str));ESP_LOGI(TAG, "Send %d bytes, data: %s", send_len, str);uart_wait_tx_done(UART_NUM_1, portMAX_DELAY);/* 串口2接收 */char buf[128] = {0};int read_len = uart_read_bytes(UART_NUM_2, buf, 128, 100 / portTICK_PERIOD_MS);if (read_len >= 0) {ESP_LOGI(TAG, "[UART2] Receive %d bytes, data: %s", read_len, buf);} else {ESP_LOGE(TAG, "[UART2] Receive data timeout");}vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
先初始化uart_config_t结构体,我设置的是常见的115200波特率,无校检,1位停止位,时钟为APB时钟。
uart_driver_install注册串口设备,参数1为串口号;参数2和3是接收和发送缓冲区大小,缓冲区的大小必须大于FIFO的大小,发送缓冲区可以为0,我设置接收缓冲区2KB,无发送缓冲;参数4和5是消息队列的大小和句柄,可以通过它来接收串口的事件数据;参数6是注册标志,一般默认为0即可。
uart_param_config配置串口通信参数;uart_set_pin配置串口引脚,参数依次为发送管脚、接收管脚、RTS管脚和CTS管脚,管脚不用的话设置为-1。
uart_write_bytes发送数据,如果发送缓冲区为0,那么所有数据压入发送FIFO就会返回;如果发送缓冲区不为0,那么所有数据复制进缓冲区时就会返回。其实无论哪一种情况,函数返回都不能保证数据一定完全发送了,所以最好后面调uart_wait_tx_done等串口完全发送再执行下一步操作。
使用uart_read_bytes接收串口数据,最后一个参数可以设置等待时长,我这里是等待100ms。

相关文章:
【ESP32】ESP-IDF开发 | UART通用异步收发传输器+串口收发例程
1. 简介 UART可以说是开发者使用得最多的外设之一了,打印log几乎都是使用串口来实现的。UART是一种异步全双工的通信方式,异步传输的特性使得它仅需2根线就可以完成全双工的传输,但这也要求发送端和接收端的速率、停止位、奇偶校验位等都要相…...
2025秋招LLM大模型多模态面试题(六)-KV缓存
目录 为什么Transformer推理需要KV缓存?KV缓存的具体实现 没有缓存的情况下使用缓存的情况下KV缓存在解码中的阶段划分 Prefil阶段Decoding阶段KV缓存的存储类型及显存占用计算KV缓存的局限与优化策略 超长文本与复杂模型场景下的瓶颈量化方案的应用量化方案的副作用与优化方法…...
matlab边缘点提取函数
1、边缘提取 matlab自带点云边缘提取函数,用于搜索点云边界,其核心是alpha shapes算法。alpha shapes提取边缘点,主要是依据滚动圆绕点云进行旋转,实现边缘检测,原理如下图所示。具体原理及效果,可以参考之前我写的博客:基于alpha shapes的边缘点提取(matlab)-CSDN博客…...
Redis 执行 Lua,能保证原子性吗?
前言 小张目前在使用分布式锁 Redisson 实现一个需求。那我在想我能否自己手撸一个能用于分布式环境的锁呢?于是果然尝试。 历经一天后,小张手撸的锁终于写出来了,再次给各位看看,看给位有没有什么优化的建议: // 加…...
让模型评估模型:构建双代理RAG评估系统的步骤解析
在当前大语言模型(LLM)应用开发的背景下,一个关键问题是如何评估模型输出的准确性。我们需要确定哪些评估指标能够有效衡量提示(prompt)的效果,以及在多大程度上需要对提示进行优化。 为解决这一问题,我们将介绍一个基于双代理的RAG(检索增强生成)评估系统。该系统使用生成代理…...
RabbitMQ 高级特性——发送方确认
文章目录 前言发送方确认confirm 确认模式return 退回模式 常见面试题 前言 前面我们学习了 RabbitMQ 中交换机、队列和消息的持久化,这样能够保证存储在 RabbitMQ Broker 中的交换机和队列中的消息实现持久化,就算 RabbitMQ 服务发生了重启或者是宕机&…...
马踏棋盘c++
马踏棋盘c 题目回溯问题模型特征模型 代码 题目 马踏棋盘算法,即骑士周游问题。将马放在国际象棋的 88 棋盘的某个方格中,马按走棋规则(马走日字)进行移动。每个方格只进入一次,走遍棋盘上全部 64 个方格。 回溯问题模型 特征 解组织成树…...
OpenSSH从7.4升级到9.8的过程 亲测--图文详解
一、下载软件 下载openssh 下载地址: Downloads | Library 下载openssl Index of /pub/OpenBSD/OpenSSH/ zlib Home Site 安装的 openssl-3.3.1.tar.gz ,安装3.3.2有问题 安装有问题, 二、安装依赖 yum install -y perl-CPAN perl-ExtUtils-CB…...
系统分析与设计
一、结构化方法 生命周期:结构化分析、结构化设计、结构化编程 原则:程序 算法 数据结构 1、结构化分析:数据流图和数据字典 2、结构化设计: 1)模块结构:信息隐藏与抽象、模块化、低耦合高内聚 2&…...
vite 使用飞行器仪表示例
这里写自定义目录标题 环境vue代码效果图 环境 jquery npm install -S jqueryjQuery-Flight-Indicators 将img、css、js拷贝到vite工程目录中 打开 jquery.flightindicators.js,在文件开头加上import jQuery from "jquery"; vue代码 <template>&…...
【隐私计算】Cheetah安全多方计算协议-阿里安全双子座实验室
2PC-NN安全推理与实际应用之间仍存在较大性能差距,因此只适用于小数据集或简单模型。Cheetah仔细设计DNN,基于格的同态加密、VOLE类型的不经意传输和秘密共享,提出了一个2PC-NN推理系统Cheetah,比CCS20的CrypTFlow2开销小的多&…...
Python 实现Excel XLS和XLSX格式相互转换
在日常工作中,我们经常需要处理和转换不同格式的Excel文件,以适应不同的需求和软件兼容性。Excel文件的两种常见格式是XLS(Excel 97-2003)和XLSX(Excel 2007及以上版本)。本文将详细介绍如何使用Python在XL…...
黑马智数Day1
src文件夹 src 目录指的是源代码目录,存放项目应用的源代码,包含项目的逻辑和功能实现,实际上线之后在浏览器中跑的代码就是它们 apis - 业务接口 assets - 静态资源 (图片) components - 组件 公共组件 constants…...
网络协议全景:Linux环境下的TCP/IP、UDP
目录 1.UDP协议解析1.1.定义1.2.UDP报头1.3.特点1.4.缓冲区 2.TCP协议解析2.1.定义2.2.报头解析2.2.1.首部长度(4位)2.2.2.窗口大小2.2.3.确认应答机制2.2.4.6个标志位 2.3.超时重传机制2.4.三次握手四次挥手2.4.1.全/半连接队列2.4.2.listen2.4.3.TIME_…...
制造企业MES系统委外工单管理探析
一、委外工单管理的重要性 在制造企业的生产过程中,委外工单管理是一项重要且复杂的任务。委外加工是指企业将某些生产任务外包给外部供应商完成,以降低成本、提高效率或满足特定需求。然而,委外加工过程中往往存在诸多不确定性,…...
【C语言-数据结构】顺序表的基本操作
顺序表的基本操作 【建议:如果对结构体还不太理解的话可以先看 C语言-结构体 这篇文章】 插入操作 ListInsert(&L,i,e):插入操作,在表 L 中的第 i 个位置上插入指定元素 e 代码实现 #include <stdio.h> #include <stdbool.…...
使用Renesas R7FA8D1BH (Cortex®-M85)实现多功能UI
目录 概述 1 系统框架介绍 1.1 模块功能介绍 1.2 UI页面功能 2 软件框架结构实现 2.1 软件框架图 2.1.1 应用层API 2.1.2 硬件驱动层 2.1.3 MCU底层驱动 2.2 软件流程图 4 软件功能实现 4.1 状态机功能核心代码 4.2 页面功能函数 4.3 源代码文件 5 功能测试 5.1…...
【java】常见限流算法原理及应用
目录 前言 限流的作用 4种常见限流算法 固定窗口限流 基本原理 简单实现 优点和缺点 滑动窗口限流 基本原理 简单实现 优点和缺点 漏桶限流 基本原理 简单实现 优点和缺点 令牌桶限流 基本原理 简单实现 优点和缺点 算法比较与选择 前言 在现代分布式系统…...
Git 原理(提交对象)(结合图与案例)
Git 原理(提交对象) 这一块主要讲述下 Git 的原理。 在进行提交操作时,Git 会保存一个提交对象(commit object): 该提交对象会包含一个指向暂存内容快照的指针; 该提交对象还包含了作者的姓…...
STM32如何修改外部晶振频率和主频
对于STM32F10x系列的单片机,除了STM32F10x_CL单片机,其它的单片机一般外部晶振HSE的时钟频率都默认是8MHz。如果我们使用的外部晶振为12Mhz,那么可以把上图绿色标记改为:12000000 72MHz的主频8MHz的外部晶振HSE*倍频系数9。当然如果像上面把外…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...
【Redis】Redis从入门到实战:全面指南
Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...
