当前位置: 首页 > news >正文

stm32之USART

目录

  • 1.引入
    • 1.1 通信接口
    • 1.2 串口
  • 2.USART
    • 2.1 简介
    • 2.2 框图
    • 2.3 基本机构图
    • 2.4 数据帧
    • 2.5 波特率发生器
    • 2.6 数据包
      • 2.6.1 数据模式
      • 2.6.2 HEX数据包
      • 2.6.3 文本数据包
      • 2.6.4 HEX数据包接收
      • 2.6.5 文本数据包接收
  • 3.结构体和相关API
    • 3.1 结构体
    • 3.2 API
      • 3.2.1 **初始化相关函数**
        • `void USART_DeInit(USART_TypeDef* USARTx)`
        • `void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)`
        • `void USART_StructInit(USART_InitTypeDef* USART_InitStruct)`
      • 3.2.2 **时钟相关函数**
        • `void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct)`
        • `void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct)`
      • 3.2.3 **控制相关函数**
        • `void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)`
        • `void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)`
        • `void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)`
      • 3.2.4 **数据收发函数**
        • `void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)`
        • `uint16_t USART_ReceiveData(USART_TypeDef* USARTx)`
      • 3.2.5 **状态和中断相关函数**
        • `FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)`
        • `void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)`
        • `ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)`
        • `void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)`
  • 4.实验
    • 4.1 串口发送
    • 4.2 串口发送 + 接收
    • 4.3 HEX数据包收发
    • 4.4 文本数据包收发
  • 5.FlyMcu串口下载&STLINK Utility
    • 5.1 FlyMcu
    • 5.2 STLINK Utility

img

1.引入

1.1 通信接口

通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统

通信协议:制定通信的规则,通信双方按照协议规则进行数据收发

名称引脚双工时钟电平设备
USARTTX、RX全双工异步单端点对点
I2CSCL、SDA半双工同步单端多设备
SPISCLK、MOSI、MISO、CS全双工同步单端多设备
CANCAN_H、CAN_L半双工异步差分多设备
USBDP、DM半双工异步差分点对点

1.2 串口

具体一点的内容看嵌入式驱动开发中的UART子系统对串口的硬件简介。

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信

单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力

img

上图左边是USB转串口模块,中间是陀螺仪传感器模块(左边的是接串口、右边的引脚接I2C),右边是蓝牙串口模块


数据低位先行

  • 简单双向串口通信有两根通信线(发送端TX和接收端RX)
  • TX与RX要交叉连接
  • 当只需单向的数据传输时,可以只接一根通信线
  • 当电平标准不一致时,需要加电平转换芯片

img

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

  • TTL电平:+3.3V或+5V表示1,0V表示0
  • RS232电平:-3-15V表示1,+3+15V表示0
  • RS485电平:两线压差+2+6V表示1,-2-6V表示0(差分信号)

串口参数及时序:

  • 波特率:串口通信的速率,每秒传送的码元个数(二进制调制下就等同于每秒传递的比特数)
  • 起始位:标志一个数据帧的开始,固定为低电平
  • 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
  • 校验位:用于数据验证,根据数据位计算得来
  • 停止位:用于数据帧间隔,固定为高电平

img

串口时序:

img

2.USART

对应芯片参考手册img的USART部分

2.1 简介

USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器

USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里

自带波特率发生器,最高达4.5Mbits/s。其实就是个分频器,波特率发生器对时钟进行一个分频,就能得到想要的波特率时钟,在该时钟下进行收发,就是指定的通信波特率。

可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)

可选校验位(无校验/奇校验/偶校验)

支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN

STM32F103C8T6 USART资源: USART1(APB2总线上的)、 USART2(APB1总线上的)、 USART3(APB1总线上的)

2.2 框图

来自参考手册

img

1. 数据接口模块

  • TX/RX:分别为串行数据发送和接收引脚,是USART的主要外部接口,用于与外部设备通信。
  • nRTS/nCTS:硬件流控引脚,分别表示请求发送(Request to Send)和清除发送(Clear to Send)信号。如果发送数据发送的太快,接收方来不及接收,就会发生数据丢失或覆盖的情况,为解决这种情况就靠这两根引脚。nRTS:你能不能发数据给我(接对方的nCTS);nCTS:我能不能发数据给你(接对方的nRTS)
  • IrDA模块:支持红外通信的编码和解码模块,可通过配置CR3寄存器启用。

2. 发送器部分

发送数据寄存器 (TDR)

  • 用于存储需要发送的数据,写操作通过CPU或DMA完成。
  • 数据从TDR被传输至发送移位寄存器,开始按位输出到TX引脚。

发送移位寄存器

  • 数据从TDR进入移位寄存器,并以配置的波特率逐位发送。
  • 发送时序由USART_BRR寄存器提供的分频时钟控制。

发送控制逻辑

  • 控制寄存器CR1中的TE位:使能发送功能。
  • 状态寄存器 (SR)中的TXE中断:当TDR为空时触发,提示CPU或DMA准备下一个数据。

3. 接收器部分

接收移位寄存器

  • 从RX引脚按位接收数据,并将其组合成完整的数据字节。
  • 数据组合完成后传递到接收数据寄存器 (RDR)。

接收数据寄存器 (RDR)

  • 接收的数据存储在RDR中,可通过CPU读取。
  • 数据从RDR读取后,触发RXNE中断,提示CPU完成一次数据接收。

接收控制逻辑

  • 控制寄存器CR1中的RE位:使能接收功能。
  • 状态寄存器 (SR)中的RXNE标志:指示RDR中有新数据可供读取。

4. 控制逻辑模块

中断控制

  • 中断源 (CR1, CR2, CR3)

    • CR1中的TXEIE、RXNEIE等控制发送和接收中断。
    • CR2控制错误中断,如帧错误和过载错误。
    • CR3用于流控中断,如CTS中断。
  • 状态寄存器 (SR)

    • 包括多种标志位,如TXE(发送数据寄存器空)、RXNE(接收数据寄存器非空)和PE(奇偶校验错误)。

5. 时钟生成模块

USART_BRR寄存器

  • 波特率寄存器,用于配置发送和接收的波特率。
  • 波特率计算公式:img
    其中,DIV_Mantissa表示整数部分,DIV_Fraction表示小数部分。
  • 波特率由系统时钟提供,并通过分频器(/16)生成。

6. 模式配置模块

CR1、CR2、CR3寄存器

  • CR1:基本功能配置,例如使能USART、发送、接收等。
  • CR2:帧格式设置(停止位长度、时钟使能)。
  • CR3:高级功能,例如DMA支持、流控和红外功能。

7. DMA支持

  • 支持通过DMA直接操作TDR和RDR寄存器,减轻CPU负担。
  • DMA触发器:根据TXE(发送)和RXNE(接收)状态,触发DMA完成数据传输。

8. 数据传递路径

  1. 发送路径
    • CPU/DMA将数据写入TDR。
    • 数据进入发送移位寄存器。
    • 移位寄存器按照波特率逐位发送到TX引脚。
  1. 接收路径
    • RX引脚接收到串行数据。
    • 数据进入接收移位寄存器,组合成数据字节。
    • 数据传递至RDR,等待CPU读取。

2.3 基本机构图

img

注意:无论是发送还是接收,数据都是低位先行。

2.4 数据帧

字长设置:

img

在时钟的上升沿进行数据的读取。对于9位字长,一般第9位会选择为校验位,毕竟前面8位刚好就是1字节,uint8。同理对于8位字长的数据,一般最后一位不选择为校验位。


停止位配置:

img

stm32的停止位可以配置停止位长度为0.5、1、1.5、2,就是停止位是时长不同。


起始位侦测采样:

img

对于输入的数据,要对其进行采用,最后就时钟的上升沿采用的时候刚好对于数据位的正中间,防止因为一些噪声等导致数据位有波形,造成采洋不准。

而为了实现这部分的功能,输入的这部分电路对采样时钟进行了细分,会以波特率的16倍频率进行采样(即在一位的时间里可以对一位的数据进行16次采样)。

而上图就是对起始位进行16次的采样,出现下降沿时,采样采到0,而后面还会继续采样,防止下降沿是因为某些抖动而导致的,并不是代表起始位。当在每3次采样里至少有2个0,就代表这个位确实是起始位。


数据采样:

img

这部分就是前面提到的,为了保证数据的正确,尽量在数据位的中间对该为数据进行采样。

2.5 波特率发生器

发送器和接收器的波特率由波特率寄存器BRR里的DIV确定

计算公式:波特率 = fPCLK2/1 / (16 * DIV)

img

为什么还要除以16???上面讲解数据采样的时候有说过,一位数据的采样次数是16次,也就是16个时钟的时间。因此 fPCLK2/1 /DIV取到的波特率还得除以16,才是实际上每秒传输码元的个数。

就当成时钟频率去理解就行,1位数据需要16个时钟,DIV分频后的时钟频率还得再去除以16,做到和每一位的数据相对应。

2.6 数据包

把多个字节(数据帧)给打包一起发送

2.6.1 数据模式

HEX模式/十六进制模式/二进制模式:以原始数据的形式显示

文本模式/字符模式:以原始数据编码后的形式显示

img

img

2.6.2 HEX数据包

img

这种为了避免载荷数据和包头包尾出现数据重复的现象,可以使用载荷数据限制大小、载荷数据限制长度和增加包头包尾的数量来解决。

至于可变包长,更适合载荷数据不会和包头包尾数据重复的情况下使用。

2.6.3 文本数据包

img

2.6.4 HEX数据包接收

img

2.6.5 文本数据包接收

img

3.结构体和相关API

3.1 结构体

typedef struct
{uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.The baud rate is computed using the following formula:- IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.This parameter can be a value of @ref USART_Word_Length */uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.This parameter can be a value of @ref USART_Stop_Bits */uint16_t USART_Parity;              /*!< Specifies the parity mode.This parameter can be a value of @ref USART_Parity@note When parity is enabled, the computed parity is insertedat the MSB position of the transmitted data (9th bit whenthe word length is set to 9 data bits; 8th bit when theword length is set to 8 data bits). */uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.This parameter can be a value of @ref USART_Mode */uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabledor disabled.This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;

\1. USART_BaudRate

  • 作用:配置USART通信的波特率(每秒比特传输速率)。

  • 计算公式
    img

    • PCLKx 是外设时钟频率。
    • BaudRate 是配置的波特率。
    • 波特率寄存器 USART_BRR 的整数部分由 USARTDIV 的整数值构成,小数部分由其余值通过四舍五入计算得出。
  • 取值范围:常用波特率值(如 9600, 19200, 38400, 115200 等)。实际取值需确保 PCLKx 能支持目标波特率。


\2. USART_WordLength

  • 作用:指定每帧传输或接收的数据位数(包括有效数据位和可选的校验位)。

  • 可取值

    • USART_WordLength_8b:8位数据帧(默认)。
    • USART_WordLength_9b:9位数据帧(通常用于特殊协议或需要扩展数据位时)。
  • 注意

    • 如果使用奇偶校验,帧中最高位(第8或第9位)被用作校验位。

\3. USART_StopBits

  • 作用:设置每帧发送结束时的停止位数,用于标识帧结束。

  • 可取值

    • USART_StopBits_1:1个停止位(默认)。
    • USART_StopBits_0.5:0.5个停止位。
    • USART_StopBits_2:2个停止位(用于慢速通信或特定协议)。
    • USART_StopBits_1.5:1.5个停止位(特定场景)。
  • 注意:停止位设置需与接收设备保持一致。


\4. USART_Parity

  • 作用:配置是否启用奇偶校验以及校验模式(奇校验或偶校验)。

  • 可取值

    • USART_Parity_No:无校验(默认)。
    • USART_Parity_Even:偶校验。
    • USART_Parity_Odd:奇校验。
  • 注意

    • 启用校验后,帧中最高有效位会被占用,用于传输校验位。
    • 校验位由硬件自动生成,无需用户干预。

\5. USART_Mode

  • 作用:指定USART的工作模式(发送、接收或两者均启用)。

  • 可取值

    • USART_Mode_Rx:仅接收模式。
    • USART_Mode_Tx:仅发送模式。
    • USART_Mode_Tx_Rx:同时启用发送和接收模式。
  • 典型应用

    • 仅接收模式常用于传感器数据读取。
    • 同时启用发送和接收模式适用于双向通信(如UART调试、RS232通信等)。

\6. USART_HardwareFlowControl

  • 作用:设置硬件流控制模式,用于控制数据流的启停(基于RTS和CTS信号)。

  • 可取值

    • USART_HardwareFlowControl_None:无硬件流控(默认)。
    • USART_HardwareFlowControl_RTS:仅启用RTS流控(发送设备请求发送时使能)。
    • USART_HardwareFlowControl_CTS:仅启用CTS流控(接收设备允许发送时使能)。
    • USART_HardwareFlowControl_RTS_CTS:同时启用RTS和CTS流控。
  • 注意:硬件流控适用于需要精确控制数据流的场景,如避免数据溢出或丢失。

3.2 API

3.2.1 初始化相关函数

void USART_DeInit(USART_TypeDef* USARTx)
  • 作用:将指定USART外设的寄存器恢复为默认复位值。
  • 使用场景:在重新配置USART外设之前使用,确保状态清零。
  • 示例
USART_DeInit(USART1); // 将USART1寄存器重置为默认值
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
  • 作用:根据USART_InitTypeDef结构配置USART的波特率、数据位、停止位、校验、工作模式和硬件流控。
  • 使用场景:初始化USART通信。
  • 示例
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx_Rx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART1, &USART_InitStructure);
void USART_StructInit(USART_InitTypeDef* USART_InitStruct)
  • 作用:将USART_InitTypeDef结构初始化为默认值。

  • 默认值

    • 波特率为9600
    • 8位数据帧。
    • 1个停止位。
    • 无校验。
    • 收发模式均启用。
    • 无硬件流控。
  • 示例

USART_InitTypeDef USART_InitStructure;
USART_StructInit(&USART_InitStructure); // 初始化为默认值
USART_Init(USART1, &USART_InitStructure);

3.2.2 时钟相关函数

void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct)
  • 作用:配置USART同步模式下的时钟设置(如极性、相位等)。
  • 使用场景:仅在同步模式下(如SPI通信)配置时钟信号。
  • 示例
USART_ClockInitTypeDef USART_ClockInitStructure;
USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Enable;USART_ClockInit(USART1, &USART_ClockInitStructure);
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct)
  • 作用:将USART_ClockInitTypeDef结构初始化为默认值(同步模式时钟禁用)。
  • 示例
USART_ClockInitTypeDef USART_ClockInitStructure;
USART_ClockStructInit(&USART_ClockInitStructure);
USART_ClockInit(USART1, &USART_ClockInitStructure);

3.2.3 控制相关函数

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
  • 作用:使能或禁用USART外设。
  • 示例
USART_Cmd(USART1, ENABLE); // 启用USART1
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
  • 作用:配置指定的USART中断。

  • 中断类型

    • USART_IT_TXE:发送数据寄存器空中断。
    • USART_IT_RXNE:接收数据寄存器非空中断。
    • USART_IT_PE:奇偶校验错误中断。
  • 示例

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 启用接收非空中断
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
  • 作用:使能或禁用USART的DMA请求。

  • 参数

    • USART_DMAReq_Tx:发送数据DMA请求。
    • USART_DMAReq_Rx:接收数据DMA请求。
  • 示例

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 启用发送DMA

3.2.4 数据收发函数

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
  • 作用:发送一个数据帧。
  • 示例
USART_SendData(USART1, 'A'); // 发送字符 'A'
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
  • 作用:接收一个数据帧。
  • 示例
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {uint16_t data = USART_ReceiveData(USART1); // 接收数据
}

3.2.5 状态和中断相关函数

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)
  • 作用:获取指定的USART标志状态。

  • 常见标志

    • USART_FLAG_TXE:发送数据寄存器空标志。
    • USART_FLAG_RXNE:接收数据寄存器非空标志。
    • USART_FLAG_ORE:溢出错误标志。
  • 示例

if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {// 接收到数据
}
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
  • 作用:清除指定标志位(如溢出错误等)。
  • 示例
USART_ClearFlag(USART1, USART_FLAG_ORE); // 清除溢出错误标志
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
  • 作用:检查指定中断是否发生。
  • 示例
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) {// 接收非空中断发生
}
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)
  • 作用:清除中断挂起标志。
  • 示例
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除接收非空中断挂起标志

4.实验

CH340 USB转串口的原理图

img

4.1 串口发送

📎9-1 串口发送.zip

img

User:

  • 📎main.c

Hardware:

  • 📎OLED.c📎OLED.h📎OLED_Font.h📎Serial.c📎Serial.h

其中对于发送数据,仍然要注意的是低位数据开始传送!!!!这里是数据帧字长为8,从低位开始传输,这个其实也不用太在意,因为调用提供的USART_SendData函数的时候内部已经帮我们做好了。

但是当我们要传输数字的时候,需要注意将其每一位数都给拆开然后再挨个传输出去。比如你要发送21(十进制),那么就要先十位的2,在发送个位的1,就是要把每一位数都给转换成一个数据帧,在这里也就是uint8_t:

/*** 函    数:串口发送一个字节* 参    数:Byte 要发送的一个字节* 返 回 值:无*/
void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);		//将字节数据写入数据寄存器,写入后USART自动生成时序波形while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待发送完成/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
}/*** 函    数:次方函数(内部使用)* 返 回 值:返回值等于X的Y次方*/
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;	//设置结果初值为1while (Y --)			//执行Y次{Result *= X;		//将X累乘到结果}return Result;
}/*** 函    数:串口发送数字* 参    数:Number 要发送的数字,范围:0~4294967295* 参    数:Length 要发送数字的长度,范围:0~10* 返 回 值:无*/
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++)		//根据数字长度遍历数字的每一位{Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');	//依次调用Serial_SendByte发送每位数字}
}

假设咱们调用了Serial_SendNumber(123,3);123是要传输的十进制的数(uinit32_t),得将每一位都给拆开成一个数据帧,也就是uint8_t a = 1、uint8_t b= 2、uint8_t c= 3,将a、b、c挨个传输。 逐位拆解数字并以 ASCII 码的形式发送。

这时候就可以采用取余的方式获取到低位。参2就是传这个数字的位数,这里是3。

通过调用Serial_Pow函数去对数字的不相关的位数进行去除,比如第一次for时,Serial_Pow传的参2是2,最后返回是100,123/100会得到1(注意是int的形式!!),1%10就可以知道百位数就是1了。其余的位数也是同理。

调用 Serial_SendNumber(123, 3) 的具体过程:

  • 第1次循环(i=0):

    • Serial_Pow(10, 3-0-1) = Serial_Pow(10, 2) = 100
    • 123 / 100 = 11 % 10 = 1,对应字符 '1'
    • 发送 '1'
  • 第2次循环(i=1):

    • Serial_Pow(10, 3-1-1) = Serial_Pow(10, 1) = 10
    • 123 / 10 = 1212 % 10 = 2,对应字符 '2'
    • 发送 '2'
  • 第3次循环(i=2):

    • Serial_Pow(10, 3-2-1) = Serial_Pow(10, 0) = 1
    • 123 / 1 = 123123 % 10 = 3,对应字符 '3'
    • 发送 '3'

4.2 串口发送 + 接收

📎9-2 串口发送+接收.zip

img

User:

  • 📎main.c

Hardware:

  • 📎OLED.c📎OLED.h📎OLED_Font.h📎Serial.c📎Serial.h

4.3 HEX数据包收发

📎9-3 串口收发HEX数据包.zip

img

User:

  • 📎main.c

Hardware:

  • 📎OLED.c📎OLED.h📎OLED_Font.h📎Serial.c📎Serial.h📎Key.h📎Key.c

需要注意的是:

img

32中中断是可以嵌套的。如果在OLED显示数据的时候,中途又发生了中断进行接收数据,对Serial_RxPacket数组进行写入,就可能会导致输出的前一半是上次的数据,后一半是新来的数据。这个需要注意。

但是这种HEX数据包多是用于传感器的各个独立数据、陀螺仪的XYZ数据等,它们相邻的数据包都是具有连续性的,即使相邻数据混在一起了也没啥关系。如果想避免这种问题,可以在中断处理函数中添加一个标志位,在上一个数据发送完后再标志为可以接收。

4.4 文本数据包收发

📎9-4 串口收发文本数据包.zip

img

User:

  • 📎main.c

Hardware:

  • 📎LED.c📎LED.h📎OLED.c📎OLED.h📎OLED_Font.h📎Serial.c📎Serial.h

img

当在发送区输入指定的数据包点击发送后,会调用到中断函数USART1_IRQHandler,根据数据包进行解析,将载荷数据放置到全局数组Serial_RxPacket中。然后在main函数中通过strcmp函数去对该数组和对应的指令进行比较,执行相应的操作:

img

stm32通过Serial_SendString函数将是LED否开启成功的状态通过串口传输到串口助手,会在接收区显示。

5.FlyMcu串口下载&STLINK Utility

5.1 FlyMcu

通过串口给stm32下载程序。

📎FlyMcu程序烧录软件.zip


需要先将设置成:系统存储器模式。

img

img

img

红色是跳线帽地接法,之后记得按一次复位键。

img

需要注意的是这个烧录软件只支持USART1下的引脚。

img


打开keil中的工程,编译生成一个.hex文件
img

之后重新编译一下:

img

img

就可以看到串口下载所需要的文件


img

之后打开烧录助手,进行相关配置,选择.hex文件,开始编程进行烧录即可。


之后将32的跳线帽重新接回主闪存启动模式,点击复位键,就可以看到程序的运行现象。

5.2 STLINK Utility

📎STLINK Utility.zip

相关文章:

stm32之USART

目录 1.引入1.1 通信接口1.2 串口 2.USART2.1 简介2.2 框图2.3 基本机构图2.4 数据帧2.5 波特率发生器2.6 数据包2.6.1 数据模式2.6.2 HEX数据包2.6.3 文本数据包2.6.4 HEX数据包接收2.6.5 文本数据包接收 3.结构体和相关API3.1 结构体3.2 API3.2.1 **初始化相关函数**void USA…...

使用 systemd 管理 Linux 服务:配置与自动重启指南

使用 systemd (推荐&#xff0c;适用于大多数 Linux 发行版) systemd 是现代 Linux 系统中最常用的服务管理器。它能可靠地管理进程&#xff0c;并在进程崩溃时自动重启。 创建 systemd 服务文件&#xff1a; 创建一个文件&#xff0c;例如 /etc/systemd/system/app.service…...

【计算机视觉】Car-Plate-Detection-OpenCV-TesseractOCR:车牌检测与识别

Car-Plate-Detection-OpenCV-TesseractOCR&#xff1a;车牌检测与识别技术深度解析 在计算机视觉领域&#xff0c;车牌检测与识别&#xff08;License Plate Detection and Recognition, LPDR&#xff09;是一个极具实用价值的研究方向&#xff0c;广泛应用于智能交通系统、安…...

《Spring Boot 3.0全新特性详解与实战案例》

大家好呀&#xff01;今天让我们轻松掌握Spring Boot 3.0的所有新特性&#xff01;&#x1f680; &#x1f4cc; 第一章&#xff1a;Spring Boot 3.0简介 1.1 什么是Spring Boot 3.0&#xff1f; Spring Boot 3.0就像是Java开发者的"超级工具箱"&#x1f9f0;&…...

二叉树的深度

二叉树的深度是指从根节点到叶子节点的最长路径上的节点数。 一、最大深度 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 最大深度是指从根节点到最远叶子节点的最长路径上的节点数。 //递归法 /*** Definition for a binary tree node.* public class T…...

科技创业园共享会议室线上预约及智能密码锁系统搭建指南

为科技创业园区的运营管理者&#xff0c;我深知高效利用会议室资源的重要性。2023年第三季度&#xff0c;我们园区启动会议室智能化改造项目&#xff0c;经过三个月的实践&#xff0c;成功将32间共享会议室升级为"线上预约智能门锁"管理模式。现将改造经验分享如下&a…...

自定义prometheus exporter实现监控阿里云RDS

# 自定义 Prometheus Exporter 实现多 RDS 数据采集## 背景1. Prometheus 官网提供的 MySQL Exporter 对于 MySQL 实例只能一个进程监控一个实例&#xff0c;数据库实例很多的情况下&#xff0c;不方便管理。 2. 内部有定制化监控需求&#xff0c;RDS 默认无法实现&#xff0c;…...

LeetCode 3342.到达最后一个房间的最少时间 II:dijkstra算法(和I一样)

【LetMeFly】3342.到达最后一个房间的最少时间 II&#xff1a;dijkstra算法(和I一样) 力扣题目链接&#xff1a;https://leetcode.cn/problems/find-minimum-time-to-reach-last-room-ii/ 有一个地窖&#xff0c;地窖中有 n x m 个房间&#xff0c;它们呈网格状排布。 给你一…...

iOS创建Certificate证书、制作p12证书流程

一、创建Certificates 1、第一步得先在苹果电脑上创建一个.certSigningRequest的文件。首先打开钥匙串&#xff0c;使用快捷键【command空格】——输入【钥匙串】回车&#xff08;找不到就搜一下钥匙串访问使用手册&#xff09; 2、然后在苹果电脑的左上角菜单栏选择【钥匙串…...

特殊配合力(SCA)作为全基因组关联分析(GWAS)的表型,其生物学意义和应用价值

生物学意义 解析非加性遗传效应 特殊配合力(SCA)主要反映特定亲本组合的杂交优势,由非加性遗传效应(如显性、超显性、上位性)驱动。显性效应涉及等位基因间的显性互作,上位性效应则涉及不同位点间的基因互作。通过SCA-GWAS,可以定位调控这些非加性效应的关键基因组区域…...

Python实例题:Python快速获取斗图表情

目录 Python实例题 题目 python-get-meme-imagesPython 快速获取斗图表情脚本 代码解释 get_meme_images 函数&#xff1a; download_images 函数&#xff1a; 主程序&#xff1a; 运行思路 注意事项 Python实例题 题目 Python快速获取斗图表情 python-get-meme-im…...

探索表访问方法功能:顺序扫描分析

引言 在之前的文章中&#xff0c;我们讨论了 PostgreSQL 表访问方法 API 的基础知识以及堆元组&#xff08;heap tuple&#xff09;与元组表槽&#xff08;Tuple Table Slot&#xff0c;简称 TTS&#xff09;之间的区别。 本文将深入探讨 PostgreSQL 核心如何通过特定的 API …...

RISC-V CLINT、PLIC及芯来ECLIC中断机制分析 —— RISC-V中断机制(一)

在长期的嵌入式开发实践中&#xff0c;对中断机制的理解始终停留在表面层次&#xff0c;特别当开发者长期局限于纯软件抽象层面时&#xff0c;对中断机制的理解极易陷入"知其然而不知其所以然"的困境&#xff0c;这种认知的局限更为明显&#xff1b;随着工作需要不断…...

Idea Code Templates配置

Templates配置 配置位置模板案例 配置位置 Settings->Editor->File and Code Templates模板案例 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#endimport com.ktools.common.dataprocess.DataProcess; import com.ktools…...

fakebook

解题方法&#xff1a; 一.用御剑扫描后台&#xff0c;查看robot.txt文件&#xff0c;发现是一个/user.php.bak,备份文件&#xff0c;我们访问这个文件 <?phpclass UserInfo {public $name "";public $age 0;public $blog "";public function __co…...

英伟达Blackwell架构重构未来:AI算力革命背后的技术逻辑与产业变革

——从芯片暴力美学到分布式智能体网络&#xff0c;解析英伟达如何定义AI基础设施新范式 开篇&#xff1a;当算力成为“新石油”&#xff0c;英伟达的“炼油厂”如何升级&#xff1f; 2025年3月&#xff0c;英伟达GTC大会上&#xff0c;黄仁勋身披标志性皮衣&#xff0c;宣布了…...

用 Rust 搭建一个优雅的多线程服务器:从零开始的详细指南

嘿&#xff0c;小伙伴们&#xff01;今天咱们来聊聊怎么用 Rust 搭建一个牛气哄哄的多线程服务器&#xff0c;还能在需要的时候优雅地关机。为啥要用 Rust 呢&#xff1f;因为 Rust 是个超级靠谱的语言&#xff0c;它能保证内存安全&#xff0c;写并发代码的时候不用担心那些让…...

今日行情明日机会——20250509

上证指数今天缩量&#xff0c;整体跌多涨少&#xff0c;走势处于日线短期的高位~ 深证指数今天缩量小级别震荡&#xff0c;大盘股表现更好~ 2025年5月9日涨停股主要行业方向分析 一、核心主线方向 服装家纺&#xff08;消费复苏出口链驱动&#xff09; • 涨停家数&#xf…...

ESP32开发入门(七):HTTP开发实践

一、HTTP协议基础 1.1 什么是HTTP&#xff1f; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最为广泛的一种网络协议&#xff0c;用于从服务器传输超文本到本地浏览器。它是一种无状态的请求/响应协议&#xff0c;工作…...

【强化学习】强化学习算法 - 马尔可夫决策过程

马尔可夫决策过程 (Markov Decision Process, MDP) 1. MDP 原理介绍 马尔可夫决策过程 (MDP) 是强化学习 (Reinforcement Learning, RL) 中用于对序贯决策 (Sequential Decision Making) 问题进行数学建模的标准框架。它描述了一个智能体 (Agent) 与环境 (Environment) 交互的…...

数据结构【二叉搜索树(BST)】

二叉搜索树 1. 二叉搜索树的概念2. 二叉搜索树的性能分析3.二叉搜索树的插入4. 二叉搜索树的查找5. 二叉搜索树的删除6.二叉搜索树的实现代码7. 二叉搜索树key和key/value使用场景7.1 key搜索场景&#xff1a;7.2 key/value搜索场景&#xff1a; 1. 二叉搜索树的概念 二叉搜索…...

振动临近失效状态,怎么频谱会是梳子?

这是一个破坏性试验的终末期振动波形。左边时域&#xff0c;右边频域。这是咋回事&#xff0c;时域看起来原本很正常的冲击信号&#xff0c;怎么频域是那个鬼样子。 同一组波形&#xff0c;放大后的频域 - 低频部分&#xff1a; 一个解释&#xff1a;...

橡胶制品行业质检管理的痛点 质检LIMS如何重构橡胶制品质检价值链

橡胶制品广泛应用于汽车、医疗、航空等领域&#xff0c;其性能稳定性直接关联终端产品的安全性。从轮胎耐磨性测试到密封件耐腐蚀性验证&#xff0c;每一项检测数据都是企业参与市场竞争的核心筹码。然而&#xff0c;传统实验室管理模式普遍面临设备调度混乱、检测流程追溯断层…...

【CTFSHOW_Web入门】命令执行

文章目录 命令执行web29web30web31web32web33web34web35web36web37web38web39web40web41web42web43web44web45web46web47web48web49web50web51web52web53web54web55web56web57web58web59web60web61web62web63web64web65web66web67web68web69web70web71web72web73web74web75web7…...

三维底座+智能应用,重构城市治理未来

在“数字中国”战略的引领下&#xff0c;住房和城乡建设领域正迎来一场深刻的数字化转型浪潮。2024年《“数字住建”建设整体布局规划》的发布&#xff0c;明确提出以“CIM”&#xff08;城市信息模型&#xff09;为核心&#xff0c;构建城市三维数字底座&#xff0c;推动住建行…...

养生:塑造健康生活的良方

养生是一场贯穿生活的自我关爱行动&#xff0c;从饮食、运动、睡眠到心态调节&#xff0c;每一个环节都对健康有着深远影响。以下为你带来全面且实用的养生策略。 饮食养生&#xff1a;科学搭配&#xff0c;呵护肠胃 合理规划三餐&#xff0c;遵循 “早营养、午均衡、晚清淡”…...

docker 镜像的导出和导入(导出完整镜像和导出容器快照)

一、导出原始镜像 1. 使用 docker save 导出完整镜像 适用场景&#xff1a;保留镜像的所有层、元数据、标签和历史记录&#xff0c;适合迁移或备份完整镜像环境。 操作命令 docker save -o <导出文件名.tar> <镜像名:标签>示例&#xff1a;docker save -o milvu…...

NestJS 框架深度解析

框架功能分析 NestJS 是一个基于 Node.js 的渐进式框架&#xff0c;专为构建高效、可扩展的服务器端应用程序而设计。其核心理念结合了 面向对象编程&#xff08;OOP&#xff09;、函数式编程&#xff08;FP&#xff09; 和 函数式响应式编程&#xff08;FRP&#xff09;&…...

游戏引擎学习第267天:为每个元素添加裁剪矩形

仓库已满:https://gitee.com/mrxiao_com/2d_game_6 新仓库:https://gitee.com/mrxiao_com/2d_game_7 回顾并为今天的内容定下基调 我们今天的主要目标是对游戏的调试“Top List”进行改进&#xff0c;也就是用来显示游戏中耗时最多的函数或模块的性能分析列表。昨天我们已经实…...

基于阿里云DataWorks的物流履约时效离线分析

基于阿里云DataWorks的物流履约时效离线分析2. 数仓模型构建 ORC和Parquet区别&#xff1a; 压缩率与查询性能 压缩率 ORC通常压缩率更高&#xff0c;文件体积更小&#xff0c;适合存储成本敏感的场景。 Parquet因支持更灵活的嵌套结构&#xff0c;压缩率略…...

web 自动化之 selenium 元素四大操作三大切换等待

文章目录 一、元素的四大操作二、三大切换&等待1、切换窗口:当定位的元素不在当前窗口&#xff0c;则需要切换窗口2、切换iframe&#xff1a;当定位的元素在frame/iframe&#xff0c;则需要切换 一、元素的四大操作 1、输入 2、点击 3、获取文本 4、获取属性 import time…...

前端取经路——性能优化:唐僧的九道心经

大家好&#xff0c;我是老十三&#xff0c;一名前端开发工程师。性能优化如同唐僧的九道心经&#xff0c;是前端修行的精髓所在。在本文中&#xff0c;我将为你揭示从网络传输到渲染优化的九大关键技术&#xff0c;涵盖HTTP协议、资源加载策略、缓存控制等核心难题。通过这些实…...

前端工程化和性能优化问题详解

选自己熟悉的内容当作重难点&#xff0c;最好是前端相关的 以下是面向前端面试官介绍前端工程化和性能优化问题的结构化回答框架&#xff0c;结合行业标准和实战经验进行整合&#xff1a; 一、前端工程化核心解析 定义与目标 前端工程化是通过工具链和规范化流程&#xff0c;将…...

【应急响应】- 日志流量如何分析?

【应急响应】- 日志流量如何下手&#xff1f;https://mp.weixin.qq.com/s/dKl8ZLZ0wjuqUezKo4eUSQ...

8b10b编解码仿真

一、基本概念 8B/10B编码&#xff08;8-bit to 10-bit encoding&#xff09;是一种将8位数据&#xff08;包括数据字符和控制字符&#xff09;转换为10位符号&#xff08;Symbol&#xff09;的编码技术&#xff0c;由IBM工程师Al Widmer和Peter Franaszek于1983年提出。其核心思…...

软件工程之面向对象分析深度解析

前文基础&#xff1a; 1.软件工程学概述&#xff1a;软件工程学概述-CSDN博客 2.软件过程深度解析&#xff1a;软件过程深度解析-CSDN博客 3.软件工程之需求分析涉及的图与工具&#xff1a;软件工程之需求分析涉及的图与工具-CSDN博客 4.软件工程之形式化说明技术深度解…...

常见标签语言的对比

XML、JSON 和 YAML 是常见的数据序列化格式 相同点 结构化数据表示 三者均支持嵌套结构&#xff0c;能描述复杂的数据层级关系&#xff08;如对象、数组、键值对&#xff09;。跨平台兼容性 均为纯文本格式&#xff0c;可被多种编程语言解析&#xff0c;适用于跨系统数据交换…...

【Linux】环境变量(图文)

目录 一、main函数的参数解释&#xff1a; 1、argc和argc的解释 2、为什么要这样设置&#xff1f; 3、注意&#xff1a; 4、命令行计算器&#xff1a; 二、认识环境变量 三、见见环境变量 1、执行一个程序的前提 2、指令&#xff1a;echo $PATH 3、为什么系统自带的指令…...

基于OpenCV的人脸识别:EigenFaces算法

文章目录 引言一、概述二、代码解析1. 准备工作2. 加载训练图像3. 设置标签4. 准备测试图像5. 创建和训练识别器6. 进行预测7. 显示结果 三、代码要点总结 引言 人脸识别是计算机视觉领域的一个重要应用&#xff0c;今天我将通过一个实际案例来展示如何使用OpenCV中的EigenFac…...

跟我学C++中级篇——STL容器的查找对比

一、C标准库的查找 在C的STL中&#xff0c;对容器或相关序列的查找中&#xff0c;有两种方式&#xff0c;一种是std::find&#xff0c;另外一种是std::search。而且在它们的基础上&#xff0c;还衍生出std::find_if、std::find_if_not、std::find_end等和std::search_n、range…...

解构C++高级命名空间:构建空间作用域·控制兼容

前引&#xff1a;C作为C语言的继承者&#xff0c;也是其掘墓人。在编程语言的演化长河中&#xff0c;C始终游走在【兼容】与【革新】的路上。C程序员眼中&#xff08;高效直接&#xff09;的全局函数&#xff0c;对于C开发者来说是【命名空间污染的炸弹】&#xff0c;如果C未发…...

怎么判断是不是公网IP?如何查看自己本地路由器是内网ip还是公网?

在网络世界中&#xff0c;IP 地址如同每台设备的 “门牌号”&#xff0c;起着至关重要的标识作用。而 IP 地址又分为公网 IP 和私网 IP&#xff0c;准确判断一个 IP 属于哪一类&#xff0c;对于网络管理、网络应用开发以及理解网络架构等都有着重要意义。接下来&#xff0c;我们…...

微服务中 本地启动 springboot 无法找到nacos配置 启动报错

1. 此处的环境变量需要匹配nacos中yml配置文件名的后缀 对于粗心的小伙伴在切换【测试】【开发】环境的nacos使用时会因为这里导致项目总是无法启动成功...

android-ndk开发(11): 安装 repo 命令

1. 长话短说 mkdir ~/soft/bin curl -L https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo chmod x repo~/.pathrc 添加: export PATH$PATH:~/soft/bin2. 短话长说 repo 的官方介绍页面&#xff1a; https://gerrit.googlesource.com/git-repo/ repo 的官方下载地…...

【设计模式】GoF设计模式之策略模式(Strategy Pattern)

设计模式之策略模式 Strategy Pattern V1.0核心概念角色代码示例程序运行结果代码讲解 适用范围 V1.0 核心概念 策略模式是一种行为型设计模式&#xff0c;其核心思想是业务类执行某个动作时&#xff0c;可以使用该动作的不同的实现&#xff0c;并在程序运行中可以切换使用该…...

QT6(35)4.8定时器QTimer 与QElapsedTimer:理论,例题的界面搭建,与功能的代码实现。

&#xff08;112&#xff09; &#xff08;113&#xff09;模仿随书老师给的源代码搭建的&#xff0c; LCD 显示的部分不一样 &#xff1a; &#xff08;114&#xff09;以下开始代码完善&#xff1a; 关联定时器的信号与槽函数 &#xff1a; &#xff08;115&#xff09;…...

用Python监控金价并实现自动提醒!附完整源码

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【星海网址导航】&#x1f4bb;香港大宽带-4H4G 20M只要36/月&#x1f449; 点此查看详情 在日常投资中&#xff0c;很多朋友喜欢在一些平台买点黄金&#xff0c;低买高卖赚点小差价。但黄金价格实时波动频繁&#xf…...

加密领域 AI Agent 的崛起:DeFAI 如何重塑金融

原文&#xff1a;https://polkadot.com/blog/defai-crypto-ai-agents-explained/ 编译&#xff1a;OneBlock 一些创新大肆宣扬&#xff0c;另一些则在后台默默酝酿&#xff0c;不断迭代&#xff0c;直到它们突然无处不在&#xff0c;去中心化的金融系统也不例外。DeFi 解锁了…...

电位器如何接入西门子PLC的模拟量输入

1.设计思考 我现在手上有一个三线10kΩ的滑动变阻器&#xff0c;想让其当作模拟量接入西门子PLC中&#xff0c;外部改变电阻&#xff0c;PLC程序中能看到对应的阻值或电压&#xff0c;这样可以练习模拟量输入这个知识点&#xff01; 2.了解模拟量的种类 模拟量一般有电压型和…...

发那科机器人5(异常事件和程序备份加载+ROBOGUIDE离线仿真)

发那科机器人5(异常事件和程序备份加载+ROBOGUIDE离线仿真) 一,异常事件和程序备份加载1,常见异常事件2,零点复归介绍3,程序备份-加载(未整理)二,`ROBOGUIDE`离线仿真1,仿真软件简介及安装步骤(未整理)2,机器人==导入与工具==与==工件添加==2.1,机器人导入(未整…...