代码仓库git clone https://gitee.com/jumayusi/unit7-gd32-tim.git7.1 基于定时器实现计时功能ARM32位单片机定时器外设一览定时器的常规用途可以概括为三点定时计数、输出比较PWM和输入捕获红外遥控输入。定时器资源概述如下一共0~1314个定时器从左到右功能性递减。预分频计数器、自动重装载计数器和时钟主频这老三样我们就不再罗嗦了。定时器配置周期定时中断的一般方法7.2 基于PWM实现呼吸灯GD32F303ZET6所有定时器对应的GPIO口其中ON代表互补输出。CHxCV寄存器需要参与PWM方波的生成现成的prompt看看吧PWM的有效电平精准图例注意7.3 基于输入捕获测量PWM周期本节课的目标是用PA0实现定时器输入捕获。输入捕获模式可以用来测量信号周期频率或脉冲宽度。输入捕获原理示意图配置流程7.4 红外遥控简介及应用层代码实现本讲主要介绍的是NEC红外通信协议它是一种调制载波信号频率为38KHz。发送端数据帧结构起始信号引导码和停止位之间存在32bit数据用户码通常用来存储原厂信息数据码存储具体的按键功能指令。接收端数据帧介绍本节课需要操作定时器7的通道07.5 红外遥控驱动层代码实现以接收0x55为例:代码实现#define TICK_HEAD_MAX 20000 //引导码最大值 #define TICK_HEAD_MIN 10000 #define TICK_0_MAX 1800 #define TICK_0_MIN 500 #define TICK_1_MAX 3000 #define TICK_1_MIN 1800 static uint8_t g_irCode[4]; static bool g_irCodeFlag false; static void ParseIrFrame(uint32_t tickNum) { static bool s_headFlag false; static uint8_t s_Index 0; if(tickNum TICK_HEAD_MIN tickNum TICK_HEAD_MAX) { s_headFlag true; return; } if(!s_headFlag) { return; } if(tickNum TICK_1_MIN tickNum TICK_1_MAX) { g_irCode[s_Index/8]1; g_irCode[s_Index/8] | 0x80; s_Index; } if(tickNum TICK_0_MIN tickNum TICK_0_MAX) { g_irCode[s_Index/8]1; s_Index; } if(s_Index32) { if((g_irCode[2] g_irCode[3])0) //反码判断 { g_irCodeFlagtrue; } else { g_irCodeFlagfalse; } s_headFlagfalse; s_Index0; } }7.6 基于输入捕获测量PWM脉宽示例代码这种配置是为了实现PWM输入模式PWM Input Mode利用定时器的两个捕获通道同时测量PWM的周期和脉宽。核心原理主从通道配合CH0主通道通常配置为上升沿捕获用于检测PWM周期的起点CH1从通道配置为下降沿捕获如代码所示用于检测高电平结束点INDIRECTTI 的作用TIMER_IC_SELECTION_INDIRECTTI 表示CH1不直接采集自己的引脚信号而是交叉采集CH0对应的输入信号这样CH0和CH1实际上监测的是同一个物理引脚上的PWM信号测量过程CH0捕获上升沿→ 记录时刻T1周期起点CH1捕获下降沿→ 记录时刻T2高电平结束CH0再次捕获上升沿→ 记录时刻T3下一个周期起点脉宽 T2 - T1周期 T3 - T1为什么必须这样设置如果CH1使用DIRECTTI直接采集它只能捕获自己引脚的信号无法与CH0同步测量同一个PWM波形。使用INDIRECTTI才能让两个通道协同工作通过硬件自动完成周期和脉宽的精确测量无需软件干预时序。GD官方提供了API捕获测量PWM在AI时代要注意地方代码提示的幻觉避免使用错误函数。