ruanlingling2 2024-11-18 14:53 采纳率: 53.3%
浏览 65
已结题

stm32f103c8t6制作万能红外遥控器

红外遥控模组NEC协议 38kHZ载波
自家的

img


外采遥控器的

img


大致写法:
MCU: STM32f103
单片机GPIO引脚控制红外灯珠, 然后定时器1不停的反转最终达到 近似38khz 占空比30的一个PWM波
红外接受器,当接受到38khz波时输出低电平,没有接受 到输出高电平,最终监听现象如上图
主程序通过控制定时器1来实现 来实现各种NEC协议等各种操作
然后去测试空调发现控制不了,最终检查协议格式是对的 就是精度问题如上图,外采可以很准确的输出一个560us的一个低电平与高电平,而我不行也做不到,

img


做不到的测试推出来的原因:
首先修改延时是可以改变 红外接受高低电平的宽度的,但是不是线性的,而是阶梯状的,
举个例子SysTick_Delay_Us(560); 与SysTick_Delay_Us(565), 红外接受输出的宽度都是 572.625us; 而当写570的时候,红外输出时598.925us,是成阶梯状的,不是线性的;
我猜测是一个完整的38khz一个周期是26us,所以我延时的时间是38khz的周期的整数;例如我输出一个38khz 红外接受低电平26.3us,两个38khz周期就是72.6us;所以我延时是没用的 只能延周期时间的倍数 560us/(一个38kHZ周期的时间),不能线性的延时;不明白外采是怎么做到560us正正好好的
我感觉我制作遥控器的方向错了;指导一下:除了买万能遥控芯片;我是知道有万能遥控芯片的;但是时间来不及只能硬件先这样了; 我不能外采是怎么做到的

示意图

img

  • 写回答

21条回答 默认 最新

  • 铭渊老黄 新星创作者: Python技术领域 2024-11-18 17:33
    关注
    🕒下午好,题主!目前:🟢[在线]
    📢参考GPT-4o mini 模型、由清水白石008整理提供!
    📣今日金句:“成功的关键在于相信自己有能力实现目标。” — 诺曼·文森特·皮尔
    

    你的问题归结为 如何精确生成符合 NEC 协议要求的红外信号,尤其是如何解决当前红外信号宽度偏差问题。通过分析现象和描述,问题可能出在 PWM 频率精度不足延时机制不够灵活。以下是改进方向和实现建议:


    问题原因分析

    1. 定时器精度受限

    • STM32 的 定时器分辨率 受时钟源频率和分频系数的影响。如果定时器无法精确生成所需的 38kHz 信号及 NEC 协议所需的特定时间间隔(例如 560µs、1690µs 等),红外信号精度就会下降。
    • 你的推测正确,SysTick_Delay_Us 的延时不是连续线性变化,而是离散的,受限于时钟周期的整数倍。

    2. 延时与 PWM 信号的耦合问题

    • NEC 协议要求高精度控制载波信号(38kHz)和高低电平切换时间。这种情况如果单靠延时函数(如 SysTick_Delay_Us),很难兼顾载波精度和切换时间精度。

    3. 外采模块如何精确实现

    • 市售红外遥控芯片或专业模块使用 硬件定时器加 CPLD/FPGA 等逻辑控制,直接按时序输出固定宽度的 PWM 信号。这样能精确控制载波频率与脉冲宽度,而不依赖 MCU 软件延时。

    改进方向与解决方案

    1. 优化 PWM 生成

    使用 STM32 的高级定时器(如 TIM1)直接生成 38kHz PWM 信号,并在必要时中断切换高低电平。步骤如下:

    1. 配置 TIM1 输出 38kHz

      • 通过调整预分频器和计数周期,确保 TIM1 输出的频率为 38kHz,且占空比为 1/3。
        // 定时器时钟频率假设为 72MHz
        TIM1->PSC = 1 - 1; // 预分频器为1,时钟仍为 72MHz
        TIM1->ARR = 1884;  // 自动重装值: 72MHz / (ARR + 1) = 38kHz
        TIM1->CCR1 = 628;  // 占空比 1/3
        
    2. 使用 DMA 或中断切换脉冲时间

      • 配置 DMA 或定时器更新中断,切换 PWM 的启停时间。例如,在 560µs1690µs 的时间点切换 PWM 输出。
    3. 结合 GPIO 切换高低电平

      • 使用定时器触发 OC 模式(输出比较),在精确的时间点拉高或拉低 GPIO。

    2. 改进延时方法

    如果需要更灵活的延时机制,改用高分辨率定时器(如 SysTick 或 TIM6 定时器)。方法如下:

    1. 利用 TIM6 定时器生成精确延时
      • 配置 TIM6 的时间基准为微秒级:
        void Delay_us(uint32_t us) {
          TIM6->ARR = us - 1; // 设置自动重装值
          TIM6->CNT = 0;      // 清空计数器
          TIM6->CR1 |= TIM_CR1_CEN; // 启动定时器
          while (!(TIM6->SR & TIM_SR_UIF)); // 等待更新标志位
          TIM6->SR &= ~TIM_SR_UIF; // 清除标志位
        }
        
    2. 结合 TIM1 实现 PWM 停止和启动
      • 利用 TIM1 定时器输出 PWM,结合 TIM6 的延时精确控制高低电平的切换时序。

    3. 直接使用查表法生成波形

    通过预计算的查表方式,减少实时计算导致的误差:

    1. 预定义红外信号序列
      • 预先定义每个信号的脉冲和空闲时间,存储在数组中。
    2. 利用 DMA 输出波形
      • 利用 DMA 将预计算的信号序列写入 TIM1 的比较寄存器,自动输出符合 NEC 协议的信号。

    示例代码:

    // NEC 协议波形查表
    const uint16_t nec_waveform[] = {560, 1690, 560, 560, ...};
    
    // DMA 配置代码
    DMA1_Channel1->CNDTR = sizeof(nec_waveform) / sizeof(uint16_t);
    DMA1_Channel1->CMAR = (uint32_t)&nec_waveform[0];
    DMA1_Channel1->CCR |= DMA_CCR_EN;
    

    4. 最佳实践:组合软件与硬件

    • 软件负责控制信号序列和协议逻辑;
    • 硬件负责精确生成载波和时间间隔。

    总结

    • 优化方向:
      1. 使用 TIM1 生成稳定的 38kHz PWM 信号;
      2. 利用 TIM6 实现精确的延时控制;
      3. 考虑预计算信号序列,结合 DMA 高效输出波形。
    • 通过硬件定时器+软件逻辑结合,可以实现精确符合 NEC 协议要求的红外信号输出。即便无法外采,也能尽量靠近专业模块的性能。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(20条)

报告相同问题?

问题事件

  • 系统已结题 11月27日
  • 已采纳回答 11月19日
  • 创建了问题 11月18日