# CH32V003 与 TFDU4101 红外通信测试:低成本红外数据传输方案
## 一、测试目的
官方没有给出历程,想学习一下配置irDA模式的串口
## 二、硬件准备
### 1. 核心器件清单
主控 MCU:CH32V003F4P6(SOP8 封装,72MHz 主频,内置 USART、GPIO 等外设)
红外模块:TFDU4101(集成红外发送器与接收器,支持 38kHz 载波,3.3V 供电)
辅助元件:10kΩ 上拉电阻(按键用)、1kΩ 限流电阻(LED 用)、3.3V 电源模块(或 USB 转 3.3V)
工具:烧录器、杜邦线、示波器(可选,用于信号调试)
TFDU4101 引脚定义
原理图如下
### 2. 硬件连接表
CH32V003 引脚 TFDU4101 引脚 功能说明 备注
PD5 RX 红外模块接收端(数据输入) USART1_TX,
PD6 TX 红外模块发送端(数据输出) USART1_RX,
PD3 LED 正极 接收成功指示灯 LED 负极串 1kΩ 电阻接 GND
3.3V VCC 模块供电 不得接 5V,避免烧毁芯片
GND GND 共地 必须共地,否则通信不稳定
## 三、软件设计
### 1. 核心功能架构
基于 CH32V003 的 USART 外设,启用IrDA 模式(红外专用编码协议),适配 TFDU4101 的 38kHz 载波调制。
按键触发发送固定字符串,接收数据时翻转 LED 指示灯,并回显接收内容(便于直观验证)。
采用中断接收方式,提升数据接收效率,避免主循环阻塞。
### 2. 关键代码实现(完整可运行)
(1)头文件与宏定义
c
```c
#include "debug.h"
#include "SoftUART.h"
/* Global define */
/* Global Variable */
vu8 val;
uint8_t tmp[20] = {0x01, 0x80, 0xaa, 0x55};
// 串口接收配置
#define RX_BUF_SIZE 64
uint8_t rx_buf[RX_BUF_SIZE];
uint16_t rx_len = 0;
uint8_t rx_complete = 0; // 接收完成标志(换行符结束)
/*********************************************************************
* @fn USART1_Config
* @brief 初始化串口1(PD5/PD6引脚 + IrDA模式,适配TFDU4101)
********************************************************************/
void USART1_Config(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
// 1. 使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOD |RCC_APB2Periph_USART1, ENABLE);
// 2. 配置PD5(TX)和PD6(RX)为串口功能
// PD5:复用推挽输出(IrDA发送端)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出(USART1 TX)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
// PD6:浮空输入(IrDA接收端)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入(USART1 RX)
GPIO_Init(GPIOD, &GPIO_InitStructure);
// 3. 配置串口基本参数(8N1)
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式
USART_Init(USART1, &USART_InitStructure); // 调用库函数初始化
USART1->CTLR2 &=0x87FF;
USART_SmartCardCmd(USART1,DISABLE);
USART_HalfDuplexCmd(USART1,DISABLE);
// 4. 配置IrDA模式(TFDU4101必须启用,红外信号需要IrDA编码)
// 5. 使能接收中断(收到数据后触发中断)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 接收非空中断
// 6. 配置NVIC中断优先级
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* must clean LINEN,STOP,CLKEN,SCEN,HDSEL */
//USART_LINCmd(USART1, DISABLE);
// 7. 使能串口1
USART_Cmd(USART1, ENABLE);
USART_SetPrescaler(USART1,1);//很重要
USART_IrDAConfig(USART1, USART_IrDAMode_Normal); // 标准模式(非低功耗)
// USART_IrDACmd(USART1, DISABLE); // 开启IrDA功能
USART_IrDACmd(USART1, ENABLE); // 开启IrDA功能
}
/*********************************************************************
* @fn GPIO_Toggle_INIT
*
* @brief Initializes GPIOA.0
*
* @return none
*/
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_30MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_WriteBit(GPIOD, GPIO_Pin_4, Bit_RESET);
}
//#define SENDDEV
#define RECVDEV
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
uint8_t i=0;
uint8_t strarr[64];
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
SystemCoreClockUpdate();
Delay_Init();
#if (SDI_PRINT == SDI_PR_OPEN)
SDI_Printf_Enable();
#else
USART_Printf_Init(115200);
#endif
GPIO_Toggle_INIT();
USART1_Config(9600);
// printf("SystemClk:%d\r\n", SystemCoreClock);
// printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID());
SoftUARTFunc.Init(115200);
// USART1_SendString("IrDA Ready (PD5/PD6)\n"); // 初始化提示
uint8_t flag =0;
while (1)
{
#ifdef SENDDEV
USART1_SendString("Send:irDA test\n");
#endif
Delay_Ms(1000);
#ifdef RECVDEV
if (rx_complete)
{
rx_complete = 0; // 清除标志
// 翻转LED提示接收完成
GPIO_WriteBit(GPIOD, GPIO_Pin_3, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
// 回显接收数据
// printf("Received:%s\n",rx_buf);
sprintf(strarr,"Received: ");
SoftUARTFunc.TransmitBytes(strarr,strlen(strarr));
memcpy(strarr,rx_buf,strlen(rx_buf));
SoftUARTFunc.TransmitBytes(strarr,strlen(strarr));
memset(rx_buf,0,64);
memset(strarr,0,64);
}
#endif
// if (SoftUARTFunc.ReceiveBytes(tmp, 0xff))
// SoftUARTFunc.TransmitBytes(tmp, 4);
}
}
/*********************************************************************
* @fn USART1_IRQHandler
* @brief 串口1中断服务函数(PD6接收数据处理)
********************************************************************/
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART1_IRQHandler(void)
{
uint8_t data = 0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // 接收非空中断触发
{
data = USART_ReceiveData(USART1); // 读取接收数据
// 接收逻辑:缓冲区未满且未到结束符
if (rx_len < RX_BUF_SIZE - 1)
{
rx_buf[rx_len++] = data;
if (data == '\n') // 以换行符作为一包数据结束
{
rx_buf[rx_len] = '\0'; // 字符串结束符
rx_complete = 1; // 置位接收完成标志
rx_len = 0; // 重置接收长度
}
}
else
{
// 缓冲区满,强制结束
rx_buf[RX_BUF_SIZE - 1] = '\0';
rx_complete = 1;
rx_len = 0;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除中断标志
}
}
```
注意在串口初始话的过程中一定要把**分频设置成1** 。把这句话加初始化程序中
## 四、过程与结果
关键现象验证
接收端收到数据后,LED 稳定翻转,串口回显内容完整,无乱码。
遮挡红外窗口时,通信立即中断;移除遮挡后,通信恢复正常。
低波特率(2400)下,即使有轻微遮挡或角度偏差,仍能稳定通信。
### 五、常见问题与解决方法
问题现象 可能原因 解决方法
接收端无反应 1. IrDA 模式未开启;2. 引脚重映射配置错误;3. 硬件接线反 1. 确认调用USART_IrDACmd(USART1, ENABLE);3. 核对 PD5/PD6 与 TFDU4101 的 TX/RX 连接 确定初始话分频
通信距离短 1. 波特率过高;2. 红外窗口未对准;3. 电源电压不稳定 1. 降低波特率至 2400;2. 调整设备角度,避免遮挡;3. 更换稳定的 3.3V 电源
接收数据乱码 1. 波特率不匹配;2. 时钟配置错误 1. 确保两套设备波特率一致;
六、总结
1. 测试结论
CH32V003 与 TFDU4101 的组合实现了低成本、低功耗、短距离的红外通信,整套方案硬件成本<5 元,完全满足玩具、简易传感器、遥控器等场景的需求。其中,2400 波特率是兼顾距离与效率的最优选择。
2. 关于CH32V003 单片机,单线下载,MR stdio软件做的很好,比其他厂家基于eclipse开发的启动快多了
|
|