USART 串口通信全解析:原理、结构与代码实战

article/2025/8/11 12:52:34

文章目录

    • USART
      • USART简介
      • USART框图
      • USART基本结构
      • 数据帧
      • 起始位侦测
      • 数据采样
      • 波特率发生器
      • 串口发送数据 主要代码
      • 串口接收数据与发送数据主要代码

USART

USART简介

一、USART 的全称与基本定义

  1. 英文全称
    • USARTUniversal Synchronous Asynchronous Receiver Transmitter,即 通用同步异步收发器
    • 核心功能:实现串行通信,支持 同步通信(需时钟信号)和 异步通信(无需时钟信号,依赖波特率同步)。
  2. 与 UART 的本质区别
    • UARTUniversal Asynchronous Receiver Transmitter,即 通用异步收发器仅支持异步通信
    • 关键差异
      • USART 比 UART 多一个 同步时钟输出功能(对应引脚 CLK),可在通信中提供时钟信号。
      • 实际应用中,由于串口通信极少使用同步模式,USART 与 UART 在异步模式下可视为等价,硬件驱动和配置流程基本一致。

二、USART 的核心功能特性

  1. 通信模式灵活切换
    • 异步模式(常用):
      • 无需时钟信号,通信双方通过 波特率 约定数据传输速率。
      • 数据帧包含 起始位、数据位、校验位(可选)、停止位,通过 TX/RX 引脚完成收发。
    • 同步模式(少用):
      • 通过 CLK 引脚输出时钟信号,用于同步发送方和接收方的时序。
      • 时钟频率与波特率一致,可兼容 SPI 等需要时钟的协议,但 仅支持时钟输出,不支持输入,因此 无法实现两个 USART 设备间的同步通信
  2. 硬件自动化处理
    • 数据帧生成与解析
      • 发送时,自动将数据寄存器(TDR)中的字节转换为符合协议的波形(如添加起始位、停止位),通过 TX 引脚输出。
      • 接收时,自动从 RX 引脚读取波形,按协议解析为字节数据存入接收寄存器(RDR)。
    • 双缓存机制
      • 发送端:TDR(写缓冲)与发送移位寄存器配合,允许连续写入数据,提升传输效率。
      • 接收端:RDR(读缓冲)与接收移位寄存器配合,避免数据丢失。
  3. 可配置参数
    • 波特率:最高支持 4.5 Mbps,通过内部波特率发生器(分频器)配置。
    • 数据位长度:8 位(无校验)或 9 位(含 1 位奇偶校验位)。
    • 停止位长度:0.5/1/1.5/2 位,常用 1 位。
    • 校验方式:无校验、奇校验、偶校验。

在这里插入图片描述

USART框图

  1. 数据传输路径
    • 发送路径:CPU 或 DMA 将数据写入发送数据寄存器(TDR) ,TDR 的数据转移至发送移位寄存器,然后在发送器控制的作用下(这里是向右移位的与串口输出的低位先行是一致的),通过 TX 引脚逐位发送出去。在此过程中,发送数据寄存器(TDR)起到缓冲作用,允许 CPU 或 DMA 在发送移位寄存器工作时写入下一个数据。当数据转移至移位寄存器中会置标志位 TXE 发送寄存器空,就可以将数据写入寄存器。
    • 接收路径:RX 引脚接收到的数据进入接收移位寄存器,将数据先放在最高位然后向右移位(也是符合串口通信低位先行的原则),当接收移位寄存器接收到完整的数据字节后,数据被转移到接收数据寄存器(RDR),在接收数据过程中,也是会置标志位,接收寄存器非空RXNE,当检测到该标志位后, CPU 或 DMA 可以进行读取。
  2. 寄存器功能
    • 数据寄存器(DR):实际包含发送数据寄存器(TDR)和接收数据寄存器(RDR),对 DR 进行写操作时数据存入 TDR,进行读操作时从 RDR 读取数据,也就是两个寄存器占据一块空间。
    • 状态寄存器(SR) :包含多个标志位,如 TXE(发送寄存器空)、TC(发送完成)、RXNE(接收寄存器非空)、IDLE(总线空闲) 、ORE(溢出错误)、NE(噪声错误)、FE(帧错误)、PE(奇偶校验错误)等,用于反映 USART 的工作状态,方便软件判断何时进行数据发送、接收以及检测通信错误 。
    • 波特率寄存器(BRR) :用于设置波特率,其值决定了发送器和接收器的波特率时钟。计算公式为 USARTDIV = DIV_Mantissa + (DIV_Fraction / 16) ,通过设置 DIV_Mantissa(整数部分)和 DIV_Fraction(小数部分)来得到所需的波特率分频值 。
    • 控制寄存器(CR1 - CR3) :CR1 用于控制 USART 的基本功能,如使能发送(TE)、接收(RE) ,奇偶校验(PCE、PS、PE),唤醒功能(WAKE)等;CR2 用于控制停止位(STOP [1:0])、时钟使能(CKEN)等;CR3 用于控制硬件流控(CTSE、RTSE)、智能卡模式(SCEN)等功能 。
  3. 控制单元
    • 发送器控制:根据控制寄存器(如 CR1 中的 TE 位)的配置来控制发送移位寄存器的工作,决定何时将 TDR 的数据转移到发送移位寄存器并进行发送,同时参与波特率控制相关操作 。
    • 接收器控制:负责管理接收移位寄存器的工作,包括起始位侦测、数据采样等操作。通过对 RX 引脚的信号以波特率 16 倍频率采样来侦测起始位,然后逐位接收数据并转移到 RDR 。同时,还具备噪声过滤等功能,通过三次采样投票机制(2:1 规则)判断有效数据,若采样不一致则置 NE 标志位 (说明有噪声干扰)。
    • 硬件数据流控:如果发送数据太快,接收设备来不及处理就会出现数据丢失或覆盖的现象,可以通过 nRTS(请求发送 Request to send)和 nCTS(清除发送 clear to send)引脚实现硬件流控。当接收方接收缓冲区快满时,通过 nRTS 引脚通知发送方暂停发送,发送方根据 nCTS 引脚状态判断是否可以继续发送,以此避免数据丢失 。接收方的nRTS 与 发送方的 nCTS相连接,也就是这两个引脚相互连接。置高电平说明会产生信号,nRTS就是停止发送。
    • 中断控制:根据状态寄存器(SR)中的标志位状态来触发中断,如 TXE、RXNE、NE 等标志位置 1 时,可触发相应中断,使 CPU 能够及时响应并处理 USART 相关事件,如读取接收数据、写入新的发送数据或处理通信错误等 。
  4. 时钟相关
    • 时钟来源:USART1 时钟来自 APB2 总线时钟(PCLK2),USART2 和 USART3 时钟来自 APB1 总线时钟(PCLK1) 。
    • 波特率时钟生成:时钟经过波特率发生器(由 BRR 寄存器配置)进行分频,得到发送器和接收器的波特率时钟。发送器波特率控制和接收器波特率控制分别根据 BRR 寄存器的值生成相应的时钟信号,确保发送和接收数据的速率符合设定的波特率 。
    • 同步时钟(SCLK) :在同步模式下,SCLK 引脚输出同步时钟信号,其频率与波特率一致(发送寄存器每移位一次,同步时钟就跳变一个周期)。同步时钟信号由 SCLK 控制模块根据相关配置(如 CR2 中的时钟控制位)生成,用于为同步通信提供时钟基准,如在与 SPI 等协议兼容通信时发挥作用 和 做自适应波特率。
  5. 其他功能模块
    • IrDA 编码解码模块:用于红外数据通信(IrDA 模式),对发送数据进行编码后通过 IrDA_OUT 引脚发送,对 IrDA_IN 引脚接收到的信号进行解码后送入接收路径 。
    • 唤醒单元:配合多设备通信场景,可根据配置的 USART 地址,在接收到特定地址的信号时唤醒 USART 设备,使其进入工作状态,实现类似 I2C 的多主机通信机制 。

在这里插入图片描述

USART基本结构

USART 基本结构

  • 波特率发生器:位于最左边,用于产生约定的通信数据。
  • 时钟单元:由 PCLK2 或经过分频后产生,为发送和接收控制器提供时钟,控制发送和接收移位。
  • 发送部分:发送数据寄存器和发送移位寄存器配合,将数据一位一位右移(低位先行),通过 GPIO 口复用输出到 TX 引脚,产生规定波形,数据转移时置 TXE 标志位。
  • 接收部分:RX 引脚波形通过 GPIO 口输入,在接收控制器控制下,数据右移(低位先行)进入接收移位寄存器,移完一帧后转运到接收数据寄存器,转移时置 RXNE 标志位,该标志位可用于判断是否收到数据及申请中断。
  • 寄存器:右边实际有 4 个寄存器,软件层面只有 Dr 寄存器可读写,写入 Dr 走发送路径,读取 Dr 走接收路径。
  • 开关控制:配置完成后用 CMD 开启外设。

在这里插入图片描述

数据帧

一、字长与校验位选择

  • 9 位字长
    • 结构为 “1 位起始位 + 8 位数据位 + 1 位校验位 + 停止位(自定义长度)”。
    • 校验位可配置为奇校验或偶校验,用于检测数据传输中的错误。
  • 8 位字长
    • 结构为 “1 位起始位 + 8 位数据位 + 停止位(自定义长度)”。
    • 无校验位,每帧有效载荷为完整的 8 位(1 字节),适用于一般数据传输场景,可提升传输效率,避免因校验位导致的额外开销。

二、同步时钟作用

  • 功能:在同步模式下,USART 通过 CLK 引脚输出同步时钟信号,该信号在每个数据位的中间位置产生上升沿。
  • 意义:接收端可利用此时钟信号精准采样数据位,确保数据接收的准确性,尤其适用于与外部设备(如模拟 SPI 从设备)的同步通信。
  • 配置:时钟极性(CPIO,空闲时电平状态)和相位(CPHA,采样时刻)可通过寄存器配置,以适配不同协议的时序要求。

三、特殊数据帧

  • 空闲帧(Idle Frame)
    • 定义:整个数据帧的波形从头到尾均为高电平(逻辑 1)。
    • 用途:用于局域网(LIN)等协议中,表示总线空闲状态,通知从设备准备接收后续数据。
    • 串口应用:在普通串口通信中极少使用。
  • 断开帧(Break Frame)
    • 定义:整个数据帧的波形从头到尾均为低电平(逻辑 0)。
    • 用途:用于局域网协议中,通常作为一种特殊的控制信号,打断当前通信流程或唤醒从设备。
    • 串口应用:在普通串口通信中极少使用。

四、停止位波形变化

  • 配置选项:STM32 的 USART 可配置停止位长度为 0.5 位、1 位、1.5 位或 2 位。
  • 波形时长
    • 停止位的波形时长与波特率相关,例如波特率为 9600 bps 时,1 位停止位的时长为 96001≈104.17μs,0.5 位则约为 52.08μs
  • 常用选择:实际应用中,1 位停止位最为常用,因其兼容性好,适用于大多数串口设备(如 PC 端串口助手、传感器模块等)。

五、数据帧整体作用

  • 数据帧是 USART 通信的基本单元,通过定义起始位、数据位、校验位(可选)、停止位的组合,确保收发双方在异步通信中实现时序同步,避免数据错位或丢失。
  • 不同的帧格式(如 8 位无校验、9 位带校验)和停止位配置,为开发者提供了灵活的选择,可根据具体应用场景(如工业控制的高可靠性需求、普通调试信息传输的高效性需求)优化通信参数。

起始位侦测

  • 频采样机制:接收端以波特率 16 倍的频率对 RX 引脚进行采样,这种高频采样有助于精确捕捉信号变化,为起始位检测提供基础。
  • 起始位下降沿侦测:当检测到 RX 引脚出现下降沿(从高电平跳变到低电平)时,初步判断可能是起始位的开始。
  • 多次采样确认:在侦测到下降沿后,通过连续多批次采样进一步判断。若后续采样持续检测到低电平,则确认该下降沿为真正的起始位;若采样结果不一致,则借助噪声处理机制判断。
  • 噪声处理:采用三次采样投票机制(2:1 规则),即连续三次采样中,若两次结果相同则判定为有效电平。若采样过程中出现噪声导致不一致,会置位噪声标志位(NE),但不影响正常数据接收,仅作为提示。

在这里插入图片描述

数据采样

采样位置对齐:起始位侦测通过后,接收状态机发生改变,调整后续采样的时间点,使采样位置精确对齐数据位的中心,确保后续数据位采样的准确性。

在这里插入图片描述

波特率发生器

一、定义与核心功能

波特率发生器是 USART(通用同步异步收发器)的关键模块,用于生成数据发送与接收的时钟信号,决定数据位的传输速率(波特率),确保收发双方在串行通信中时序同步,避免数据错位或乱码。

二、输入时钟来源

  • USART1:挂载于 APB2 总线,输入时钟为 PCLK2(通常为 72 MHz)。
  • USART2/3:挂载于 APB1 总线,输入时钟为 PCLK1(通常为 36 MHz)。

三、波特率计算原理
在这里插入图片描述

四、寄存器配置

  • BRR 寄存器:存储分频系数 DIV,分为整数部分(BRR[15:4])和小数部分(BRR[3:0])。通过配置该寄存器,可灵活调整波特率。

五、对通信的影响

  • 若波特率设置错误,收发双方时序不匹配,会导致数据接收错误(如乱码)。
  • 在同步模式下,波特率发生器还控制同步时钟(SCLK)的频率,使其与波特率一致,确保数据与时钟信号同步输出。

串口发送数据 主要代码

// Serial.c USART模块主要代码#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
void Serial_Init(void)
{//1.开启时钟 //开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//初始化gpioinit参数中的结构体GPIO_InitTypeDef GPIO_InitStructure;//将gpio口设置为推挽输出,因为非工作模式默认为高电平,所以配置为上拉GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//初始化发送引脚 9号引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitTypeDef USART_InitStruct;//要配置的波特率USART_InitStruct.USART_BaudRate = 9600;//有没有启动硬件数据流控USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//模式输出模式USART_InitStruct.USART_Mode = USART_Mode_Tx;//奇偶校验位USART_InitStruct.USART_Parity = USART_Parity_No;//停止位USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);//开始USART1的总开关USART_Cmd(USART1, ENABLE);
}//封装发送数据的函数
void Serial_SendBtye(uint8_t byte)
{USART_SendData(USART1, byte);//等待数据发送完成,读取标志位while( USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//标志位置一之后不需要手动清零,进行写操作会自动清零}
void Serial_SendArray(uint8_t *Array, uint8_t length)
{uint8_t i;for(i = 0; i < length; i++){Serial_SendBtye(Array[i]);}
}void Serial_SendString(char *string)
{for(uint8_t i = 0; string[i] != '\0'; i++){Serial_SendBtye(string[i]);}
}
uint32_t Pow(uint8_t x, uint8_t y)
{uint32_t result = 1;while(y--){result *= x;}return result;
}
void Serial_SendNum(uint32_t Number, uint8_t length)
{for(uint8_t i = 0; i < length; i++){Serial_SendBtye(Number / Pow(10, length - i - 1) % 10 + '0');}
}
/*** 函    数:使用printf需要重定向的底层函数* 参    数:保持原始格式即可,无需变动* 返 回 值:保持原始格式即可,无需变动*/
int fputc(int ch, FILE *f)
{Serial_SendBtye(ch);			//将printf的底层重定向到自己的发送字节函数return ch;
}
/*** 函    数:自己封装的prinf函数* 参    数:format 格式化字符串* 参    数:... 可变的参数列表* 返 回 值:无*/
void Serial_Printf(char *format, ...)
{char String[100];				//定义字符数组va_list arg;					//定义可变参数列表数据类型的变量argva_start(arg, format);			//从format开始,接收参数列表到arg变量vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中va_end(arg);					//结束变量argSerial_SendString(String);		//串口发送字符数组(字符串)
}

串口接收数据与发送数据主要代码

//Serial.c USART模块主要代码#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>int Serial_Data;
int Serial_flag;
void Serial_Init(void)
{//1.开启时钟 //开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//初始化gpioinit参数中的结构体GPIO_InitTypeDef GPIO_InitStructure;//将gpio口设置为推挽输出,因为非工作模式默认为高电平,所以配置为上拉GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//初始化发送引脚 9号引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//接收数据初始化 10号引脚 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//初始化发送引脚 9号引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;USART_InitTypeDef USART_InitStruct;//要配置的波特率USART_InitStruct.USART_BaudRate = 9600;//有没有启动硬件数据流控USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//模式输出模式USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//奇偶校验位USART_InitStruct.USART_Parity = USART_Parity_No;//停止位USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);//如果想要使用中断,就开启中断,然后配置NVICUSART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//先设置中断分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);//开始USART1的总开关USART_Cmd(USART1, ENABLE);
}//封装发送数据的函数
void Serial_SendBtye(uint8_t byte)
{USART_SendData(USART1, byte);//等待数据发送完成,读取标志位while( USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//标志位置一之后不需要手动清零,进行写操作会自动清零}
void Serial_SendArray(uint8_t *Array, uint8_t length)
{uint8_t i;for(i = 0; i < length; i++){Serial_SendBtye(Array[i]);}
}void Serial_SendString(char *string)
{for(uint8_t i = 0; string[i] != '\0'; i++){Serial_SendBtye(string[i]);}
}
uint32_t Pow(uint8_t x, uint8_t y)
{uint32_t result = 1;while(y--){result *= x;}return result;
}
void Serial_SendNum(uint32_t Number, uint8_t length)
{for(uint8_t i = 0; i < length; i++){Serial_SendBtye(Number / Pow(10, length - i - 1) % 10 + '0');}
}
/*** 函    数:使用printf需要重定向的底层函数* 参    数:保持原始格式即可,无需变动* 返 回 值:保持原始格式即可,无需变动*/
int fputc(int ch, FILE *f)
{Serial_SendBtye(ch);			//将printf的底层重定向到自己的发送字节函数return ch;
}
/*** 函    数:自己封装的prinf函数* 参    数:format 格式化字符串* 参    数:... 可变的参数列表* 返 回 值:无*/
void Serial_Printf(char *format, ...)
{char String[100];				//定义字符数组va_list arg;					//定义可变参数列表数据类型的变量argva_start(arg, format);			//从format开始,接收参数列表到arg变量vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中va_end(arg);					//结束变量argSerial_SendString(String);		//串口发送字符数组(字符串)
}
int Serial_GetFlag(void)
{//实现读取标志位后自动清除的功能if(Serial_flag == 1){Serial_flag = 0;return 1;}return 0;
}
int Serial_GetData(void)
{return Serial_Data;
}void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET){Serial_Data = USART_ReceiveData(USART1);Serial_flag = 1;//不用手动清除标志位,读取数据会自动清除}
}


http://www.hkcw.cn/article/SFdcgifmLA.shtml

相关文章

C# winform 教程(一)

一、安装方法 官网下载社区免费版&#xff0c;在线下载安装 VS2022官网下载地址 下载后双击启动&#xff0c;选择需要模块&#xff08;net桌面开发&#xff0c;通用window平台开发&#xff0c;或者其他自己想使用的模块&#xff0c;后期可以修改&#xff09;&#xff0c;选择…

ZLG ZCANPro,ECU刷新,bug分享

文章目录 摘要 📋问题的起因bug分享 ✨思考&反思 🤔摘要 📋 ZCANPro想必大家都不陌生,买ZLG的CAN卡,必须要用的上位机软件。在汽车行业中,有ECU软件升级的需求,通常都通过UDS协议实现程序的更新,满足UDS升级的上位机要么自己开发,要么用CANoe或者VFlash,最近…

Matlab作图之 subplot

1. subplot(m, n, p) 将当前图形划分为m*n的网格&#xff0c;在 p 指定的位置创建坐标轴 matlab 按照行号对子图的位置进行编号 第一个子图是第一行第一列&#xff0c;第二个子图是第二行第二列......... 如果指定 p 位置存在坐标轴&#xff0c; 此命令会将已存在的坐标轴设…

【STM32F1标准库】理论——外部中断

目录 一、中断介绍 二、外部引脚EXTI申请的中断 三、外部中断的适用场景 四、其他注意事项 一、中断介绍 STM32可以触发中断的外设有外部引脚(EXTI)、定时器、ADC、DMA、串口、I2C、SPI等 中断同一由NVIC管理 n表示一个外设可能同时占用多个中断通道 优先级的值越小优先…

SAP学习笔记 - 开发18 - 前端Fiori开发 应用描述符(manifest.json)的用途

上一章讲了 Component配置&#xff08;组件化&#xff09;。 本章继续讲Fiori的知识。 目录 1&#xff0c;应用描述符(Descriptor for Applications) 1&#xff09;&#xff0c; manifest.json 2&#xff09;&#xff0c;index.html 3&#xff09;&#xff0c;Component.…

定时任务:springboot集成xxl-job-core(一)

springboot:2.7.2 xxl-job-core: 2.3.0 一、集成xxl-job 1. 在gitee上下载xxl-job项目 git clone https://gitee.com/xuxueli0323/xxl-job.git 2. 执行以下目录下的sql /xxl-job-2.3.0/doc/db/tables_xxl_job.sql 3. 在xxl-job-admin的项目中配置数据库信息 ### xxl-job, data…

【STM32开发板】接口部分

一、USB接口 可以看到USBP和USBN与PA12,PA11引脚相接,根据协议&#xff0c;需要添加上拉电阻 二、ADC和DAC 根据原理图找到可以作为ADC和DAC的引脚 ADC和DAC属于模拟部分的&#xff0c;所以要接模拟地 三、指示灯电路 找几个通用的引脚&#xff0c;因为单片机的灌电流比拉电流…

阻塞队列BlockingQueue解析

阻塞队列是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除的方法。 阻塞插入&#xff1a;当队列满的时候&#xff0c;队列会阻塞插入元素的线程&#xff0c;直到队列不满。 阻塞移除&#xff1a;当队列空的时候&#xff0c;队列会阻塞移除元素的线程&…

[Redis] Redis命令在Pycharm中的使用

初次学习&#xff0c;如有错误还请指正 目录 String命令 Hash命令 List命令 set命令 SortedSet命令 连接pycharm的过程见&#xff1a;[Redis] 在Linux中安装Redis并连接桌面客户端或Pycharm-CSDN博客 redis命令的使用见&#xff1a;[Redis] Redis命令&#xff08;1&#xf…

车载控制器的“机电一体化”深度集成

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 所谓鸡汤&#xff0c;要么蛊惑你认命&#xff0c;要么怂恿你拼命&#xff0c;但都是回避问题的根源&…

PINN模型相关原理

PINN模型相关原理 目录 PINN模型相关原理原本的物理界的利用神经网络的参数估计PINN 的原理介绍一、基本思想二、PINN 的损失函数三、自动微分&#xff08;Autodiff&#xff09;四、PINN 的优势与挑战 原本的物理界的利用神经网络的参数估计 原本物理界需要确定一个三维流体&a…

计算机基础——宏病毒防御与网络技术

文章目录 宏病毒详解与防范措施宏病毒简介宏病毒的特点宏病毒的传播途径宏病毒的防范措施宏病毒的检测与清除 自治计算机与自治系统解析什么是自治计算机&#xff1f;技术特点 自治系统&#xff08;Autonomous System, AS&#xff09;特点&#xff1a;自治系统类型 总结&#x…

MySql(十一)

目录 准备工作 1&#xff09;准备一张表 2&#xff09;插入数据 分组 1&#xff09;通过性别去统计各组的平局工资 2.limit关键字 不使用limit的关键字 使用limit的关键字 使用limit关键字获取从指定行开始获取 准备工作 1&#xff09;准备一张表 CREATE table role(roleid INT…

论文阅读(六)Open Set Video HOI detection from Action-centric Chain-of-Look Prompting

论文来源&#xff1a;ICCV&#xff08;2023&#xff09; 项目地址&#xff1a;https://github.com/southnx/ACoLP 1.研究背景与问题 开放集场景下的泛化性&#xff1a;传统 HOI 检测假设训练集包含所有测试类别&#xff0c;但现实中存在大量未见过的 HOI 类别&#xff08;如…

使用 SASS 与 CSS Grid 实现鼠标悬停动态布局变换效果

最终效果概述 页面为 3x3 的彩色格子网格&#xff1b;当鼠标悬停任意格子&#xff0c;所在的行和列被放大&#xff1b;使用纯 CSS 实现&#xff0c;无需 JavaScript&#xff1b;利用 SASS 的模块能力大幅减少冗余代码。 HTML 结构 我们使用非常基础的结构&#xff0c;9 个 .i…

linux 后记

Linux Server 下载一个Server的版本&#xff0c;就是那种只有命令行的 学会这个就可以去租一个aliyun服务器&#xff0c;挺便宜的 如果在aliyun买服务器的话就不用管镜像源 但是如果是自己的虚拟机就必须设置镜像源&#xff0c;上网搜索阿里的镜像源&#xff0c;然后手动输入&…

2025年第三届CCF·夜莺开源创新论坛通知

点击蓝字 关注我们 CCF Opensource Development Committee 01 大会简介 由中国计算机学会主办、CCF开源发展委员会及夜莺开源社区承办的第三届CCF夜莺开源创新论坛拟于2025年7月4日在北京召开。本次论坛以“AI 加速可观测”为主题&#xff0c;汇聚了开源夜莺核心开发团队&#…

【2025CCF中国开源大会】RISC-V 开源生态的挑战与机遇分论坛重磅来袭!共探开源芯片未来

点击蓝字 关注我们 CCF Opensource Development Committee 开源浪潮正从软件席卷硬件领域&#xff0c;RISC-V作为全球瞩目的开源芯片架构&#xff0c;正在重塑计算生态的版图&#xff01;相较于成熟的x86与ARM&#xff0c;RISC-V生态虽处爆发初期&#xff0c;却蕴藏着无限可能。…

分布式流处理与消息传递——Kafka ISR(In-Sync Replicas)算法深度解析

Java Kafka ISR&#xff08;In-Sync Replicas&#xff09;算法深度解析 一、ISR核心原理 #mermaid-svg-OQtnaUGNQ9PMgbW0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-OQtnaUGNQ9PMgbW0 .error-icon{fill:#55222…

力扣题解106:从中序与后序遍历序列构造二叉树

一、题目内容 题目要求根据二叉树的中序遍历序列和后序遍历序列来重建二叉树。具体来说&#xff0c;我们需要利用中序遍历序列和后序遍历序列的特点&#xff0c;通过递归的方法逐步构建出完整的二叉树。 中序遍历序列的特点是&#xff1a;左子树 -> 根节点 -> 右子树。后…