【ESP32 IDF】UART串口

文章目录

  • 前言
  • 一、数据传输的基本概念
    • 1.1 串行与并行通信
    • 1.2 单工/半双工/全双工通信
    • 1.3 同步/异步通信
    • 1.4 波特率
    • 1.5 UART 四要素
  • 二、串口的使用
    • 2.1 配置UART串口
    • 2.2 配置UART引脚
    • 2.3 安装串口驱动
    • 2.4 获取环形缓冲区的数据长度
    • 2.5 读取数据
    • 2.6 发送数据
  • 总结


前言

UART(通用异步收发器)是一种常见的串口通信协议,用于在微控制器和外部设备之间进行数据传输。在ESP32 IDF(Espressif IoT Development Framework)中,提供了强大的UART功能,使得ESP32能够轻松地与其他设备进行串口通信。本文将介绍ESP32 IDF中关于UART串口的使用方法和一些重要的功能。


一、数据传输的基本概念

1.1 串行与并行通信

串行通信:
串行通信是指通过单个数据线依次传输数据位,一个接一个地发送或接收数据。在串行通信中,每个数据位依次按照顺序传输,每个时钟周期只传输一个数据位。由于只需要一根数据线,串行通信在物理线缆使用上相对简单,但数据传输速率较慢。典型的串行通信接口包括 UART、SPI、I2C 等。

并行通信:
并行通信是指同时使用多个数据线传输数据,每个数据线传输一个数据位,从而实现多个数据位同时传输。在并行通信中,多个数据位同时传输,因此可以在同一个时钟周期内传输多个数据位,从而实现较高的数据传输速率。然而,并行通信需要使用多个物理线缆,布线复杂,并且受到信号传输时延等问题的影响。典型的并行通信接口包括并行总线(如 PCI、ISA 等)。

比较:
速率: 串行通信速率较慢,每次传输一个数据位;而并行通信速率较快,每次可以同时传输多个数据位,因此可以实现更高的数据传输速率。
线缆: 串行通信只需要一根数据线,线缆布线相对简单;而并行通信需要多个数据线,布线复杂。
时延: 串行通信中每个数据位依次传输,因此受到时延影响较小;而并行通信中多个数据线同时传输,受到时延影响较大。
总体来说,串行通信适用于远距离通信和简单布线的应用场景,而并行通信适用于高速数据传输和较短距离的应用场景。

1.2 单工/半双工/全双工通信

单工通信(Simplex):
单工通信是指数据只能单向传输的通信方式,通信的一方只能发送数据,另一方只能接收数据。在单工通信中,数据流动的方向是固定的,一般用于只需单向传输数据的场合,如广播电台、电视等。

半双工通信(Half-Duplex):
半双工通信是指通信的双方都可以发送和接收数据,但不能同时进行。在同一时刻,一方只能发送数据,另一方只能接收数据。因此,在半双工通信中,数据的流动方向是可以改变的,但不能同时发送和接收数据。

全双工通信(Full-Duplex):
全双工通信是指通信的双方可以同时进行发送和接收数据。在全双工通信中,通信的双方能够独立地发送和接收数据,不会发生冲突。全双工通信常用于需要双向同时传输数据的场合,如电话通话、网络通信等。

1.3 同步/异步通信

同步通信:
在同步通信中,数据的传输是在发送方和接收方之间按照事先约定好的时钟信号进行的。发送方和接收方需要共享一个时钟信号,以确保数据传输的同步性。通常,同步通信需要发送方和接收方事先协商好时钟频率和时序控制方式,以便正确地进行数据传输。常见的同步通信接口包括 SPI(串行外设接口)、I2C(Inter-Integrated Circuit)等。

异步通信:
在异步通信中,数据的传输不需要发送方和接收方共享一个时钟信号。发送方和接收方在通信开始之前不需要进行时钟同步,而是通过发送数据中的起始位、终止位和校验位等信息来实现数据的同步和解析。异步通信不需要事先协商时钟频率和时序控制方式,因此更加灵活。常见的异步通信接口包括 UART(通用异步收发器)、RS-232 等。

比较:
时序控制: 同步通信需要发送方和接收方共享一个时钟信号进行数据传输,而异步通信不需要时钟同步。
灵活性: 异步通信更加灵活,不需要事先协商时钟频率和时序控制方式,适用于简单的通信应用。而同步通信需要事先约定时钟频率和时序控制方式,相对不够灵活。
应用场景: 同步通信适用于对时序要求较高的应用场景,如高速数据传输;而异步通信适用于不需要时序同步的简单通信场景,如串口通信。
总的来说,同步通信和异步通信各有其适用的场景,开发者可以根据具体的需求和应用场景选择合适的通信

1.4 波特率

波特率是指串行通信中每秒钟传输的比特数,通常用波特率(bps)来表示。它决定了数据传输的速度和稳定性,即每秒钟能够传输的位数。在串行通信中,发送方和接收方需要使用相同的波特率才能正确地进行数据传输。常见的波特率包括 9600 bps、115200 bps 等。

1.5 UART 四要素

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种常见的串行通信接口,用于实现串行数据的发送和接收。UART 通信的四要素包括:
波特率(Baud Rate): 波特率是串行通信中每秒钟传输的比特数,决定了数据传输的速度。发送方和接收方需要使用相同的波特率才能正常通信。
数据位(Data Bits): 数据位指的是每个数据字节中所包含的位数,常见的数据位数包括 5 位、6 位、7 位、8 位等。
停止位(Stop Bits): 停止位是在每个数据字节之后发送的用于指示数据传输结束的位。通常情况下,停止位的个数为 1 位或 2 位。
校验位(Parity Bit): 校验位用于检测数据传输过程中是否发生了错误,常见的校验方式包括奇校验、偶校验、无校验等。

二、串口的使用

2.1 配置UART串口

我们可以使用下面这个函数初始化一个UART串口:

esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)

参数1为串口编号,他有两个取值:

#define UART_NUM_0             (0) /*!< UART port 0 */
#define UART_NUM_1             (1) /*!< UART port 1 */

需要注意的是:我们的printf是使用的UART_NUM_0,如果你需要使用新串口,需要使用UART_NUM_1

uart_config_t 是一个结构体,他的成员如下:

typedef struct {int baud_rate;                      /*!< UART baud rate*/uart_word_length_t data_bits;       /*!< UART byte size*/uart_parity_t parity;               /*!< UART parity mode*/uart_stop_bits_t stop_bits;         /*!< UART stop bits*/uart_hw_flowcontrol_t flow_ctrl;    /*!< UART HW flow control mode (cts/rts)*/uint8_t rx_flow_ctrl_thresh;        /*!< UART HW RTS threshold*/union {uart_sclk_t source_clk;         /*!< UART source clock selection */bool use_ref_tick  __attribute__((deprecated)); /*!< Deprecated method to select ref tick clock source, set source_clk field instead */};
} uart_config_t;

baud_rate:
类型:int
作用:指定UART的波特率(波特率是指每秒传输的位数,通常用bps表示)。这个参数决定了通信双方之间传输数据的速度。

data_bits:
类型:uart_word_length_t
作用:指定UART每个数据帧的位数,即数据位的长度。通常可以选择8位、9位等,表示一个数据帧中有多少位用于携带实际的数据。

parity:
类型:uart_parity_t
作用:指定奇偶校验模式,可以选择禁用奇偶校验、奇校验或偶校验。奇偶校验用于检测传输过程中的错误。

stop_bits:
类型:uart_stop_bits_t
作用:指定停止位的数量。通常可以选择1位或2位停止位。

flow_ctrl:
类型:uart_hw_flowcontrol_t
作用:指定硬件流控制的模式,可以选择禁用流控制、启用CTS(Clear To Send)和RTS(Request To Send)

rx_flow_ctrl_thresh:
类型:uint8_t
作用:当启用硬件流控制时,该参数指定了UART接收缓冲区中的数据量,当数据量低于这个阈值时,RTS信号将被拉高,允许继续接收数据。

source_clk:
类型:uart_sclk_t
作用:指定UART的时钟源。可以选择使用内部时钟源(PLL输出)或外部时钟源。
他有这些取值:

typedef enum {UART_SCLK_APB = 0x0,            /*!< UART source clock from APB*/
#if SOC_UART_SUPPORT_RTC_CLKUART_SCLK_RTC = 0x1,            /*!< UART source clock from RTC*/
#endif
#if SOC_UART_SUPPORT_XTAL_CLKUART_SCLK_XTAL = 0x2,           /*!< UART source clock from XTAL*/
#endif
#if SOC_UART_SUPPORT_REF_TICKUART_SCLK_REF_TICK = 0x3,       /*!< UART source clock from REF_TICK*/
#endif
} uart_sclk_t;

UART_SCLK_APB (0x0):

作用:指定UART的时钟源来自APB总线。
APB是Advanced Peripheral Bus(高级外设总线)的缩写,是用于连接外设的总线之一。
UART_SCLK_RTC (0x1):

作用:指定UART的时钟源来自RTC(Real-Time Clock,实时时钟)。
RTC通常是微控制器中一个独立的时钟模块,用于提供精确的时间信息。
UART_SCLK_XTAL (0x2):

作用:指定UART的时钟源来自外部晶体振荡器(XTAL)。
外部晶体振荡器提供了高精度的时钟信号,常用于需要精准时序要求的应用。
UART_SCLK_REF_TICK (0x3):

作用:指定UART的时钟源来自参考时钟(REF_TICK)。
参考时钟通常是一个周期性的时钟信号,用于提供基准时钟。

use_ref_tick:
类型:bool
作用:(已弃用)以前用于选择参考时钟源,现在被source_clk字段替代。

2.2 配置UART引脚

我们可以使用下面这个函数

esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)

uart_num:
类型:uart_port_t
含义:指定要配置的UART端口号,例如UART0、UART1等。

tx_io_num:
类型:int
含义:指定UART的发送引脚(TX)的引脚号。这是数据从ESP32发送到外部设备的引脚。

rx_io_num:
类型:int
含义:指定UART的接收引脚(RX)的引脚号。这是数据从外部设备接收到ESP32的引脚。

rts_io_num:
类型:int
含义:指定UART的RTS(Request To Send)引脚的引脚号。RTS用于硬件流控制,在一些情况下可以让接收方暂停发送数据。
如果没有,使用UART_PIN_NO_CHANGE

cts_io_num:
类型:int
含义:指定UART的CTS(Clear To Send)引脚的引脚号。CTS也是用于硬件流控制,接收方通过CTS信号告知发送方是否可以发送数据。
如果没有,使用UART_PIN_NO_CHANGE

2.3 安装串口驱动

我们可以使用下面这个函数安装串口驱动:

esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int event_queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags)

uart_num:
类型:uart_port_t
含义:指定要安装的UART端口号,例如UART0、UART1等。

rx_buffer_size:
类型:int
含义:指定UART接收缓冲区的大小,即用于存储接收到的数据的缓冲区大小。

tx_buffer_size:
类型:int
含义:指定UART发送缓冲区的大小,即用于存储待发送数据的缓冲区大小。

event_queue_size:
类型:int
含义:指定用于存储UART事件的队列的大小。UART事件包括接收到数据、发送数据完成等事件。

uart_queue:
类型:QueueHandle_t *
含义:指定一个指针,用于存储创建的UART事件队列的句柄。这样,用户可以在其他部分的代码中使用这个队列句柄来接收和处理UART事件。
他里面的取值如下:

typedef enum {UART_DATA,              /*!< UART data event*/UART_BREAK,             /*!< UART break event*/UART_BUFFER_FULL,       /*!< UART RX buffer full event*/UART_FIFO_OVF,          /*!< UART FIFO overflow event*/UART_FRAME_ERR,         /*!< UART RX frame error event*/UART_PARITY_ERR,        /*!< UART RX parity event*/UART_DATA_BREAK,        /*!< UART TX data and break event*/UART_PATTERN_DET,       /*!< UART pattern detected */UART_EVENT_MAX,         /*!< UART event max index*/
} uart_event_type_t;

UART_DATA:
表示接收到了新的数据。

UART_FIFO_OVF:
表示接收 FIFO 溢出。

UART_BUFFER_FULL:
表示发送缓冲区已满。

UART_BREAK:
表示接收到 Break 信号。

UART_PARITY_ERR:
表示接收到的数据帧中有奇偶校验错误。

UART_FRAME_ERR:
表示接收到的数据帧中存在帧错误。

UART_PATTERN_DET:
表示接收到了特定的数据模式。

intr_alloc_flags:
类型:int
含义:指定中断分配的标志位。这个参数用于确定中断服务程序的运行上下文。可以使用常量 ESP_INTR_FLAG_* 来指定中断分配的特性。
作用:

控制 UART 接收和发送中断的行为,包括是否允许中断,以及中断的优先级等。
可能的取值:

ESP_INTR_FLAG_LEVEL1: 设置中断优先级为 1 级,表示具有最高的优先级,适用于需要立即响应的紧急情况。
ESP_INTR_FLAG_LEVEL2: 设置中断优先级为 2 级,次于级别 1,适用于需要较高优先级但不是最高的情况。
ESP_INTR_FLAG_LEVEL3: 设置中断优先级为 3 级,优先级次于级别 2,适用于一般性的中断处理。
ESP_INTR_FLAG_IRAM: 将中断服务程序(ISR)分配到内部 RAM 中运行,适用于对中断响应速度要求较高的情况。
ESP_INTR_FLAG_EDGE: 使用边沿触发模式,当引脚状态发生变化时触发中断。
ESP_INTR_FLAG_LEVEL: 使用电平触发模式,当引脚保持特定电平时触发中断。
ESP_INTR_FLAG_LOWMED: 用于指示低或中等优先级的中断请求。
ESP_INTR_FLAG_HIGH: 用于指示高优先级的中断请求。

如果 intr_alloc_flags 参数设置为 0,表示不使用任何中断配置标志。这意味着 UART 的中断将按照系统的默认设置进行分配和处理。在某些情况下,可能会选择不自定义中断配置,而是依赖于系统的默认设置,这通常是因为应用场景对中断处理的要求不是很严格或者默认设置已经足够满足需求。

因此,如果将 intr_alloc_flags 参数设置为 0,则系统将根据默认配置来处理 UART 的中断,这可能与系统的硬件和软件环境有关,具体的行为取决于 ESP-IDF 的实现细节。

2.4 获取环形缓冲区的数据长度

我们可以使用下面这个函数来获取环形缓冲区的数据长度:

esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t *size)

参数1为UART的编号,参数2为size_t *,用于存储长度

2.5 读取数据

我们可以使用下面这个函数来读取UART数据;

int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait)

参数1为UART的编号,参数2为你数据存储的地方,参数3为读取的长度,参数4为等待事件

2.6 发送数据

我们可以使用下面这个函数来发送数据;

int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)

参数1为UART的编号,参数2为发送源,参数3为源的size


总结

在ESP32 IDF中,UART串口模块提供了丰富的功能和灵活的配置选项,使得开发者可以方便地实现与外部设备的通信。通过使用UART串口,ESP32可以与各种设备(如传感器、显示器、无线模块等)进行可靠的数据交换。本文总结了ESP32 IDF中UART串口的基本用法,并介绍了一些常用的配置选项和注意事项,希望能够帮助开发者更好地利用ESP32的UART功能进行开发。

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

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

相关文章

第十二篇:学习python数据清洗

文章目录 一、啥是数据清洗二、将表格数据导入pandas中1. 准备工作2. 引入csv文件2.1 引入pandas库2.2 读取文件/修改名称3.2 快速浏览数据2.4 修改名字2.5 查找缺失值2.6 删除缺失值 3. 引入Excel文件3.1 引入pandas库3.2 读取Excel文件的人均GDP数据3.3 查看数据类型和non-nu…

Android中的几种定位方式调用详解

目前&#xff0c;移动端大致通过三种方式来进行设备定位&#xff1a;GPS、基站、wifi。本文就详细的讲解一下这几种定位方式和实现方法。 前言 android中我们一般使用LocationManager来获取位置信息&#xff0c;这里面有四中provider&#xff1a; public static final Strin…

怎样获取html网页中<ul >中的数据?

您可以使用Python中的BeautifulSoup库来获取HTML网页中<ul>标签中的数据。以下是一个示例代码&#xff1a; rom bs4 import BeautifulSoup import requests# 发送HTTP请求并获取网页内容 url "http://example.com" # 替换为目标网页的URL response request…

YOLOv8从入门到入土使用教程!(一)训练模型

⭐⭐⭐瞧一瞧看一看&#xff0c;新鲜的YOLOv9魔改专栏来啦&#xff01;⭐⭐⭐ 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、本文介绍 本文将演示如何使用YOLOv8进行训练及预测&#xff01; 二…

线性dp 最长公共子序列(二分版本)

本题由于1e5的数据&#xff0c;n方的做法不再适用&#xff0c;但是简单的一维并不能满足动态转移。这时&#xff0c;我们就可以考虑引入最长上升子序列来处理 用样例来看 5 序列&#xff1a;3 2 1 4 5序号&#xff1a;1 2 3 4 5序列&#xff1a;1 2 3 4 5序号&#xff1a;3 2…

1.1 Java 注解(Annotation)

1.1 注解&#xff08;Annotation&#xff09; 1.1.1 什么是注解 注解的定义&#xff1a;它提供了一种安全的类似注释的机制&#xff0c;用来将任何信息或元数据&#xff08;metadata&#xff09;与程序元素&#xff08;类、方法、成员变量等&#xff09;进行关联。为程序的元…

九型人格测试,2号人格助人型的职业分析

九型人格测试中的助人型&#xff0c;也叫二号人格&#xff0c;解读专业选择和职业选择。 助人型人格&#xff0c;在九型人格中&#xff0c;被视作一种给予者&#xff0c;他们总是喜欢帮助别人&#xff0c;有一个观念&#xff1a;“我不帮助别人&#xff0c;就没有人愿意喜欢我…

透明玻璃屏幕为什么那么贵

透明玻璃屏幕之所以价格较高&#xff0c;主要是由于以下几个方面的原因&#xff1a; 技术研发与创新&#xff1a;透明玻璃屏幕作为一种先进的显示技术&#xff0c;其研发和制造过程涉及到许多复杂的技术。这些技术的研发和创新需要投入大量的资金和时间。此外&#xff0c;透明玻…

鸿蒙应用native开发入门以及运行native项目报错spawn EPERM问题解决以及so包调用

目录 DevEco Studio新建native项目 新建第一个native项目 解决spawn EPERM报错 点击运行 分析流程

无冬之夜:增强版 Neverwinter Nights Mac 激活版

Neverwinter Nights是一款角色扮演游戏。游戏的剧情发生在虚构的城市Neverwinter&#xff0c;玩家扮演一个冒险者&#xff0c;在这个城市中探索并完成各种任务。游戏中有许多不同的职业、种族、技能和法术可供玩家选择。游戏的主要特点包括多人游戏模式、自定义模块和工具包&am…

【Mc生存】插火把

【Mc生存】插火把 题目描述 话说有一天 linyorson 在“我的世界”开了一个 n n n \times n nn 的方阵&#xff0c;现在他有 m m m 个火把和 k k k 个萤石&#xff0c;分别放在 ( x 1 , y 1 ) ∼ ( x m , y m ) (x_1, y_1) \sim (x_m, y_m) (x1​,y1​)∼(xm​,ym​) 和 …

【书生·浦语大模型实战营】第5节 课后作业

LMDeploy 的量化和部署 0. 课程链接1. 课后作业1.1 基础作业1.2 进阶作业&#xff08;可选做&#xff09; 0. 课程链接 链接&#xff1a;https://github.com/InternLM/tutorial/blob/main/lmdeploy/lmdeploy.md 1. 课后作业 1.1 基础作业 使用 LMDeploy 以本地对话、网页Gra…

大模型技术在测试领域应用的方向思考

方向1&#xff1a;利用大模型技术生成测试用例 方向2&#xff1a;利用大模型技术进行测试用例推荐 如何利用大模型技术生成测试用例 大模型技术&#xff0c;如自然语言处理&#xff08;NLP&#xff09;中的大型预训练模型&#xff0c;如BERT、GPT等&#xff0c;已经在许多领…

HTML5:七天学会基础动画网页5

CSS3渐变 (可以给背景颜色设置一个渐变的效果) 线性渐变:Linear Gradients(从直线上向远处见面) 语法: background:linear-gradient(direction&#xff0c;color-stop1&#xff0c;color-stop2…)&#xff1b; direction:方向 to left, to right, 90deg 径向渐变:Radial …

Python Flask Web + PyQt 前后端分离的项目—学习成绩可视化分析系统

简介 使用工具&#xff1a; Python&#xff0c;PyQt &#xff0c;Flask &#xff0c;MySQL 注&#xff1a;制作重点在网页端&#xff0c;因此网页端的功能更全 WEB界面展示: 系统登录分为管理员&#xff0c;老师&#xff0c;学生3部分 管理员统一管理所有的账号信息以及登录…

Jenkins发送邮件、定时执行、持续部署

集成Allure报告只需要配置构建后操作即可。但如果是web自动化&#xff0c;或是用HTMLTestRunner生成报告&#xff0c;构建后操作要选择Publish HTML reports&#xff0c;而构建中还要添加Execute system Groovy script插件&#xff0c;内容&#xff1a; System.setProperty(&q…

【数据结构】用队列实现栈

下面是一些思路分析和代码分享&#xff0c;有需要借鉴即可。 1.问题描述 我想用队列来实现栈的功能&#xff0c;具体而言是用两个队列做底层做出栈的功能来。 有人可能会疑问会不会多次一举&#xff0c;这里仅作练习&#xff0c;为了更加进一步了解栈/队列的性质 2.思路分析 …

基于Spring Boot+ Vue的房屋租赁系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…

抉择与发展:详解程序员在前端、后端与数据科学赛道上的职业定位与成长路径

作为一个程序员&#xff0c;选择职业赛道就像是在一座迷宫中探索前端的美丽花园&#xff0c;后端的黑暗洞穴&#xff0c;还有数据科学的神秘密室。每一条赛道都充满了挑战和机遇&#xff0c;而选择哪一条赛道将直接影响到你未来的职业发展和成就。对于每一位准备投身或已经在编…

搜维尔科技:捕获、分析、优化,使用 Xsens Ergo 创建更安全的工作空间

简化人体工程学分析&#xff0c;优先考虑员工福祉&#xff0c;并利用客观数据和见解提高生产力。 捕获。分析。优化。使用 Xsens Ergo 创建更安全的工作空间 1.质量数据 使用高质量、客观且经过验证的运动数据进行详细的人体工程学分析 2.随处使用 在最具挑战性的工作环境中…