5.STM32之通信接口《精讲》之USART通信---实验串口接收程序

根据上节,我们一已经完成了串口发送程序的代码,并且深入的解析探索了串口的原理,接下来,Whappy小编将带领大家进入串口接收程序的探索与实验,并将结合上一节串口发送一起来完成串口的发送和接收实验。

上来两张图


上图为数据手册推荐的TX和RX的GPIO的配置模式!

代码逐步解释

  1. 设置波特率:

     

    c

    复制代码

    USART1_InitStructure.USART_BaudRate = 9600;

    • 配置串口的通信速率为 9600 bps,这决定了串口通信的速率。
  2. 硬件流控:

     

    c

    复制代码

    USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    • 不使用硬件流控制(如 RTS 和 CTS 信号)。默认只进行基本的 TX/RX 数据传输。
  3. 工作模式:

     

    c

    复制代码

    USART1_InitStructure.USART_Mode = USART_Mode_Tx;

    • 设置为发送模式(Tx),即该配置目前只支持数据发送,不包括接收。
  4. 校验位设置:

     

    c

    复制代码

    USART1_InitStructure.USART_Parity = USART_Parity_No;

    • 不使用奇偶校验位。
  5. 停止位:

     

    c

    复制代码

    USART1_InitStructure.USART_StopBits = USART_StopBits_1;

    • 设置 1 个停止位。
  6. 字长设置:

     

    c

    复制代码

    USART1_InitStructure.USART_WordLength = USART_WordLength_8b;

    • 设置字长为 8 位(不包括起始位、校验位和停止位)。
  7. 初始化 USART1:

     

    c

    复制代码

    USART_Init(USART1, &USART1_InitStructure);

    • 调用库函数对 USART1 进行初始化,应用上述配置。
  8. 使能 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 接收功能:

接收数据可以通过轮询方式或中断方式读取数据。

  1. 轮询方式: 使用 USART_ReceiveData 读取接收到的数据:

     

    c

    复制代码

    if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) { uint8_t received_data = USART_ReceiveData(USART1); // 读取数据 }

  2. 中断方式

    • 使能 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); // 读取接收到的数据 // 处理接收到的数据 } }

这个可以给大家说一下,目前以及以前学的都是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电源电压检测器,用于检测异常电压。提供电源保护。
GPIOGPIO通用输入输出接口,支持输入/输出/模拟模式。可复用为外设功能引脚。
安全外设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)通信是单片机中一种常用的通信方式,主要用于设备之间的数据交换。它的特点是通过串行数据传输,在硬件资源有限的情况下,能够高效地进行数据传输。

典型应用场景:

  1. 设备间通信

    • 常见场景:多个设备之间通过串口进行数据交换,比如在嵌入式系统中,多个传感器(温湿度传感器、光传感器等)通过串口将数据发送到主控单片机进行处理。
    • 实例:假设你在一个温度监测系统中,温度传感器通过串口向单片机发送温度数据,单片机接收到数据后进行处理,并根据温度值控制风扇的开关。
  2. 与计算机的通信

    • 常见场景:单片机通过串口与计算机进行通信,通常用于调试、数据传输和控制。
    • 实例:在开发过程中,单片机通过串口向计算机发送调试信息(例如温度、湿度数据或状态信息),开发者通过计算机监控这些数据。这种方式在嵌入式系统开发时非常常见。
  3. 调试与诊断

    • 常见场景:在开发嵌入式系统时,串口被广泛应用于调试信息的输出。通过串口输出数据或错误信息,帮助开发者进行调试。
    • 实例:开发过程中,单片机通过串口发送错误代码或状态信息,开发者通过串口终端查看这些信息,帮助调试程序。
  4. 无线通信模块

    • 常见场景:串口可以与无线模块(如蓝牙、Wi-Fi、Zigbee)配合使用,用于实现无线通信。
    • 实例:一个常见的应用是蓝牙模块(如HC-05),它通过串口与单片机连接,单片机通过串口接收来自手机的指令并进行相应操作。例如,用户通过手机上的蓝牙应用向单片机发送指令,控制家电(如开启灯光、调节温度等)。
  5. 外设控制

    • 常见场景:使用串口控制外部设备,如液晶显示屏、步进电机等。
    • 实例:在智能家居中,单片机通过串口控制一个LCD显示屏,显示实时温度、湿度等信息。用户通过串口发送命令,控制显示的内容。

详细示例:温湿度传感器通信

假设一个智能家居系统中有一个温湿度传感器(如DHT11),它通过串口(USART)与主控单片机(例如STM32)进行通信。工作流程如下:

  1. 发送数据:传感器通过串口发送温度和湿度数据。
  2. 接收数据:单片机接收传感器的数据,通过串口的接收缓冲区存储。
  3. 处理数据:单片机将接收到的数据进行解析,并根据预设的阈值执行相应操作,比如调节空调、打开加湿器或关闭风扇。
  4. 反馈:单片机还可以通过串口将处理后的数据(例如当前温度和湿度)发送回控制系统或计算机,便于远程监控。

总结:

串口通信在嵌入式系统中的应用非常广泛,不仅用于设备间的简单数据交换,还能支持各种外设的控制与调试。通过适当的配置和使用,串口通信可以实现有效的数据传输和设备控制。

例如:

场景描述:

在此应用中,我们假设使用一个温度传感器(例如DHT11或DHT22)通过串口(USART)将温度数据发送到单片机。单片机根据接收到的温度值来控制风扇的状态。如果温度高于预设的阈值,则风扇开启;如果温度低于阈值,则风扇关闭。

 

硬件连接:

  1. 温湿度传感器(DHT11/DHT22)通过串口(例如USART1)与STM32单片机连接。
  2. 风扇(例如继电器控制的风扇)由STM32单片机的GPIO引脚控制。

     

    代码实现:

  3. 初始化串口通信:初始化STM32的USART,用于接收温度传感器的数据。
  4. 接收数据:通过串口接收温度数据。
  5. 处理数据:根据接收到的温度值控制风扇的开关。
  6. 风扇控制:使用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);  // 关闭风扇}
    }
    

    代码解释:

  7. 串口初始化(USART_Init_Config)

    • 配置串口波特率为9600,启用接收和发送模式,并且没有硬件流控制。
    • 配置USART1的TX引脚(PA9)为推挽输出模式,RX引脚(PA10)为浮空输入模式。
  8. GPIO初始化(GPIO_Init_Config)

    • 配置风扇控制引脚(PA0)为推挽输出模式,用来控制风扇的开关。
  9. 串口接收数据(USART_PollingReceive)

    • 通过轮询方式检查串口接收标志(RXNE)。如果接收到数据,则读取数据并处理。
    • 假设温度传感器将数据以字符的形式发送(例如字符 '30' 表示30°C)。
    • 根据接收到的温度数据判断是否大于设定的阈值。如果温度超过阈值,调用 Fan_Control(1) 开启风扇,否则调用 Fan_Control(0) 关闭风扇。
  10. 风扇控制(Fan_Control)

    • 控制风扇的开关。如果参数 state 为1,开启风扇;如果为0,关闭风扇。

       

      总结:

      该系统通过串口接收温度数据并根据数据控制风扇的开关,属于典型的串口通信应用场景。通过串口通信,单片机能够与外部温湿度传感器进行数据交换,根据接收到的实时数据做出响应,从而实现温控系统的自动化。







      下一节我们将进行数据包以及多字节的数据发送与接收

      其中包括HEX数据包发送和文本格式数据包的发送与接收
      期待!!!!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474499.html

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

相关文章

leetcode 扫描线专题 06-leetcode.836 rectangle-overlap 力扣.836 矩形重叠

题目 矩形以列表 [x1, y1, x2, y2] 的形式表示&#xff0c;其中 (x1, y1) 为左下角的坐标&#xff0c;(x2, y2) 是右上角的坐标。 矩形的上下边平行于 x 轴&#xff0c;左右边平行于 y 轴。 如果相交的面积为 正 &#xff0c;则称两矩形重叠。 需要明确的是&#xff0c;只在…

ASP.NET MVC宠物商城系统

该系统采用B/S架构&#xff0c;使用C#编程语言进行开发&#xff0c;以ASP.NET MVC框架为基础&#xff0c;以Visual Studio 2019为开发工具&#xff0c;数据库采用SQL Server进行保存数据。系统主要功能包括登录注册、宠物展示、个人中心、我的订单、购物车、用户管理、宠物类别…

最优化方法_罚函数法例题

1 外点罚函数 算法1 外点罚函数法 给定初点&#xff0c;初始罚因子,放大系数&#xff0c;允许误差&#xff0c;置k1。以为初始点&#xff0c;求解无约束问题得最优解。如果,则停止计算&#xff0c;为约束问题的近似最优解&#xff1b;否 则&#xff0c;增大罚因子&#xff0c;令…

python调用MySql保姆级教程(包会的)

目录 一、下载MySql 二、安装MySql 三、验证MySql是否OK 1、MySQL控制台验证 2、命令提示符cmd窗口验证 四、Python调用MySql 4.1 安装pysql 4.2 使用pysql 4.2.1、连接数据库服务器并且创建数据库和表 4.2.2 、将人脸识别考勤系统识别到的数据自动填入到数据库的表单中…

【鸿蒙生态崛起,开发者有哪些机遇与挑战?】HarmonyOS NEXT 引领数字化未来

文章目录 前言一、HarmonyOS NEXT 特点与升级二、全面突破操作系统核心技术三、鸿蒙生态全面守护用户隐私四、鸿蒙生态的崛起与开发者机遇五、全新鸿蒙生态引领数字化未来小结 前言 鸿蒙系统不断发展&#xff0c;有与安卓、iOS 形成三足鼎立之势&#xff0c;且其在智能手机、智…

ssh无法连接Ubuntu

试了多次ssh都无法连接&#xff0c;明明可以上网 网卡、防火墙、端口都没有问题&#xff0c;就是连接不上 结果是这个版本Ubuntu镜像默认没有安装ssh服务 安装SSH服务&#xff1a;apt-get install openssh-server 开启SSH服务&#xff1a;/etc/init.d/ssh start 就可以连接…

基于Java Springboot外卖平台系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数…

vue2动态导出多级表头表格

需求&#xff1a;导出多级表格&#xff0c;如下&#xff0c;每个人名对应的是不同的城市金钱和年龄&#xff0c;日期占俩行&#xff0c;需要根据数据进行动态展示 1.效果 2.关键代码讲解 2.1数据源 2.2所需插件 npm install xlsx 2.3关键代码 创建name组和date组&#xff0c…

散户持股增厚工具:智能T0算法交易

最近市场很多都说牛市&#xff0c;但是大多数朋友怎么来的又怎么吐出去了。这会儿我们用T0的智能算法交易又可以增厚我们的持仓收益。简单来说&#xff0c;就是基于用户原有的股票持仓&#xff0c;针对同一标的&#xff0c;配合智能T0算法&#xff0c;每天全自动操作&#xff0…

独立开发:一人公司模式下副业产品的全流程

在数字经济的浪潮下&#xff0c;越来越多的开发者选择成为自由职业者或创立一人公司&#xff0c;通过副业产品开发实现个人价值与经济收益的双重提升。本文将围绕一人公司模式下副业产品的设计、开发、运营及变现落地全流程&#xff0c;提供一套实战指南&#xff0c;帮助有志于…

SD模型微调之Textual Inversion和Embedding fine-tuning

​ &#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&a…

【Vue笔记】基于vue3 + element-plus + el-dialog封装一个自定义的dialog弹出窗口组件

这篇文章,介绍一下如何使用vue3+element-plus中的el-dialog组件,自己封装一个通用的弹出窗口组件。运行效果如下所示: 目录 1.1、父子组件通信 1.2、自定义VDialog组件(【v-model】模式) 1.2.1、编写VDialog组件代码 1.2.2、使用VDialog组件 1.2.3、运行效果 1.3、自…

Spring Cloud Alibaba [Gateway]网关。

1 简介 网关作为流量的入口&#xff0c;常用功能包括路由转发、权限校验、限流控制等。而springcloudgateway 作为SpringCloud 官方推出的第二代网关框架&#xff0c;取代了Zuul网关。 1.1 SpringCloudGateway特点: &#xff08;1&#xff09;基于Spring5&#xff0c;支持响应…

不完全微分PID控制算法

不完全微分PID控制算法是一种改进的PID控制方法&#xff0c;主要针对PID控制中的微分环节对高频噪声敏感的问题。通过对微分项进行优化和改造&#xff0c;减少其对噪声的放大作用&#xff0c;同时保留对系统动态变化的响应能力。 不完全微分PID控制原理 不完全微分的核心思想是…

DataOps for LLM 的数据工程技术架构实践

导读 在 LLM 蓬勃发展的今天&#xff0c;数据工程已成为支持大规模 AI 模型训练的基石。DataOps 作为数据工程的重要方法论&#xff0c;通过优化数据集成、转换和自动化运维&#xff0c;加速数据到模型的闭环流程。本文聚焦新一代数据 & AI 集成工具- Apache SeaTunnel 在…

go-zero(七) RPC服务和ETCD

go-zero 实现 RPC 服务 在实际的开发中&#xff0c;我们是通过RPC来传递数据的&#xff0c;下面我将通过一个简单的示例&#xff0c;说明如何使用go-zero框架和 Protocol Buffers 定义 RPC 服务。 一、生成 RPC项目 在这个教程中&#xff0c;我们根据user.api文件&#xff0…

【c++丨STL】list模拟实现(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、节点、迭代器以及函数声明 二、list功能实现 1. 节点 2. 迭代器 迭代器的默认构造 operator* operator-> 前置和-- 后置和--…

SpringBoot:不支持发行版本17超详细解决办法

一开始linux中就已经下好了JDK21&#xff0c;但是后来创建项目的时候选用了JDK23&#xff0c;导致环境错乱&#xff0c;估计大部分都是因为这个原因&#xff0c;接下来我会一步步带大家解决。 检查系统环境&#xff08;以Ubuntu为例&#xff09; 没有下载JDK的可以在官网下载…

计算机网络中的数据包传输机制详解

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机网络中的数据包传输机制详解 计算机网络中的数据包传输机制详解 计算机网络中的数据包传输机制详解 引言 数据包的基本概念…

Springboot3.3.5 启动流程之 tomcat启动流程介绍

在文章 Springboot3.3.5 启动流程&#xff08;源码分析&#xff09; 中讲到 应用上下文&#xff08;applicationContext&#xff09;刷新(refresh)时使用模板方法 onRefresh 创建了 Web Server. 本文将详细介绍 ServletWebServer — Embedded tomcat 的启动流程。 首先&…