ESP32学习笔记_Peripherals(1)——UART

摘要(From AI):
这篇博客详细讲解了 ESP32 UART 通信的基础知识、配置流程和实践代码,涵盖了 UART 的工作原理、API 使用方法以及实际应用场景,结合完整的代码示例展示了如何与外部设备(如 4G 模块)进行串口通信。内容逻辑清晰,注释详尽,并附有运行调试截图验证效果,实用性强

前言:本文档是本人在依照乐鑫科技编写的ESP32 API文档进行学习时所做的学习笔记,可能存在疏漏和错误,如有发现,敬请指正。

文章目录

  • UART
    • Set Communication Parameters
      • Single Step
      • Multiple Steps
    • Set Communication Pins
      • uart_set_pin()
    • Install Drivers
      • uart_driver_install()
    • Run UART Communication
      • Transmit Data
        • uart_write_bytes()
        • uart_write_bytes_with_break()
        • uart_tx_chars()
        • uart_wait_tx_done()
      • Receive Data
        • uart_read_bytes()
        • uart_get_buffered_data_len()
        • uart_flush()
    • Delete a Driver
      • uart_driver_delete()
    • Check for Errors
        • ESP_ERROR_CHECK()
    • Example Code:UART Communication Task

参考资料
ESP 官方文档(写的真的很好)


UART

UART(Universal Asynchronous Receiver-Transmitter,通用异步收发器)是一种常见的串行通信接口,用于在设备之间传输数据。它的特点是简单、可靠,广泛应用于嵌入式系统、微控制器、传感器和计算机外围设备中

UART的工作原理

  1. 异步通信:UART不需要额外的时钟信号,通信双方使用预先约定的波特率(baud rate)来同步数据。
  2. 数据帧结构:数据以帧的形式传输,每帧包括:
    • 起始位(Start Bit):1位,表示数据帧的开始,通常为低电平
    • 数据位(Data Bits):5到8位,表示实际传输的数据
    • 校验位(Parity Bit,非必须):1位,用于检测数据错误
    • 停止位(Stop Bit):1或2位,表示数据帧的结束
  3. 双向通信:UART包括发送端(TX)和接收端(RX),数据从一个设备的TX引脚传输到另一个设备的RX引脚

优点

  • 硬件简单,不需要额外的时钟线
  • 支持全双工通信(TX和RX同时工作)
  • 波特率灵活,适配多种设备需求

缺点

  • 通信速度较慢,不适合大数据量的高速传输
  • 距离有限,通常适用于短距离通信
  • 对波特率一致性要求较高

ESP32 芯片有 3 个 UART 控制器(端口),每个控制器都有一组相同的寄存器以简化编程并提高灵活性
每个 UART 控制器可以独立配置波特率、数据位长度、位顺序、停止位位数、奇偶校验位等参数。所有具备完整功能的 UART 控制器都能与不同制造商的 UART 设备兼容,并且支持红外数据协会 (IrDA) 定义的标准协议

使用 UART 通信流程

  1. Set Communication Parameters 设置通信参数 设置波特率、数据位、停止位等
  2. Set Communication Pins 设置通信管脚 分配连接设备的管脚
  3. Install Drivers 安装驱动程序 为 UART 驱动程序分配 ESP32 资源
  4. Run UART Communication 运行 UART 通信发送/接收数据
  5. Use Interrupts 使用中断 触发特定通信事件的中断
  6. Delete a Driver 删除驱动程序 如无需 UART 通信,则释放已分配的资源

Set Communication Parameters

UART 通信参数可以在一个步骤中完成全部配置,也可以在多个步骤中单独配置

Single Step

使用 uart_param_config() 可以在一个步骤中完成通信参数的全部配置

esp_err_t uart_param_config(uart_port_t uart_num,const uart_config_t *uart_config)

参数
uart_num UART 端口(控制器)号,最大端口号为(UART_NUM_max-1)
uart_config UART 参数设置,本质为一个 uart_config_t 结构体,应包含所有必要参数

const uart_port_t uart_num = UART_NUM_2;
uart_config_t uart_config = {.baud_rate = 115200,// 设置通信波特率.data_bits = UART_DATA_8_BITS,// 设置每帧数据的传输位数.parity = UART_PARITY_DISABLE,// 设置是否使用校验位,用于检测传输错误.stop_bits = UART_STOP_BITS_1,// 设置停止位的数量,用于标识一帧的结束.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,// 设置流控模式.rx_flow_ctrl_thresh = 122,// 设置接收数据流控的触发阈值
};

以上这些数据的定义可以在 uart_types.h找到,如:
UART_DATA_5_BITS = 0x0, // 5 位数据
UART_DATA_6_BITS = 0x1, // 6 位数据
UART_DATA_7_BITS = 0x2, // 7 位数据
UART_DATA_8_BITS = 0x3, // 8 位数据
UART_DATA_BITS_MAX = 0x4,

Multiple Steps

可以使用相应的设置函数单独设置每一个参数

配置参数函数
波特率uart_set_baudrate()
传输位调用 uart_set_word_length()
奇偶控制调用 uart_set_parity()设置 uart_parity_t
停止位调用 uart_set_stop_bits()设置 uart_stop_bits_t
硬件流控模式调用 uart_set_hw_flow_ctrl()设置 uart_hw_flowcontrol_t
通信模式调用 uart_set_mode()设置 uart_mode_t

每个函数都可使用 _get_ 对应项来查看当前设置值;例如 uart_set_baudrate()uart_get_baudrate()

uart_set_baudrate()
设置串口通信波特率

esp_err_t uart_set_baudrate(uart_port_t uart_num,uint32_t baudrate)

参数
uart_num UART 端口号
baudrate UART 波特率值

返回值
ESP_FAIL 参数错误
ESP_OK 成功

uart_get_baudrate()
获取 UART 波特率配置

esp_err_t uart_get_baudrate(uart_port_t uart_num,uint32_t *baudrate)

参数
uart_num UART 端口号
baudrate 指向用于存储 UART 波特率值的空间的指针

返回值
ESP_FAIL 参数错误
ESP_OK 成功将结果写入 *baudrate

Set Communication Pins

通信参数设置完成后,可以配置与其他 UART 设备连接的 GPIO 管脚;通过函数 uart_set_pin(),指定配置 Tx、Rx、RTS 和 CTS 信号的 GPIO 管脚编号

uart_set_pin()

将 UART 外设的信号分配给 GPIO 引脚

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 端口号
tx_io_num Tx 引脚 GPIO 编号
rx_io_num Rx 引脚 GPIO 编号
rts_io_num RTS 引脚 GPIO 编号
cts_io_num CTS 引脚 GPIO 编号

如要为特定信号保留(不使用)当前分配的管脚编号,可传递宏 UART_PIN_NO_CHANGE

RTS(Request to Send)CTS(Clear to Send) 是串行通信中的硬件流控信号,用于管理数据流量
RTS信号由发送方控制,用于通知接收方“我准备好发送数据了”。当发送方的数据准备就绪时,会将RTS信号拉高(或拉低,具体取决于硬件逻辑),以请求对方允许发送
CTS信号由接收方控制,用于通知发送方“我已准备好接收数据”。只有在接收方拉高(或拉低)CTS信号后,发送方才会开始传输数据

在以下场景中,RTS、CTS 可以不接(可能存在问题)
1.设备之间的通信不使用硬件流控
2.传输的数据量较小或通信速率较低,不接RTS/CTS通常不会引起问题,因为接收方有足够时间处理数据
3.接收设备有足够大的缓冲区
4.通信是单向的

如果为 UART 信号配置的 GPIO 编号与该 GPIO 的 IOMUX 信号之一匹配,那么信号将通过 IOMUX 直接连接。否则,GPIO 和信号将通过 GPIO 矩阵(GPIO Matrix)连接
例如,在 ESP32 上,如果调用 uart_set_pin(0, 1, 3, -1, -1),由于 GPIO1 是 UART0 的默认 TX 引脚,而 GPIO3 是 UART0 的默认 RX 引脚,这两个引脚将分别通过 IOMUX 直接连接到 U0TXD 和 U0RXD,完全绕过 GPIO 矩阵
这种检查是逐引脚进行的。因此,可以实现如下情况:RX 引脚通过 GPIO 矩阵绑定到一个 GPIO,而 TX 引脚则通过 IOMUX 绑定到其默认的 GPIO

IOMUX 是嵌入式芯片中管理 GPIO 功能的重要工具,负责在多个功能之间选择最合适的信号连接方式。它通过直接映射机制,在固定的引脚上提供高效的信号传输,但在灵活性上略逊于 GPIO Matrix
GPIO Matrix 是嵌入式系统中的一种硬件抽象机制,用于将芯片内部的外设信号映射到任意的 GPIO 引脚上。它通过一个矩阵式的硬件逻辑层,允许开发者灵活地配置信号和引脚之间的关系,而不受固定引脚的限制

可以将TX和RX配置为共享同一个IO引脚(单线模式),但需要注意输出冲突的问题,这可能会损坏引脚。为保护引脚,应提前对其应用开漏配置和上拉电阻,或者由上层协议确保不会出现两端同时输出的情况

返回值
ESP_FAIL 参数错误
ESP_OK 成功

Install Drivers

通信管脚设置完成后,调用 uart_driver_install() 安装驱动程序并指定以下参数

  • UART 控制器编号
  • Tx 环形缓冲区的大小 - 指定用于存储 UART 发送数据的环形缓冲区的大小(以字节为单位)
  • Rx 环形缓冲区的大小 - 指定用于存储 UART 接收数据的环形缓冲区的大小(以字节为单位)
  • 指向事件队列句柄的指针 - 用于指向事件队列(Event Queue)的句柄指针
  • 事件队列大小 - 指定事件队列中可以存储的最大事件数
  • 分配中断的标志 - 用于指定是否为 UART 分配硬件中断,以及中断的相关设置

环形缓冲区是一种循环队列,支持高效的数据流管理,因为其结构允许在数据未完全发送完的情况下继续写入新数据
环形缓冲区过小:可能导致数据等待区满,无法及时写入新数据。
环形缓冲区过大:占用内存资源

Tx 环形缓冲区:数据被写入缓冲区后,UART 硬件会从中取出数据并逐字节发送
Rx 环形缓冲区:接收的数据会先存储到这个缓冲区中,供程序按需读取

uart_driver_install()

安装 UART 驱动程序

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

参数
uart_num UART 端口号
rx_buffer_size Rx 环形缓冲区大小
tx_buffer_size Tx 环形缓冲区大小
queue_size UART 事件队列大小
uart_queue 事件队列句柄,成功后,这里会编写一个新的队列句柄,以提供对 UART 事件的访问;若设置为 NULL,驱动程序将不使用事件队列,此时 queue_size 的值会被忽略
intr_alloc_flags 用于分配中断的标志,用于配置 UART 驱动的中断行为

UART 驱动的中断行为是指 UART 硬件模块通过中断机制向处理器发出信号,以通知某些事件的发生(例如数据接收完成、发送缓冲区空等)。中断行为是 UART 驱动的重要特性之一,用于提高通信效率和实时性,避免 CPU 频繁轮询设备状态

返回值
ESP_FAIL 参数错误
ESP_OK 成功

Run UART Communication

串行通信由每个 UART 控制器的有限状态机 (FSM) 控制

UART 控制器的有限状态机(FSM, Finite State Machine) 是 UART 硬件模块内部用于管理数据收发过程的逻辑机制。FSM 是一种基于状态转换的逻辑模型,它通过状态和状态间的转换规则,实现对复杂操作的高效管理。UART 控制器的 FSM 在发送和接收数据时会根据当前状态和输入条件进行动态切换,以确保通信的可靠性和正确性

发送数据的过程分为以下步骤:

  1. 将数据写入 Tx FIFO 缓冲区(First In, First Out(先进先出))
  2. FSM 序列化数据
  3. FSM 发送数据

接收数据的过程类似,只是步骤相反:

  1. FSM 处理且并行化传入的串行流
  2. FSM 将数据写入 Rx FIFO 缓冲区
  3. 从 Rx FIFO 缓冲区读取数据

因此,应用程序仅会通过 uart_write_bytes()uart_read_bytes() 从特定缓冲区写入或读取数据,其余工作由 FSM 完成

Transmit Data

uart_write_bytes()

从给定的缓冲区和长度向 UART 端口发送数据
如果 UART 驱动程序的参数“tx_buffer_size”设置为零,在所有数据都发送出去或至少推入 Tx FIFO 之前,此函数不会返回
如果“tx_buffer_size”>0,此函数将在将所有数据复制到 Tx 环形缓冲区后返回,UART ISR 将逐渐将数据从环形缓冲区移动到 Tx FIFO

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

参数
uart_num UART 端口号
src 数据缓冲区地址
size 发送的数据长度

返回值
-1 参数错误
其它值 推送到 TX FIFO 的字节数

uart_write_bytes_with_break()

该函数从给定的缓冲区和长度向 UART 端口发送数据
如果 UART 驱动程序的参数“tx_buffer_size”设置为零,在所有数据和中断信号发出之前,此函数不会返回。所有数据发出后,发送中断信号
如果“tx_buffer_size”>0,此函数将在将所有数据复制到 Tx 环形缓冲区后返回,UART ISR 将逐渐将数据从环形缓冲区移动到 Tx FIFO。所有数据发出后,发送中断信号

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

参数
uart_num UART 端口号
src 数据缓冲区地址
size 发送的数据长度
brk_len 中断信号持续时间(单位:以当前波特率发送一个比特所需的时间)

参数 brk_len 的作用是指定在发送完数据后生成的 BREAK 信号的长度。BREAK 信号是串行通信协议中用来指示通信线路的异常状态或特殊条件的一种信号:
BREAK 信号是一种特殊的状态,指通信线路(TX 引脚)被拉低到逻辑 0,并保持比正常帧的停止位更长的时间,可以用来指示通信异常、同步主从设备或标识数据帧结束

返回值
-1 参数错误
其它值 推送到 TX FIFO 的字节数

uart_tx_chars()

将给定缓冲区中的数据发送到指定的 UART 端口

  • 本函数不等待 TX FIFO 缓冲区有足够空间,而是将尽可能多的数据填充到可用的 TX FIFO 中,并在缓冲区满时立即返回
int uart_tx_chars(uart_port_t uart_num,const char *buffer,uint32_t len)

参数
uart_num UART 端口号
buffer 数据缓冲区地址
len 要发送的数据长度(字节数)

返回值
-1 参数错误
其它值 推送到 TX FIFO 的字节数

uart_wait_tx_done()

等待UART TX FIFO为空

esp_err_t uart_wait_tx_done(uart_port_t uart_num,TickType_t ticks_to_wait)

参数
uart_num UART 端口号
ticks_to_wait 等待时间,以RTOS节拍为单位计数

返回值
ESP_FAIL 参数错误
ESP_OK 成功
ESP_ERR_TIMEOUT 超时

Receive Data

一旦 UART 接收了数据,并将其保存在 Rx FIFO 缓冲区中,就需要使用函数 uart_read_bytes() 检索数据

uart_read_bytes()

从 UART 缓冲区读取字节

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

参数
uart_num UART 端口号
buf 指向缓冲区的指针
length 数据长度
ticks_to_wait 等待时间,以 RTOS 节拍为单位计数

返回值
-1 错误
其它值 从缓冲区读取到的字节数

uart_get_buffered_data_len()

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

esp_err_t uart_get_buffered_data_len(uart_port_t uart_num,size_t *size)

参数
uart_num UART 端口号
size 指向用于存储 size 值的空间的指针

返回值
ESP_FAIL 参数错误
ESP_OK 成功将结果写入 size

uart_flush()

UART 环形缓冲区刷新,将丢弃 UART RX 缓冲区中的所有数据

esp_err_t uart_flush(uart_port_t uart_num)

参数
uart_num UART 端口号

返回值
ESP_FAIL 参数错误
ESP_OK 成功


Use Interrupts
这部分涉及内容较多且复杂,待后续整理


Delete a Driver

uart_driver_delete()

卸载 UART 驱动程序

esp_err_t uart_driver_delete(uart_port_t uart_num)

参数
uart_num UART 端口号

返回值
ESP_FAIL 参数错误
ESP_OK 成功

Check for Errors

ESP_ERROR_CHECK()

ESP_ERROR_CHECK 是 ESP-IDF(Espressif IoT Development Framework)提供的一个宏,用于检查函数的返回值是否表示成功。如果返回值不是 ESP_OK(表示无错误),ESP_ERROR_CHECK 会打印出错误信息并终止程序的执行
示例:

ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));

工作原理

  1. 宏接收一个表达式 x,通常是一个函数调用
  2. 执行该表达式,并将其返回值存储在临时变量 __err_rc
  3. 检查返回值是否等于 ESP_OK
    • 如果等于 ESP_OK
      • 无任何动作,继续执行程序。
    • 如果不等于 ESP_OK
      • 打印错误日志,包括返回值(错误代码)
      • 调用 abort() 函数终止程序(适用于调试阶段)

Example Code:UART Communication Task

这里是一个使用UART1与外部设备进行通信的例子,GPIO16和17连接到了一个4G通信模块,模块上已经配置好了和华为云IoTDA进行通信的配置。
通过串口透传,4G模块能够将所有通过串口发送给它的数据直接发送到IotDA,并从IoTDA接受数据,再发送至单片机

有关 FreeRTOS 的部分详见 ESP32专栏

/*  * Author: Lamonce * Date: 2024-11-28 * Description: Test uart1 */  #include <stdio.h>  
#include "freertos/FreeRTOS.h"  
#include "freertos/task.h"  
#include "driver/uart.h" // 串口驱动  
#include "driver/gpio.h" // GPIO驱动  
#include "esp_log.h"     // 日志  
#include "sdkconfig.h"   // 配置  
#include <string.h>      // 字符串  #define UART_1_TX_PIN 17  
#define UART_1_RX_PIN 16  
#define UART_1_BAUDRATE 115200 // 波特率115200  #define BUF_SIZE 1024 * 2  void uartInit1(void)  
{  uart_config_t uart_config = {  .baud_rate = UART_1_BAUDRATE,  .data_bits = UART_DATA_8_BITS,  .parity = UART_PARITY_DISABLE,  .stop_bits = UART_STOP_BITS_1,  .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,  .rx_flow_ctrl_thresh = 0, // 由于关闭了硬件流控,所以阈值设置为0  };  // 配置串口,使用ESP_ERROR_CHECK来检查错误  ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));                                                    // 配置串口参数  ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, UART_1_TX_PIN, UART_1_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); // 设置串口引脚,不使用硬件流控,因此cts和rts引脚都设置为UART_PIN_NO_CHANGE  ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE, BUF_SIZE, 0, NULL, 0));                                // 安装串口驱动,缓冲区大小为BUF_SIZE,事件回调函数为NULL,事件标志为0,表示不使用事件  
}  void uartTest1(void *pvParameters)  
{  uartInit1();  char *receiveData = (char *)pvParameters;  char *sendData = "Hello, Lamonce!";  while (1)  {  uart_write_bytes(UART_NUM_1, sendData, strlen(sendData)); // 发送数据  ESP_LOGI("UART_1", "Sent %d bytes: %s", strlen(sendData), sendData); // 日志打印发送的数据  vTaskDelay(pdMS_TO_TICKS(5000)); // 延时5秒  size_t len;  if (uart_get_buffered_data_len(UART_NUM_1, &len) == ESP_OK && len > 0)  {  len = (len < BUF_SIZE - 1) ? len : BUF_SIZE - 1; // 判断数据长度是否大于缓冲区大小减1,如果是,则根据缓冲区大小减1读取数据  uart_read_bytes(UART_NUM_1, receiveData, len, pdMS_TO_TICKS(5000)); // 读取数据,最大等待时间为5000ms  receiveData[len] = '\0';// 添加字符串结束符  ESP_LOGI("UART_1", "Received %d bytes: %s", len, receiveData); // 日志打印接收到的数据  }  else  {  ESP_LOGI("UART_1", "No data received"); // 日志打印没有数据接收  }  }  
}  TaskHandle_t uartTest1TaskHandle;  void app_main(void)  
{  char *receiveData = (char *)malloc(BUF_SIZE); // 存储数据  xTaskCreate(uartTest1, "uartTest1", 1024 * 5, (void *)receiveData, 5, &uartTest1TaskHandle);  
}

由于在测试代码中没有设置上传topic,因此IoTDA在读取上传的数据时会有格式问题,但是我们仍旧能从下图中看出我们想要发送的数据是什么
在这里插入图片描述
这里我以“Audio”命令下发了一条数据,从日志中可以看到,数据成功被ESP32收到
在这里插入图片描述

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

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

相关文章

UE5 实现组合键触发事件的方法

因为工作原因。 需要用大括号{和}来触发事件 但是在蓝图中搜了一下&#xff0c;发现键盘事件里根本就没有{}这两个键。 花费了一下午&#xff0c;终于找到解决的方法了&#xff0c;也就是增强输入的弦操作 首先创建一个项目 纯蓝图或者C都可行 进入到内容浏览器的默认页面 …

富文本编辑器图片上传并回显

1.概述 在代码业务需求中&#xff0c;我们会经常涉及到文件上传的功能&#xff0c;通常来说&#xff0c;我们存储文件是不能直接存储到数 据库中的&#xff0c;而是以文件路径存储到数据库中&#xff1b;但是存储文件的路径到数据库中又会有一定的问题&#xff0c;就是 浏览…

JVM指令集概览:基础与应用

写在文章开头 在现代软件开发中,Java 语言凭借其“一次编写,到处运行”的理念成为了企业级应用的首选之一。这一理念的背后支撑技术正是 Java 虚拟机(JVM)。JVM 是一个抽象的计算机,它实现了 Java 编程语言的各种特性,并且能够执行编译后的字节码文件。了解 JVM 的工作原…

麒麟系统x86安装达梦数据库

一、安装准备前工作 操作系统&#xff1a;银河麒麟V10&#xff0c;CPU&#xff1a; x86_64 架构 下载地址&#xff0c;麒麟官网&#xff1a;https://www.kylinos.cn/ 数据库&#xff1a;dm8_20220915_x86_kylin10_64 下载地址&#xff0c;达梦数据库官网&#xff1a;https://…

力扣 二叉树的中序遍历

用了递归遍历&#xff0c;关于树的经典例题。 题目 递归 常规做法即递归了&#xff0c;不会写也得背下来。递归可以大致理解方法调用自身&#xff0c;先写中序遍历递归的方法&#xff0c;递归一定要有递归出口&#xff0c;当遍历到节点为空时返回&#xff0c;即已经找到了。…

windows server 2019 启动 nginx 报错

环境 &#xff1a;windows server 2019 &#xff0c;nginx-1.19.7 背景&#xff1a; 自己经常用这个 nginx 包作为 web 服务器。今天发现 部署到 server 2019 上直接报错了。这可是原生的包&#xff0c;我啥也没改&#xff0c;怎么可能报错。而且之前在 其他服务器用都没问题…

python代码示例(读取excel文件,自动播放音频)

目录 python 操作excel 表结构 安装第三方库 代码 自动播放音频 介绍 安装第三方库 代码 python 操作excel 表结构 求出100班同学的平均分 安装第三方库 因为这里的表结构是.xlsx文件,需要使用openpyxl库 如果是.xls格式文件,需要使用xlrd库 pip install openpyxl /…

百度智能云发布首个空间智能解决方案,百度AI优势如何分析?

首先&#xff0c;百度智能云此次推出的空间智能解决方案&#xff0c;在技术底座上展现了其强大的AI异构计算能力。百度百舸AI异构计算平台作为该方案的底层支撑&#xff0c;为2D和3D应用中的人物、物件及场景生成提供了强大的算力支持。这一平台的推出&#xff0c;不仅提升了空…

深度学习-49-AI应用实战之基于HyperLPR的车牌识别

文章目录 1 车牌识别系统1.1 识别原理1.1.1 车牌定位1.1.2 字符识别2 实例应用2.1 安装hyperlpr32.2 识别结果2.3 可视化显示2.4 结合streamlit3 附录3.1 PIL.Image转换成OpenCV格式3.2 OpenCV转换成PIL.Image格式3.3 st.image嵌入图像内容3.4 参考附录1 车牌识别系统 车牌识别…

非递归遍历二叉树(数据结构)

我的博客主页 非递归遍历二叉树 前序遍历&#xff08;迭代&#xff09;中序遍历&#xff08;迭代&#xff09;后续遍历&#xff08;迭代&#xff09; 二叉树的遍历方式有&#xff1a;前序遍历、中序遍历、后续遍历&#xff0c;层序遍历&#xff0c;而树的大部分情况下都是通过递…

丹摩征文活动|实现Llama3.1大模型的本地部署

文章目录 1.前言2.丹摩的配置3.Llama3.1的本地配置4. 最终界面 丹摩 1.前言 Llama3.1是Meta 公司发布的最新开源大型语言模型&#xff0c;相较于之前的版本&#xff0c;它在规模和功能上实现了显著提升&#xff0c;尤其是最大的 4050亿参数版本&#xff0c;成为开源社区中非常…

基于stm32单片机的教室节能系统设计

功能描述 0. STM32F103C8T6单片机为控制核心 1. OLED液晶显示当前年 月 日 时 分 秒 星期 2. 按键可以设置定时时间 3. 按键可以设置用电开关的开启和关闭时间&#xff0c;实现设备的节能 4. 通过红外遥控可以打开关闭空调设备&#xff08;通过继电器开关闭合模拟&#x…

防止按钮被频繁点击

在做开发的时候,不希望按钮被用户频繁点击,给后端服务器增加负担,这个时候,可以在按钮的触发函数加上如下代码: // 禁用按钮 const fetchButton document.querySelector(.btn-fetch); fetchButton.disabled true; // 延时61秒后重新启用按钮 setTimeout(() > { fetchBut…

Spring Boot【三】

自动注入 xml中可以在bean元素中通过autowire属性来设置自动注入的方式&#xff1a; <bean id"" class"" autowire"byType|byName|constructor|default" /> byName&#xff1a;按照名称进行注入 byType&#xff1a;按类型进行注入 constr…

构建 LLM (大型语言模型)应用程序——从入门到精通(第七部分:开源 RAG)

通过检索增强生成 (RAG) 应用程序的视角学习大型语言模型 (LLM)。 本系列博文 简介数据准备句子转换器矢量数据库搜索与检索大语言模型开源 RAG&#xff08;本帖&#xff09;评估服务LLM高级 RAG 1. 简介 我们之前的博客文章广泛探讨了大型语言模型 (LLM)&#xff0c;涵盖了其…

【Python入门】Python数据类型

文章一览 前言一、变量1.1.如何使用变量1.2.如何定义变量的名字&#xff08;标识符&#xff09; 二、数据类型2.1 整型数据2.2 浮点型数据2.3 布尔型&#xff08;bool&#xff09;数据2.4 复数型数据2.5 字符串类型1 > 字符串相加&#xff08;合并&#xff09;&#xff08;&…

第1章-JVM和Java体系架构

虚拟机 虚拟机概念 所谓虚拟机&#xff08;Virtual Machine&#xff09;&#xff0c;就是一台虚拟的计算机。它是一款软件&#xff0c;用来执行一系列虚拟计算机指令。大体上&#xff0c;虚拟机可以分为系统虚拟机和程序虚拟机。 大名鼎鼎的Virtual Box&#xff0c;VMware就属…

【H2O2|全栈】Node.js(2)

目录 前言 开篇语 准备工作 npm 概念 常见指令 项目中的包 创建项目 启动项目 服务器搭建 express 基本步骤 搭建应用 创建路由 监听端口 启动服务器 面试相关 结束语 前言 开篇语 本系列博客分享Node.js的相关知识点&#xff0c;本章讲解npm与服务器的简单…

JDK的版本演化,JDK要收费吗?

Java版本演化历史 Java的版本历史可以追溯到1995年&#xff0c;以下是Java语言自诞生以来的主要版本及其关键特性&#xff1a; 一、早期版本 Java 1.0&#xff08;1996年1月发布&#xff09; 引入了Java虚拟机&#xff08;JVM&#xff09;和Java应用编程接口&#xff08;API&…

书生大模型实训营第4期进阶岛第三关:LMDeploy 量化部署进阶实践

书生大模型实训营第4期进阶岛第三关&#xff1a;LMDeploy 量化部署进阶实践 1. 配置 LMDeploy 环境1.1 开发机的创建与环境搭建1.2 模型获取1.3 模型测试 2. InternLM2.5 的部署与量化2.1 LMDeploy API 部署 InternLM2.52.1.1 启动API服务器2.1.2 以命令行形式连接 API 服务器2…