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

文章目录

    • 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.pswp.cn/bicheng/84118.shtml

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

相关文章

LeetCode 152. 乘积最大子数组 - 动态规划解法详解

文章目录 问题描述解题思路动态规划状态定义状态转移方程完整代码实现复杂度分析示例解析关键点说明总结问题描述 给定一个整数数组 nums,请找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组对应的乘积。 示例: 输入: [2,3,-2,4] 输出: 6 解…

Python: 操作 Excel折叠

💡Python 操作 Excel 折叠(分组)功能详解(openpyxl & xlsxwriter 双方案) 在处理 Excel 报表或数据分析时,我们常常希望通过 折叠(分组)功能 来提升表格的可读性和组织性。本文将详细介绍如何使用 Python 中的两个主流 Excel 操作库 —— openpyxl 和 xlsxwriter …

28、元组的遍历

const_cast 只能用于指针或引用类型&#xff0c;而不能用于基本类型如 int。 在的代码中&#xff0c;试图将 i 转换为 const_cast<int>(i)&#xff0c;这是不合法的。 可以使用模板函数来获取元组中的元素&#xff0c;而不是使用 const_cast。以下是修正后的代码&#x…

sendDefaultImpl call timeout(rocketmq)

rocketmq 连接异常 senddefaultimpl call timeout-腾讯云开发者社区-腾讯云 第一种情况&#xff1a; 修改broker 的配置如下&#xff0c;注意brokerIP1 这个配置必须有&#xff0c;不然 rocketmq-console 显示依然是内网地址 caused by: org.apache.rocketmq.remoting.excep…

【仿生机器人】仿生机器人智能架构:从感知到个性的完整设计

仿生机器人智能架构&#xff1a;从感知到个性的完整设计 仿生机器人不仅需要模拟人类的外表&#xff0c;更需要具备类人的认知、情感和个性特征。本研究提出了一个综合性的软件架构&#xff0c;实现了从环境感知到情感生成、从实时交互到人格塑造的完整智能系统。该架构突破了…

Spring Boot微服务架构(十一):独立部署是否抛弃了架构优势?

Spring Boot 的独立部署&#xff08;即打包为可执行 JAR/WAR 文件&#xff09;本身并不会直接丧失架构优势&#xff0c;但其是否体现架构价值取决于具体应用场景和设计选择。以下是关键分析&#xff1a; 一、独立部署与架构优势的关系 内嵌容器的优势保留 Spring Boot 独立部署…

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…

2025年6月3日面试总结

1. 面试官问一台机器内存或者磁盘占用99% 再点一下就挂了&#xff0c;个人刚开始反应内存不足加内存&#xff0c;磁盘不足加磁盘&#xff0c;还有啥办法&#xff0c;有些时候没干过的事一定要大胆&#xff0c;敲命令都敲不成&#xff0c;只能换磁盘了和加内存了&#xff0c;要么…

从上下文学习和微调看语言模型的泛化:一项对照研究

大型语言模型表现出令人兴奋的能力&#xff0c;但也可以从微调中表现出令人惊讶的狭窄泛化。例如&#xff0c;他们可能无法概括为简单的关系反转&#xff0c;或者无法根据训练信息进行简单的逻辑推理。这些未能从微调中概括出来的失败可能会阻碍这些模型的实际应用。另一方面&a…

解决cocos 2dx/creator2.4在ios18下openURL无法调用的问题

由于ios18废弃了旧的openURL接口&#xff0c;我们需要修改CCApplication-ios.mm文件的Application::openURL方法&#xff1a; //修复openURL在ios18下无法调用的问题 bool Application::openURL(const std::string &url) {// NSString* msg [NSString stringWithCString:…

Go 语言并发编程基础:Goroutine 的创建与调度

Go 语言的并发模型是其最显著的语言特性之一。Goroutine 是 Go 实现并发的核心机制&#xff0c;它比线程更轻量&#xff0c;调度效率极高。 本章将带你了解 Goroutine 的基本概念、创建方式以及背后的调度机制。 一、什么是 Goroutine&#xff1f; Goroutine 是由 Go 运行时&a…

网页绘制表格

说明&#xff1a; border"1"&#xff1a;设置表格边框宽度为 1 像素&#xff08;可调整数值改变边框粗细&#xff09;。cellspacing"0"&#xff1a;设置单元格间距为 0&#xff08;去除边框间的空白间隙&#xff09;。<thead>&#xff1a;定义表头区…

Python爬虫实战:研究Unirest库相关技术

一、引言 在当今信息爆炸的时代,网络数据的获取与分析变得尤为重要。Python 作为一种功能强大且易于学习的编程语言,在网络爬虫领域有着广泛的应用。Unirest 库是一个轻量级的 HTTP 客户端库,它提供了简洁的 API,使得发送 HTTP 请求变得更加容易。本论文将详细分析如何使用…

二、【ESP32开发全栈指南:ESP32 GPIO深度使用】

GPIO&#xff08;通用输入输出&#xff09; 是ESP32最基础却最核心的功能。本文将带你深入ESP32的GPIO操作&#xff0c;通过按键读取和LED控制实现物理按键→ESP32→LED的完整信号链路。 一、ESP32 GPIO核心特性速览 34个可编程GPIO&#xff08;部分引脚受限&#xff09;输入模…

调用.net DLL让CANoe自动识别串口号

1.前言 CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客 之前做CAPL通过串口控制数控电源&#xff0c;存在一个缺点&#xff1a;更换电脑需要改串口号 CSDN上有类似的博客&#xff0c;不过要收费&#xff0c;本文根据VID和PID来自动获取串口号&#xff0c;代码…

SpringBoot十二、SpringBoot系列web篇之过滤器Filte详解

一、前言 JavaWeb三大组件Servlet、Filter、Listener&#xff0c;其中之一便是过滤器Filter。 其实&#xff0c;Filter我们平常用的不多&#xff0c;一般多为项目初期搭建web架构的时候使用&#xff0c;后面用的就少了&#xff0c;在日常业务开发中不太可能碰到需要手写Filte…

Java实现飞机射击游戏:从设计到完整源代码

JAVA打飞机游戏毕业设计 一、游戏概述 本游戏基于Java Swing开发&#xff0c;实现了经典的飞机射击游戏。玩家控制一架战斗机在屏幕底部移动&#xff0c;发射子弹击落敌机&#xff0c;同时躲避敌机攻击。游戏包含多个关卡&#xff0c;随着关卡提升&#xff0c;敌机速度和数量…

通俗易懂linux环境变量

如果想要清楚的了解环境变量&#xff0c;我觉得我们需要先大致搞清楚一个简单的事——什么是会话&#xff1f; 会话大致是什么&#xff1f; 在这里我们的目的是更好的理解环境变量&#xff0c;所以适当讲解一下会话即可。通常我们都是用xshell连接远程服务器&#xff0c;都会打…

【补题】Codeforces Round 715 (Div. 2) C. The Sports Festival

题意&#xff1a;给你一个序列&#xff0c;你可以对它重新排序&#xff0c;然后使每个i&#xff0c;max(a0,a1……ai)-min(a0,a1……ai)最小。问答案是多少 思路&#xff1a; C. The Sports Festival&#xff08;区间DP&#xff09;-CSDN博客 区间dp&#xff0c;完全没想到…

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…