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

news2025/6/8 11:00:36

文章目录

    • 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;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	Serial_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);
	
	//如果想要使用中断,就开启中断,然后配置NVIC
	USART_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;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	Serial_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.coloradmin.cn/o/2404052.html

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

相关文章

UOS无法安装deb软件包

UOS无法安装deb软件包 问题描述解决办法: 关闭安全中心的应用隔离结果验证 问题描述 UOS安装Linux微信的deb包时&#xff0c;无法正常安装 解决办法: 关闭安全中心的应用隔离 要关闭-安全中心的应用隔离后才可以正常软件和运行。 应用安全----》 允许任意应用。 结果验证 # …

VUE前端实现自动打包成压缩文件

VUE前端实现自动打包成压缩文件 背景思路实现打包代码实现 尾巴 背景 做前端开发的兄弟们都经历过每次开发完成之后发包需要进行打包&#xff0c;然后将打包文件压缩。每次打好包了都得手动压缩一遍&#xff0c;就有点繁琐。今天我们就使用一种命令行自动压缩的方法&#xff0…

2025政务服务便民热线创新发展会议顺利召开,张晨博士受邀分享

5月28日&#xff0c;由新华社中国经济信息社、新华社广东分社联合主办的2025政务服务便民热线创新发展暨“人工智能热线”会议在广州举行。会议围绕“人工智能与新质热线”主题&#xff0c;邀请全国的12345政务服务便民热线主管部门负责人、省市热线负责人和专家学者&#xff0…

【PDF PicKiller】PDF批量删除固定位置图片工具,默认解密,可去一般图、背景图、水印图!

PDF批量删除固定位置图片工具 PDF PicKiller <center>PDF PicKiller [Download](https://github.com/Peaceful-World-X/PDF-PicKiller)&#x1f929; 工具介绍&#x1f973; 主要功能&#x1f92a; 软件使用&#x1f92a; 参数解释&#x1f92a; 关键代码&#x1f929; 项…

GIC700组件

GIC700包含了几个重要的组件,它们使用一个内部的GIC互联,用于在不同的组件之间使用AXI5-Stream接口进行路由。 1. Distributor(GICD) gicd是GIC700中所有组件之间的主要通信节点。它作为SPI的管理者以及维护LPI的cache,并且与其它chip上的GIC700组件进行通信。当支持GIC…

有没有 MariaDB 5.5.56 对应 MySQL CONNECTION_CONTROL 插件

有没有 MariaDB 对应 MySQL CONNECTION_CONTROL 插件 背景 写这篇文章的目的是因为昨晚半夜突然被call起来&#xff0c;有一套系统的mysql数据库启动失败了。尝试了重启服务器也不行。让我协助排查一下问题出在哪。 分析过程 一开始拿到服务器IP地址&#xff0c;就去数据库…

TripGenie:畅游济南旅行规划助手:个人工作纪实(二十二)

这周&#xff0c;我进行了历史记录的设计与制作&#xff0c;我对于每一个用户与智能体交互得出的历史行程的数据进行了存储与可视化展示。 首先&#xff0c;我设置了一个csv文件存储每一个得出的行程规划&#xff0c;注意这里的地图我设置了一个全路径进行存储&#xff0c;这样…

如何用AI高效运营1000+Tiktok矩阵账号

在当今数字化的时代&#xff0c;Tiktok 矩阵账号运营成为了众多企业和个人追求流量与变现的重要手段。然而&#xff0c;面对众多的账号管理&#xff0c;如何高效运营成为了关键。此时&#xff0c;AI 工具的出现为我们提供了强有力的支持。 一、Tiktok 矩阵账号的重要性 Tiktok…

【论文解读】Toolformer: 语言模型自学使用工具

1st author: ‪Timo Schick‬ - ‪Google Scholar‬ paper: Toolformer: Language Models Can Teach Themselves to Use Tools | OpenReview NeurIPS 2023 oral code: lucidrains/toolformer-pytorch: Implementation of Toolformer, Language Models That Can Use Tools, by…

408第一季 - 数据结构 - 线性表II

链表 头节点始终指向第一个 头节点的好处&#xff1a; 第一个好处 这里L是头节点 可以发现&#xff0c;删除第一个也可以统一了 第二个好处 这是无头节点&#xff0c;空和非空指向的不一样 然后有头节点就可以统一了&#xff01; 双链表 插入 第一步要在第四步之前&…

基于VMD-LSTM融合方法的F10.7指数预报

F10.7 Daily Forecast Using LSTM Combined With VMD Method ​​F10.7​​ solar radiation flux is a well-known parameter that is closely linked to ​​solar activity​​, serving as a key index for measuring the level of solar activity. In this study, the ​​…

35 C 语言字符串转数值函数详解:strtof、strtod、strtold(含 errno 处理、ERANGE 错误)

1 strtof() 函数 1.1 函数原型 #include <stdlib.h> // 必须包含这个头文件才能使用 strtof() #include <errno.h> // 包含 errno 和 ERANGE #include <float.h> // 包含 FlOAT_MAX 和 FLOAT_MIN #include <math.h> // 包含 HUGE_VALF(inf)float…

日志收集工具-Filebeat

提示&#xff1a;windows 环境下 Filebeat 的安装与使用 文章目录 前言一、安装二、配置部署三、启动测试 前言 Filebeat 一般用于日志采集&#xff0c;由两部分组成 &#xff1a;Harvesters 和 prospector Harvesters采集器&#xff1a;逐行读取单个文件的内容&#xff0c;并…

Vue3学习(4)- computed的使用

1. 简述与使用 作用&#xff1a;computed 用于基于响应式数据派生出新值&#xff0c;其值会自动缓存并在依赖变化时更新。 ​缓存机制​&#xff1a;依赖未变化时直接返回缓存值&#xff0c;避免重复计算&#xff08;通过 _dirty 标志位实现&#xff09;。​响应式更新​&…

手机上网可以固定ip地址吗?详细解析

在移动互联网时代&#xff0c;手机已成为人们日常上网的主要设备之一。无论是工作、学习还是娱乐&#xff0c;稳定的网络连接都至关重要。许多用户对IP地址的概念有所了解&#xff0c;尤其是固定IP地址的需求。那么&#xff0c;手机上网能否固定IP地址&#xff1f;又该如何实现…

如何在Unity中实现点击一个按钮跳转到哔哩哔哩

1.创建一个按钮 2.编写一个脚本&#xff08;你可以把链接改成你想要跳转的网站&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class JumpToBilibili : MonoBehaviour {void Start(){gameObject.…

PySide6 GUI 学习笔记——常用类及控件使用方法(单行文本控件QLineEdit)

文章目录 QLineEdit 介绍常用方法QLineEdit.EchoMode 取值光标相关方法文本选择方法输入格式化字符&#xff08;Input Mask&#xff09;常用信号QLineEdit 实例 QLineEdit 介绍 QLineEdit 是 PySide6&#xff08;Qt for Python&#xff09;中用于单行文本输入的控件。它支持文本…

【数据结构】6. 时间与空间复杂度

文章目录 一、算法效率1、算法的复杂度 二、时间复杂度1、时间复杂度的概念2、大O的渐进表示法3、常见时间复杂度计算1&#xff09;实例12&#xff09;实例23&#xff09;实例34&#xff09;实例45&#xff09;实例56&#xff09;实例67&#xff09;实例78&#xff09;实例8 三…

基于springboot的藏文古籍系统

博主介绍&#xff1a;高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实实在…

重构城市应急指挥布控策略 ——无人机智能视频监控的破局之道

在突发事件、高空巡查、边远区域布控中&#xff0c;传统摄像头常常“看不到、跟不上、调不动”。无人机智能视频监控系统&#xff0c;打破地面视角局限&#xff0c;以“高空布控 AI分析 实时响应”赋能政企单位智能化管理。在城市应急指挥中心的大屏上&#xff0c;一场暴雨正…