# irtestv1 **Repository Path**: dkori/irtestv1 ## Basic Information - **Project Name**: irtestv1 - **Description**: 红外收发实验 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-03 - **Last Updated**: 2026-03-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # STM32F1 红外学习/收发项目 ## 硬件引脚汇总 | 功能模块 | 引脚 | 模式 | 说明 | |---------|------|------|------| | **红外接收** | PA7 | TIM3_CH2 输入捕获 | 红外信号接收输入 | | **红外发射** | PA2 | GPIO 推挽输出 | 红外载波发射输出 | | **红外学习输入** | PB6 | TIM4_CH1 输入捕获 | 红外学习模式信号输入 | | **模式切换按键** | PB0 | GPIO 输入(上拉) | 学习模式/正常模式切换 | | **状态指示灯** | PC13 | GPIO 推挽输出 | LED状态指示 | | **调试输出** | PA3 | GPIO 推挽输出 | 红外捕获调试信号输出 | ## 定时器使用汇总 | 定时器 | 功能 | 时钟源 | 预分频 | 计数频率 | 用途 | |--------|------|--------|--------|----------|------| | **TIM2** | 基础定时 | 72MHz | 71 | 1MHz | 红外发射延时基准 (delay_us) | | **TIM3** | 输入捕获 | 8MHz | 7 | 1MHz | 红外接收信号捕获 (通道2) | | **TIM4** | 输入捕获 | 8MHz | 7 | 1MHz | 红外学习信号捕获 (通道1) | ## 中断使用汇总 | 中断源 | 优先级 | 用途 | |--------|--------|------| | **TIM3_IRQn** | 0 (最高) | 红外接收捕获中断 | | **TIM4_IRQn** | 5 | 红外学习捕获中断 | --- ## 模块功能说明 ### 1. bsp_ir_receiver.c - 红外接收模块 **文件路径**: `App/bsp_ir_receiver.c` **功能描述**: - 使用 **TIM3_CH2 (PA7)** 输入捕获功能接收红外信号 - 实现 NEC 红外协议解码状态机 - 支持 32 位数据接收(地址码+地址反码+命令码+命令反码) - 软件去抖功能:连续 3 次相同命令才确认有效 - 数据校验:自动验证地址码和命令码的反码关系 **主要函数**: - `infrared_gpio_config()` - 初始化 GPIO 和 TIM3 输入捕获 - `infrared_process()` - 主循环中调用,处理接收到的红外数据 - `get_infrared_command()` - 获取去抖后的红外命令码 - `clear_infrared_command()` - 清除红外命令数据 - `get_infra_read_error()` - 获取接收错误信息 **NEC 协议时序参数**: - 同步头高电平: 7.6ms ~ 26ms - 逻辑 0 低电平: 400μs ~ 800μs - 逻辑 1 低电平: 1.4ms ~ 2.1ms --- ### 2. bsp_ir_transmitter.c - 红外发射模块 **文件路径**: `App/bsp_ir_transmitter.c` **功能描述**: - 使用 **PA2** GPIO 输出 38kHz 红外载波 - 实现 NEC 红外协议编码发送 - 基于 **TIM2** 实现微秒级精确延时 - 支持发送标准 NEC 帧格式 **主要函数**: - `infrared_tx_gpio_config()` - 初始化红外发射 GPIO - `send_infrared_data(address, command)` - 发送 NEC 格式红外数据 - `send_infrared_test_data()` - 发送测试数据 (地址0x00, 命令0x01) - `ir_send_carrier(time_us)` - 发送 38kHz 载波 - `ir_send_bit(bit)` - 发送单个位(NEC协议) **NEC 协议发送时序**: - 引导码: 9ms 载波 + 4.5ms 空闲 - 位 "0": 560μs 载波 + 560μs 空闲 - 位 "1": 560μs 载波 + 1688μs 空闲 - 结束位: 560μs 载波 **38kHz 载波参数**: - 周期: 26.316μs - 占空比: 50% (13μs 高电平, 13μs 低电平) --- ### 3. ir_learning_task.c - 红外学习模块 **文件路径**: `App/ir_learning_task.c` **功能描述**: - 使用 **TIM4_CH1 (PB6)** 输入捕获学习未知红外信号 - 基于 FreeRTOS 任务实现 - 支持最多 16 个按键特征存储 - 特征提取算法:多帧平均、位时序分析 - 相似度匹配算法:支持识别已学习的按键 **工作模式**: 1. **学习模式** (PB0 按下): - LED 常亮指示 - 捕获红外信号并提取特征 - 存储到按键特征数组 - 学习完成 LED 闪烁 5 次 2. **正常模式** (PB0 松开): - LED 熄灭 - 实时匹配接收到的红外信号 - 输出最相似的按键索引 **特征数据结构** (`ir_key_feature_t`): - `diff_count`: 时间差数量(帧长度) - `first_diff`: 同步头时间差 - `first_diff_avg`: 多帧同步头平均值 - `bit_diffs[32]`: 每个位位置的平均时间差 - `sum_diff`: 所有时间差总和 **主要函数**: - `ir_learning_task_init()` - 初始化 GPIO、TIM4 和按键数组 - `start_ir_learning_task()` - 启动 FreeRTOS 学习任务 - `ir_learning_task()` - 主任务循环,处理学习/匹配逻辑 - `calculate_feature()` - 从时间差计算信号特征 - `find_most_similar_key()` - 查找最相似的已学习按键 **匹配算法**: - 主特征:diff_count 必须完全匹配 - 次特征:first_diff 容差 5% - 位特征:每个位时间差容差 5% - 综合评分:选择得分最低的匹配项 --- ## 系统架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 应用层 │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │ │ │ 红外接收模块 │ │ 红外发射模块 │ │ 红外学习 │ │ │ │ bsp_ir_receiver │ │ bsp_ir_transmitter│ │ ir_learning │ │ │ └────────┬────────┘ └────────┬────────┘ └──────┬──────┘ │ └───────────┼────────────────────┼──────────────────┼─────────┘ │ │ │ ┌───────────▼────────────────────▼──────────────────▼─────────┐ │ 硬件抽象层 (HAL) │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │ │ │ TIM3 输入捕获 │ │ TIM2 基础定时 │ │ TIM4 输入捕获│ │ │ │ (PA7 - 接收) │ │ (延时函数) │ │ (PB6 - 学习)│ │ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ GPIO (PA2 - 发射)│ │ GPIO (PB0/PC13) │ │ │ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 使用说明 ### 红外接收 ```c // 初始化 infrared_gpio_config(); // 主循环中处理 while (1) { infrared_process(); uint8_t cmd = get_infrared_command(); if (cmd != 0) { // 处理命令 } } ``` ### 红外发射 ```c // 初始化 infrared_tx_gpio_config(); // 发送数据 send_infrared_data(0x00, 0x01); // 地址 0x00, 命令 0x01 ``` ### 红外学习 ```c // 初始化 ir_learning_task_init(); // 启动任务 start_ir_learning_task(); // 按下 PB0 进入学习模式,对准 PB6 发送红外信号 // LED 闪烁表示学习完成 ``` --- ## 注意事项 1. **定时器冲突**: TIM2 用于发射延时,TIM3 用于接收,TIM4 用于学习,避免重复使用 2. **中断优先级**: TIM3 (接收) 优先级高于 TIM4 (学习),确保接收实时性 3. **GPIO 复用**: PA7 复用为 TIM3_CH2,PB6 复用为 TIM4_CH1 4. **FreeRTOS**: 学习任务使用 128 字栈空间,优先级为 5 --- 实验结论: 收发不能同时进行,误差太大