STM32CubeMX红外收发模块(串口)
两块开发板,一块接发送模块;一块接接收模块,实现一个开发板红外发送数据包控制另一个开发板LED的亮灭(数据包匹配)
一、红外发送模块
红外发送模块负责将电信号转换为红外光信号并发射出去。
红外发射管:940nm波长,辐射角度30°-60°,需串联限流电阻(常用100-200Ω)。
驱动电路:使用NPN三极管(如8050)或MOSFET(如2N7002)放大电流,由MCU的PWM引脚控制。
载波生成:通过STM32定时器输出38kHz PWM信号(占空比50%)。
二、红外接收模块
红外接收模块用于接收和解调红外信号,将其转换为电信号。
一体化接收头:如VS1838B(3引脚:VCC, GND, OUT),内置38kHz带通滤波和解调。
信号调理电路:OUT引脚接10kΩ上拉电阻,输出TTL电平信号至MCU串口接收RX引脚。
三、CubeMX配置
我使用的是stm32f030K6
RCC与SYS
波特率根据购买的来自己定
PWM调制看有没有相应的引脚配置,没有可以不加
计算:48MHz/[(32-1)*(40-1)]=37.5KHz≈38KHz
四、代码
UART.c
/** @Author: random* @Date: 2025-07-14 16:17:01* @Last Modified by: random* @Last Modified time: Do not Edit*/
// 串口封装函数
#include "UART.h"
#include "usart.h"
//#define debug
// 重定向函数,用于printf1
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}//=======================================================================接收===================================//
char rxdat[255+1]; // +1 用于字符串终止符
volatile uint8_t rx_count = 0;
uint8_t rxbuff;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){if (rx_count < 5){rxdat[rx_count++] = rxbuff;// 检查是否收到结束符if (rx_count == 4 && rxdat[0]== 0xAA && rxdat[3]== 0x55)//接收包头包尾,可自行修改{rxdat[rx_count] = '\0'; // 添加终止符
#ifdef debugLED_turn();
#endifrx_count = 0;}}else{// 缓冲区溢出处理rx_count = 0;memset(rxdat, 0, sizeof(rxdat));}HAL_UART_Receive_IT(&huart1, &rxbuff, 1);}
}//==========================================================================发送====================================//
#include "string.h"
#include "tim.h"// UART定义
#define IR_TX_UART huart1 // 使用UART1的PA9引脚发送// 发送状态
volatile uint8_t ir_sending = 0;
static uint8_t uart_buffer[64]; // UART发送缓冲区/*** @brief 启动PWM输出*/
static void IR_PWM_On(void)
{HAL_TIMEx_PWMN_Start(&htim17, TIM_CHANNEL_1);
}/*** @brief 停止PWM输出*/
static void IR_PWM_Off(void)
{HAL_TIMEx_PWMN_Stop(&htim17, TIM_CHANNEL_1);
}/*** @brief 微秒级延时* @param us 延时微秒数*/
static void IR_Delay_us(uint32_t us) {uint32_t delay = us * 48 ; // 假设每次循环3周期while (delay--) {__NOP(); // 1周期}
}/*** @brief 通过UART1(PA9)发送红外数据* @param data 要发送的数据* @param length 数据长度*/
void IR_SendData_UART(uint8_t *data, uint16_t length)
{if (data == NULL || length == 0 || length > sizeof(uart_buffer))return;if (!ir_sending){ir_sending = 1;// // 启动PWM载波IR_PWM_On();// 复制数据到缓冲区memcpy(uart_buffer, data, length);// 通过UART发送数据HAL_UART_Transmit_IT(&IR_TX_UART, uart_buffer, length);}
}/*** @brief 通过UART1发送NEC协议数据* @param address 设备地址* @param command 命令码*/
void IR_SendNEC_UART(uint8_t address, uint8_t command)//可自行修改匹配
{uint8_t data[4];// NEC协议: 地址 + 命令 + 命令反码 + 地址反码data[0] = address;data[1] = command;data[2] = ~command;data[3] = ~address;IR_SendData_UART(data, 4);
}/*** @brief UART发送完成回调函数* @param huart UART句柄*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){// 关闭PWM载波IR_PWM_Off();ir_sending = 0;}
}
UART.h
/** @Author: random* @Date: 2025-07-14 16:17:15* @Last Modified by: random* @Last Modified time: Do not Edit*/
#ifndef _UART_H
#define _UART_H#include "main.h"
int fputc(int ch, FILE *f);//==============================
static void IR_PWM_On(void);
static void IR_PWM_Off(void);//==============================
void IR_SendData_UART(uint8_t *data, uint16_t length);
void IR_SendNEC_UART(uint8_t address, uint8_t command);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);#endif
发送模块main.c
//初始化HAL_UART_Receive_IT(&huart1, &rxbuff, 1);HAL_TIMEx_PWMN_Start(&htim17, TIM_CHANNEL_1);char t[4]={0x01,0x02,0x03,0x04}; uint8_t t_count = 0;while (1){IR_SendNEC_UART(0xAA,t[t_count++]);if(t_count == 4)t_count = 0;Delay_ms(1000);}
接收模块main.c
while (1){if(rxdat[1] ==0x01)//灯灭{LED_OFF(LED_CHARG); //LED_OFF(LED_FREE); //LED_OFF(LED_LOAD); //}else if(rxdat[1] ==0x02)//蓝{LED_ON(LED_CHARG); //LED_OFF(LED_FREE); //LED_OFF(LED_LOAD); //}else if(rxdat[1] ==0x03)//红{LED_OFF(LED_CHARG); //LED_ON(LED_FREE); //LED_OFF(LED_LOAD); //}else if(rxdat[1] ==0x04)//绿{LED_OFF(LED_CHARG); //LED_OFF(LED_FREE); //LED_ON(LED_LOAD); //}else{LED_OFF(LED_CHARG); //LED_OFF(LED_FREE); //LED_OFF(LED_LOAD); //}
debug实时更新接收数据包