5.STM32之通信接口《精讲》之USART通信---实验串口接收程序
根据上节,我们一已经完成了串口发送程序的代码,并且深入的解析探索了串口的原理,接下来,Whappy小编将带领大家进入串口接收程序的探索与实验,并将结合上一节串口发送一起来完成串口的发送和接收实验。
上来两张图


上图为数据手册推荐的TX和RX的GPIO的配置模式!
代码逐步解释
-
设置波特率:
c
复制代码
USART1_InitStructure.USART_BaudRate = 9600;
- 配置串口的通信速率为 9600 bps,这决定了串口通信的速率。
-
硬件流控:
c
复制代码
USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- 不使用硬件流控制(如 RTS 和 CTS 信号)。默认只进行基本的 TX/RX 数据传输。
-
工作模式:
c
复制代码
USART1_InitStructure.USART_Mode = USART_Mode_Tx;
- 设置为发送模式(
Tx
),即该配置目前只支持数据发送,不包括接收。
- 设置为发送模式(
-
校验位设置:
c
复制代码
USART1_InitStructure.USART_Parity = USART_Parity_No;
- 不使用奇偶校验位。
-
停止位:
c
复制代码
USART1_InitStructure.USART_StopBits = USART_StopBits_1;
- 设置 1 个停止位。
-
字长设置:
c
复制代码
USART1_InitStructure.USART_WordLength = USART_WordLength_8b;
- 设置字长为 8 位(不包括起始位、校验位和停止位)。
-
初始化 USART1:
c
复制代码
USART_Init(USART1, &USART1_InitStructure);
- 调用库函数对 USART1 进行初始化,应用上述配置。
-
使能 USART1:
c
复制代码
USART_Cmd(USART1, ENABLE);
- 启用 USART1 外设。
如何添加接收功能
要使能接收功能,需要将 USART_Mode
设置为接收模式或同时支持发送和接收模式,并适配相应的 GPIO 引脚(如 RX 引脚)。
修改代码:
c
复制代码
USART1_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
添加接收引脚的初始化:
初始化 GPIOA 的 PA10
(USART1 RX)为浮空输入或上拉输入模式:
c
复制代码
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);
使用 USART 接收功能:
接收数据可以通过轮询方式或中断方式读取数据。
-
轮询方式: 使用
USART_ReceiveData
读取接收到的数据:c
复制代码
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) { uint8_t received_data = USART_ReceiveData(USART1); // 读取数据 }
-
中断方式:
- 使能 USART1 的接收中断:
c
复制代码
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); NVIC_EnableIRQ(USART1_IRQn); // 使能中断
- 在中断处理函数中读取数据:
c
复制代码
void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t received_data = USART_ReceiveData(USART1); // 读取接收到的数据 // 处理接收到的数据 } }
- 使能 USART1 的接收中断:
这个可以给大家说一下,目前以及以前学的都是STM32内部集成的外设
在这里Whappy给大家整理一下,也可以看对应的数据手册

以下是 STM32 内部外设整理的表格,适合 A4 大小打印:
分类 | 外设名称 | 功能描述 | 备注 |
---|---|---|---|
通信外设 | USART/UART | 串口通信,支持异步传输,部分支持 LIN、IrDA、Modbus。 | 常用作调试串口和外设通信。 |
SPI | 全双工同步通信,用于连接传感器、存储设备等。 | 常用于高速短距离数据传输。 | |
I2C | 主从同步通信协议,连接低速设备(如 EEPROM、传感器)。 | 适用于多设备共享通信总线。 | |
CAN | 工业控制和汽车通信网络。 | 适合实时和抗干扰场景。 | |
USB | 支持设备/主机/OTG 模式,可实现与 PC 的通信。 | 部分型号支持 USB 2.0。 | |
Ethernet | 网络通信接口,用于数据网络传输。 | 高性能型号支持。 | |
SDIO | 与 SD 卡或 MMC 卡通信。 | 常用于外部存储扩展。 | |
定时器外设 | 通用定时器(TIMx) | PWM 生成、定时、中断产生、脉冲计数等。 | 提供灵活的定时功能。 |
高级定时器 | 支持复杂 PWM,适合电机控制场景。 | 例如:TIM1、TIM8。 | |
基础定时器 | 用于简单的时间基准,如滴答定时器。 | 例如:TIM6、TIM7。 | |
看门狗定时器 | 独立看门狗和窗口看门狗,用于提高系统容错性。 | 防止程序跑飞。 | |
模拟外设 | ADC | 多通道模数转换,通常为 12 位分辨率。 | 部分型号支持 16 位高精度 ADC。 |
DAC | 数模转换,将数字信号输出为模拟电压。 | 用于波形生成。 | |
比较器 | 模拟信号比较,可实现过零检测。 | 多用于实时保护电路。 | |
运算放大器 | 集成模拟放大电路,便于信号处理。 | 仅部分高端型号支持。 | |
存储外设 | 闪存(Flash Memory) | 存储程序代码,支持在线擦写。 | 用于固件存储。 |
SRAM | 数据存储,静态随机存储器。 | 易失性存储器。 | |
EEPROM | 保存配置数据,非易失性存储器。 | 部分型号支持内置。 | |
控制与管理外设 | DMA | 提高数据传输效率,减少 CPU 干预。 | 用于大数据量传输场景。 |
RTC | 提供低功耗实时时钟,支持日期和时间功能。 | 适合低功耗应用。 | |
电源管理模块 | 支持睡眠、停止、待机模式。 | 降低能耗。 | |
PVD | 电源电压检测器,用于检测异常电压。 | 提供电源保护。 | |
GPIO | GPIO | 通用输入输出接口,支持输入/输出/模拟模式。 | 可复用为外设功能引脚。 |
安全外设 | CRC | 提供数据完整性校验。 | 用于通信或存储校验。 |
TRNG | 真随机数生成器,用于加密。 | 常见于安全应用。 | |
硬件加密引擎 | 支持 AES、SHA 等硬件加速算法。 | 提高加密运算效率。 | |
显示外设 | LCD 控制器 | 驱动 LCD 显示屏,支持多种接口标准。 | 仅部分型号支持。 |
FSMC/FMC | 支持连接外部存储器或显示屏。 | 高性能型号提供支持。 | |
特殊外设 | 触摸感应控制器 | 支持触摸按键或触摸屏检测。 | 用于人机交互设计。 |
硬件 DIV/SQRT | 硬件实现除法与开方运算,提高效率。 | 部分型号支持。 |
不同 STM32 系列(如 F1、F4、H7 等)外设配置有所差异,实际使用时需查阅对应芯片的参考手册
代码加入部分!
配置接收部分,只需另初始化一下GPIOA的PA10即可,然后在初始化的串口模式配置中或上一个接收部分的模式即可!
接收部分!有查询和中断模式,下面分别演示一下这个模式
在 STM32 或嵌入式开发中,轮询方式和中断方式是两种常用的外设数据处理方式。两者的核心区别在于程序对外设事件的响应机制:
1. 轮询方式
工作原理
- 程序不断检查某个标志位(例如,USART 的接收标志位
USART_FLAG_RXNE
),当标志位被设置时,执行相应操作。 - 轮询方式是同步的,程序在等待某个事件发生时无法执行其他任务。
优点
- 实现简单,不需要配置中断。
- 不涉及中断优先级,代码逻辑直观。
缺点
- 占用 CPU 时间:程序不断地检查标志位,会浪费大量 CPU 时间。
- 不适合实时性高或需要处理多任务的场景。
void USART_PollingReceive(void) {uint8_t received_data;while (1) {// 检查 RXNE 标志位,判断是否有数据可读if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {// 读取数据received_data = USART_ReceiveData(USART1);// 处理接收到的数据printf("Received: %c\n", received_data);}}
}
执行流程:
- 程序进入一个无限循环。
- 持续检查
USART_FLAG_RXNE
是否置位。 - 如果有数据,则读取处理。
2. 中断方式
工作原理
- 程序无需主动检查某个标志位。外设事件发生(例如 USART 接收到数据)时,自动触发中断,CPU 跳转到中断服务程序执行预设操作。
- 中断方式是异步的,外设与主程序解耦,CPU 能处理其他任务。
优点
- 高效:CPU 只在外设有事件发生时响应,不浪费时间。
- 支持实时性要求高的场景。
- 易于实现多任务系统的并行性。
缺点
- 实现较复杂,需要配置中断向量表、优先级等。
- 如果中断处理时间过长,可能影响系统的实时性。
示例代码
以下是基于 USART 的中断接收数据的示例:
void USART_InterruptInit(void) {// USART 初始化略(同之前的代码)// 启用 USART 接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 配置 NVIC(中断控制器)NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
void USART1_IRQHandler(void) {uint8_t received_data;// 检查是否是接收中断if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {// 读取接收到的数据received_data = USART_ReceiveData(USART1);// 处理接收到的数据printf("Interrupt Received: %c\n", received_data);// 清除中断标志位(库函数自动完成)}
}
执行流程:
- 当 USART 接收到数据时,硬件自动触发中断。
- CPU 跳转到
USART1_IRQHandler
中断服务函数执行处理。 - 处理完成后,CPU 返回主程序继续执行其他任务。

轮询模式:
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
#include "Delay.h"void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 选择引脚13GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIO//串口发送初始化GPIO_InitTypeDef GPIO_InitStructrue;GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 串口发送的TXGPIO_InitStructrue.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructrue);//串口接收GPIO初始化GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPU; //上拉输入GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_10;
// GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructrue);//内部外设USART1初始化USART_InitTypeDef USART1_InitStructure;USART1_InitStructure.USART_BaudRate = 9600;USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART1_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART1_InitStructure.USART_Parity = USART_Parity_No ;USART1_InitStructure.USART_StopBits = USART_StopBits_1;USART1_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1,&USART1_InitStructure);USART_Cmd(USART1,ENABLE);}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1,Byte);while ((USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET));
}void Serial_SendArray(uint8_t* Array, uint8_t Lenght)
{uint16_t i;for(i=0; i<Lenght; i++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char* String)
{uint8_t i;for(i=0; String[i] != '\0'; i++){Serial_SendByte(String[i]);}
}uint32_t Result(uint32_t X, uint32_t Y)
{uint8_t result = 1;while(Y--){result = result * X;}return result;
}void Serial_SendNum(uint32_t Num, uint16_t Lenght)
{uint16_t i;uint32_t ww;for(i=Lenght; i>0; i--){ww = Result(10,i-1);Serial_SendByte((Num/ww )% 10 + '0');}}int fputc(int ch, FILE* f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char* format, ...)
{char String[100];va_list arg;va_start(arg,format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}重定向C库函数printf()到串口,重定向后可使用printf();
//int fputc(int ch,FILE *f)
//{
// USART_SendData(USART1,(uint8_t)ch);
// while(!(USART_GetFlagStatus(USART1,USART_FLAG_TC)));
// return ch;
//}void USART_PollingReceive(void) {uint8_t received_data;Serial_Printf("Please enter the book command: ");while (1) {// 检查 RXNE 标志位,判断是否有数据可读if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {// 读取数据received_data = USART_ReceiveData(USART1);// 只有在接收到'3'时才处理接收的数据if (received_data == '3') {// 点亮LEDGPIO_SetBits(GPIOA, GPIO_Pin_4); // 点亮LED// 处理接收到的数据printf("Received: %c\n", received_data);// 等待一段时间,模拟LED点亮一段时间后熄灭(可选)Delay_ms(1000); // 延时1000ms,具体延时函数需要根据你的环境定义// 熄灭LEDGPIO_ResetBits(GPIOA, GPIO_Pin_4); // 熄灭LED} else {// 如果接收到的不是'3',则继续等待printf("Invalid command received: %c\n", received_data);}}}
}
中断模式:
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
#include "Delay.h"void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 选择引脚13GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIO//串口发送初始化GPIO_InitTypeDef GPIO_InitStructrue;GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 串口发送的TXGPIO_InitStructrue.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructrue);//串口接收GPIO初始化GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPU; //上拉输入GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_10;
// GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructrue);//内部外设USART1初始化USART_InitTypeDef USART1_InitStructure;USART1_InitStructure.USART_BaudRate = 9600;USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART1_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART1_InitStructure.USART_Parity = USART_Parity_No ;USART1_InitStructure.USART_StopBits = USART_StopBits_1;USART1_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1,&USART1_InitStructure);USART_Cmd(USART1,ENABLE);//开启中断USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC配置NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1,Byte);while ((USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET));
}void Serial_SendArray(uint8_t* Array, uint8_t Lenght)
{uint16_t i;for(i=0; i<Lenght; i++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char* String)
{uint8_t i;for(i=0; String[i] != '\0'; i++){Serial_SendByte(String[i]);}
}uint32_t Result(uint32_t X, uint32_t Y)
{uint8_t result = 1;while(Y--){result = result * X;}return result;
}void Serial_SendNum(uint32_t Num, uint16_t Lenght)
{uint16_t i;uint32_t ww;for(i=Lenght; i>0; i--){ww = Result(10,i-1);Serial_SendByte((Num/ww )% 10 + '0');}}int fputc(int ch, FILE* f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char* format, ...)
{char String[100];va_list arg;va_start(arg,format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}重定向C库函数printf()到串口,重定向后可使用printf();
//int fputc(int ch,FILE *f)
//{
// USART_SendData(USART1,(uint8_t)ch);
// while(!(USART_GetFlagStatus(USART1,USART_FLAG_TC)));
// return ch;
//}void USART_PollingReceive(void) {uint8_t received_data;Serial_Printf("Please enter the book command: ");while (1) {// 检查 RXNE 标志位,判断是否有数据可读if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {// 读取数据received_data = USART_ReceiveData(USART1);// 只有在接收到'3'时才处理接收的数据if (received_data == '3') {// 点亮LEDGPIO_SetBits(GPIOA, GPIO_Pin_4); // 点亮LED// 处理接收到的数据printf("Received: %c\n", received_data);// 等待一段时间,模拟LED点亮一段时间后熄灭(可选)Delay_ms(1000); // 延时1000ms,具体延时函数需要根据你的环境定义// 熄灭LEDGPIO_ResetBits(GPIOA, GPIO_Pin_4); // 熄灭LED} else {// 如果接收到的不是'3',则继续等待printf("Invalid command received: %c\n", received_data);}}}
}//USART中断入口函数void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE)){uint16_t ReceiveData = USART_ReceiveData(USART1); USART_SendData(USART1,ReceiveData);while (USART_GetFlagStatus(USART1,USART_FLAG_RXNE));USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
结尾了我要总结一下:
串口(USART)通信是单片机中一种常用的通信方式,主要用于设备之间的数据交换。它的特点是通过串行数据传输,在硬件资源有限的情况下,能够高效地进行数据传输。
典型应用场景:
-
设备间通信:
- 常见场景:多个设备之间通过串口进行数据交换,比如在嵌入式系统中,多个传感器(温湿度传感器、光传感器等)通过串口将数据发送到主控单片机进行处理。
- 实例:假设你在一个温度监测系统中,温度传感器通过串口向单片机发送温度数据,单片机接收到数据后进行处理,并根据温度值控制风扇的开关。
-
与计算机的通信:
- 常见场景:单片机通过串口与计算机进行通信,通常用于调试、数据传输和控制。
- 实例:在开发过程中,单片机通过串口向计算机发送调试信息(例如温度、湿度数据或状态信息),开发者通过计算机监控这些数据。这种方式在嵌入式系统开发时非常常见。
-
调试与诊断:
- 常见场景:在开发嵌入式系统时,串口被广泛应用于调试信息的输出。通过串口输出数据或错误信息,帮助开发者进行调试。
- 实例:开发过程中,单片机通过串口发送错误代码或状态信息,开发者通过串口终端查看这些信息,帮助调试程序。
-
无线通信模块:
- 常见场景:串口可以与无线模块(如蓝牙、Wi-Fi、Zigbee)配合使用,用于实现无线通信。
- 实例:一个常见的应用是蓝牙模块(如HC-05),它通过串口与单片机连接,单片机通过串口接收来自手机的指令并进行相应操作。例如,用户通过手机上的蓝牙应用向单片机发送指令,控制家电(如开启灯光、调节温度等)。
-
外设控制:
- 常见场景:使用串口控制外部设备,如液晶显示屏、步进电机等。
- 实例:在智能家居中,单片机通过串口控制一个LCD显示屏,显示实时温度、湿度等信息。用户通过串口发送命令,控制显示的内容。
详细示例:温湿度传感器通信
假设一个智能家居系统中有一个温湿度传感器(如DHT11),它通过串口(USART)与主控单片机(例如STM32)进行通信。工作流程如下:
- 发送数据:传感器通过串口发送温度和湿度数据。
- 接收数据:单片机接收传感器的数据,通过串口的接收缓冲区存储。
- 处理数据:单片机将接收到的数据进行解析,并根据预设的阈值执行相应操作,比如调节空调、打开加湿器或关闭风扇。
- 反馈:单片机还可以通过串口将处理后的数据(例如当前温度和湿度)发送回控制系统或计算机,便于远程监控。
总结:
串口通信在嵌入式系统中的应用非常广泛,不仅用于设备间的简单数据交换,还能支持各种外设的控制与调试。通过适当的配置和使用,串口通信可以实现有效的数据传输和设备控制。
例如:
场景描述:
在此应用中,我们假设使用一个温度传感器(例如DHT11或DHT22)通过串口(USART)将温度数据发送到单片机。单片机根据接收到的温度值来控制风扇的状态。如果温度高于预设的阈值,则风扇开启;如果温度低于阈值,则风扇关闭。
硬件连接:
- 温湿度传感器(DHT11/DHT22)通过串口(例如USART1)与STM32单片机连接。
- 风扇(例如继电器控制的风扇)由STM32单片机的GPIO引脚控制。
代码实现:
- 初始化串口通信:初始化STM32的USART,用于接收温度传感器的数据。
- 接收数据:通过串口接收温度数据。
- 处理数据:根据接收到的温度值控制风扇的开关。
- 风扇控制:使用GPIO控制风扇。
#include "stm32f10x.h" #include <stdio.h>#define FAN_PIN GPIO_Pin_0 // 假设风扇连接在GPIOA的Pin 0 #define TEMP_THRESHOLD 30 // 设定的温度阈值,单位:摄氏度void USART_Init_Config(void); void GPIO_Init_Config(void); void USART_PollingReceive(void); void Fan_Control(uint8_t state);int main(void) {// 初始化串口和GPIOUSART_Init_Config();GPIO_Init_Config();// 无限循环,定期检查接收到的数据while (1) {USART_PollingReceive(); // 等待并接收温度数据} }void USART_Init_Config(void) {// 初始化USART1RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // USART1_TXGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // USART1_RXGPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600; // 波特率9600USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送和接收模式USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE); }void GPIO_Init_Config(void) {// 初始化风扇控制GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = FAN_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); }void USART_PollingReceive(void) {uint8_t received_data;// 检查RXNE标志位,判断是否有数据可读if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {// 读取接收到的数据received_data = USART_ReceiveData(USART1);// 打印接收到的数据printf("Received temperature: %c\n", received_data);// 判断温度数据,并控制风扇if (received_data >= TEMP_THRESHOLD) {Fan_Control(1); // 温度超过阈值,开启风扇} else {Fan_Control(0); // 温度低于阈值,关闭风扇}} }void Fan_Control(uint8_t state) {// 控制风扇的开关if (state == 1) {GPIO_SetBits(GPIOA, FAN_PIN); // 开启风扇} else {GPIO_ResetBits(GPIOA, FAN_PIN); // 关闭风扇} }
代码解释:
-
串口初始化(USART_Init_Config):
- 配置串口波特率为9600,启用接收和发送模式,并且没有硬件流控制。
- 配置USART1的TX引脚(PA9)为推挽输出模式,RX引脚(PA10)为浮空输入模式。
-
GPIO初始化(GPIO_Init_Config):
- 配置风扇控制引脚(PA0)为推挽输出模式,用来控制风扇的开关。
-
串口接收数据(USART_PollingReceive):
- 通过轮询方式检查串口接收标志(RXNE)。如果接收到数据,则读取数据并处理。
- 假设温度传感器将数据以字符的形式发送(例如字符
'30'
表示30°C)。 - 根据接收到的温度数据判断是否大于设定的阈值。如果温度超过阈值,调用
Fan_Control(1)
开启风扇,否则调用Fan_Control(0)
关闭风扇。
-
风扇控制(Fan_Control):
- 控制风扇的开关。如果参数
state
为1,开启风扇;如果为0,关闭风扇。
总结:
该系统通过串口接收温度数据并根据数据控制风扇的开关,属于典型的串口通信应用场景。通过串口通信,单片机能够与外部温湿度传感器进行数据交换,根据接收到的实时数据做出响应,从而实现温控系统的自动化。
下一节我们将进行数据包以及多字节的数据发送与接收
其中包括HEX数据包发送和文本格式数据包的发送与接收
期待!!!!!!
- 控制风扇的开关。如果参数
相关文章:

5.STM32之通信接口《精讲》之USART通信---实验串口接收程序
根据上节,我们一已经完成了串口发送程序的代码,并且深入的解析探索了串口的原理,接下来,Whappy小编将带领大家进入串口接收程序的探索与实验,并将结合上一节串口发送一起来完成串口的发送和接收实验。 上来两张图 上图…...

【Redis_Day6】Hash类型
【Redis_Day6】Hash类型 Hash类型操作hash的命令hset:设置hash中指定的字段(field)的值(value)hsetnx:想hash中添加字段并设置值hget:获取hash中指定字段的值hexists:判断hash中是否…...

[开源] SafeLine 好用的Web 应用防火墙(WAF)
SafeLine,中文名 “雷池”,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击 一、简介 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注…...

40分钟学 Go 语言高并发:Select多路复用
Select多路复用 学习目标 知识点掌握程度应用场景select实现原理深入理解底层机制channel通信和多路选择超时处理掌握超时控制方法避免阻塞和资源浪费优先级控制理解优先级实现处理多个channel的顺序性能考虑了解性能优化点高并发场景优化 1. Select实现原理 让我们通过一个…...

candence: 如何快速设置SUBCLASS 的颜色
如何快速设置SUBCLASS 的颜色 一、一般操作 正常情况下修改SUBCLASS,需要如下步骤进行设置: 二、快速操作 右键,选择一个颜色即可...

FinalShell进行前端项目部署及nginx配置
首先需要准备服务器(阿里云、腾讯云都可)与域名; 示例为阿里云服务器; 1.进行FinalShell下载 下载官网 https://www.hostbuf.com/ 2.下载完毕后 配置FinalShell ssh 名称自定义即可! 2-1 提示连接成功 3.首先检查nginx是否下载 …...

神经网络(系统性学习一):入门篇——简介、发展历程、应用领域、基本概念、超参数调优、网络类型分类
相关文章: 神经网络中常用的激活函数 神经网络简介 神经网络(Neural Networks)是受生物神经系统启发而设计的数学模型,用于模拟人类大脑处理信息的方式。它由大量的节点(或称为“神经元”)组成࿰…...

用nextjs开发时遇到的问题
这几天已经基本把node后端的接口全部写完了,在前端开发时考虑时博客视频类型,考虑了ssr,于是选用了nextJs,用的是nextUi,tailwincss,目前碰到两个比较难受的事情。 1.nextUI个别组件无法在服务器段渲染 目前简单的解决方法&…...

微前端基础知识入门篇(二)
概述 在上一篇介绍了一些微前端的基础知识,详见微前端基础知识入门篇(一)。本文主要介绍qiankun微前端框架的实战入门内容。 qiankun微前端实践 通过Vite脚手架分别创建三个程序,主应用A为:vite+vue3+ts,两个微应用分别为B:vite+vue3+ts;C:vite+React+ts。因为qiankun的…...

自然语言处理:第六十五章 MinerU 开源PDF文档解析方案
本人项目地址大全:Victor94-king/NLP__ManVictor: CSDN of ManVictor 原文地址:MinerU:精准解析PDF文档的开源解决方案 论文链接:MinerU: An Open-Source Solution for Precise Document Content Extraction git地址࿱…...

Arcpy 多线程批量重采样脚本
Arcpy 多线程批量重采样脚本 import arcpy import os import multiprocessingdef resample_tifs(input_folder, output_folder, cell_size0.05, resampling_type"BILINEAR"):"""将指定文件夹下的所有 TIFF 文件重采样到指定分辨率,并输出…...

python 画图例子
目录 多组折线图点坐标的折线图 多组折线图 数据: 第1行为x轴标签第2/3/…行等为数据,其中第一列为标签,后面为y值 图片: 代码: import matplotlib.pyplot as plt# 原始数据字符串 # 第1行为x轴标签 # 第2/3/...行等为数据,其中第一列为标签,后面…...

Win11 22H2/23H2系统11月可选更新KB5046732发布!
系统之家11月22日报道,微软针对Win11 22H2/23H2版本推送了2024年11月最新可选更新补丁KB5046732,更新后,系统版本号升至22621.4541和22631.4541。本次更新后系统托盘能够显示缩短的日期和时间,文件资源管理器窗口很小时搜索框被切…...

【STM32】MPU6050初始化常用寄存器说明及示例代码
一、MPU6050常用配置寄存器 1、电源管理寄存器1( PWR_MGMT_1 ) 此寄存器允许用户配置电源模式和时钟源。 DEVICE_RESET :用于控制复位的比特位。设置为1时复位 MPU6050,内部寄存器恢复为默认值,复位结束…...

深度学习中的mAP
在深度学习中,mAP是指平均精度均值(mean Average Precision),它是深度学习中评价模型好坏的一种指标(metric),特别是在目标检测中。 精确率和召回率的概念: (1).精确率(Precision):预测阳性结果中实际正确的比例(TP / …...

Redis设计与实现 学习笔记 第二十章 Lua脚本
Redis从2.6版本引入对Lua脚本的支持,通过在服务器中嵌入Lua环境,Redis客户端可以使用Lua脚本,直接在服务器端原子地执行多个Redis命令。 其中EVAL命令可以直接对输入的脚本进行求值: 而使用EVALSHA命令则可以根据脚本的SHA1校验…...

大模型(LLMs)推理篇
大模型(LLMs)推理篇 1. 为什么大模型推理时显存涨的那么多还一直占着? 首先,序列太长了,有很多Q/K/V;其次,因为是逐个预测next token,每次要缓存K/V加速解码。 大模型在gpu和cpu上…...

Leetcode 412. Fizz Buzz
Problem Given an integer n, return a string array answer (1-indexed) where: answer[i] “FizzBuzz” if i is divisible by 3 and 5.answer[i] “Fizz” if i is divisible by 3.answer[i] “Buzz” if i is divisible by 5.answer[i] i (as a string) if none of t…...

双因子认证:统一运维平台安全管理策略
01双因子认证概述 双因子认证(Two-Factor Authentication,简称2FA)是一种身份验证机制,它要求用户提供两种不同类型的证据来证明自己的身份。这通常包括用户所知道的(如密码)、用户所拥有的(如…...

CMake笔记:install(TARGETS target,...)无法安装的Debug/lib下
1. 问题描述 按如下CMake代码,无法将lib文件安装到Debug/lib或Release/lib目录下,始终安装在CMAKE_INSTALL_PREFIX/lib下。 install(TARGETS targetCONFIGURATIONS DebugLIBRARY DESTINATION Debug/lib) install(TARGETS targetCONFIGURATIONS Release…...

使用ENSP实现NAT
一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30 ip address 12.12.12.1 30进入e0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置…...

漫步北京小程序构建智慧出行,打造旅游新业态模式
近年来,北京市气象服务中心持续加强推进旅游气象服务,将旅游气象监测预警基础设施纳入景区配套工程,提升气象和旅游融合发展水平,服务建设高品质智慧旅游强市。 天气条件往往影响着旅游景观的体验,北京万云科技有限公…...

对齐输出
对齐输出 C语言代码C 语言代码Java语言代码Python语言代码 💐The Begin💐点点关注,收藏不迷路💐 输入三个整数,按每个整数占8个字符的宽度,右对齐输出它们。 输入 只有一行,包含三个整数&…...

Wekan看板安装部署与使用介绍
Wekan看板安装部署与使用介绍 1. Wekan简介 Wekan 是一个开源的看板式项目管理工具,它的配置相对简单,因为大多数功能都是开箱即用的。它允许用户以卡片的形式组织和跟踪任务,非常适合敏捷开发和日常任务管理。Wekan 的核心功能包括看板…...

VisionPro 机器视觉案例 之 黑色齿轮
第十五篇 机器视觉案例 之 齿轮齿数检测 文章目录 第十五篇 机器视觉案例 之 齿轮齿数检测1.案例要求2.实现思路2.1 统计齿轮齿数使用模板匹配工具CogPMAlignTool,并从模板匹配工具的结果集中得到每一个齿的中心点。2.2 测量距离需要知道两个坐标点,一个…...

学习python的第十三天之数据类型——函数传参中的传值和传址问题
学习python的第十三天之数据类型——函数传参中的传值和传址问题 函数传参中的传值和传址问题 函数传参的机制可以理解为传值(pass-by-value)和传址(pass-by-reference)的混合体,但实际上更接近于传对象引用ÿ…...

Windows11深度学习环境配置
CUDA、CUDNN 一、安装另一个版本的CUDA 下载.exe文件,网址打不开自己开热点就能解决:CUDA Toolkit 11.2 Downloads | NVIDIA Developer 若遇到“You already have a newer version of the NVIDIA Frameview SDK installed” 1.把电脑已经存在的FrameVi…...

电销老是被标记,该如何解决!!!
在当今的商业世界中,电话销售依然是许多企业拓展业务、接触客户的重要手段。然而,电销人员常常面临一个令人头疼的问题 —— 老是被标记。 一、电销被标记的困扰 当你的电话号码被频繁标记为 “骚扰电话”“推销电话” 等,会带来一系列不良…...

MyBatis入门——基本的增删改查
目录 一、MyBatis简介 二、搭建MyBatis (一)配置依赖 (二)log4j日志功能 (三)数据库配置文件——jdbc.properties (四)创建MyBatis的核心配置文件 (五)使用MyBatisX插件 三、项目其他配置搭建 (一)创建数据库连接工具类 (二)创建表 (三)创建数据库的实体类 (四)Use…...

学习Gentoo系统中二进制软件包和源代码包的概念
Gentoo Linux 是一个以源代码包管理和高度定制化特性著称的Linux发行版。以下是关于Gentoo系统中二进制软件包和源代码包的概念、发展历程以及它们各自的优势: 二进制软件包概念及发展历程: 概念:Gentoo的二进制软件包是指预先编译好的软件包…...