当前位置: 首页 > news >正文

CC253x/CC254x定时器红外收发原理与实战配置详解

1. 项目概述与核心价值

如果你正在用CC253x或CC254x这类芯片做物联网节点、智能家居遥控器或者任何需要红外收发功能的小玩意儿,那你肯定绕不开它的定时器。芯片手册里关于Timer1和Timer3在红外模式下的那几页,我当年第一次看的时候也是一头雾水,一堆寄存器位和框图,感觉懂了又好像没完全懂。直到真正动手调了几个项目,把红外发射和学习的代码从头到尾写了一遍,才把这些碎片化的信息串成了完整的知识链条。

简单来说,CC253x/CC254x的红外功能,其核心就是让两个定时器“打配合”。Timer3这个8位定时器,主要干的是“打拍子”的活,负责产生那个38kHz(或者其它频率)的载波,你可以把它想象成一个节奏稳定的节拍器。而Timer1这个16位的大家伙,则负责“唱旋律”,它根据具体的红外协议(比如NEC、RC5),生成高低电平变化的编码信号。最关键的是,这两个定时器的输出在硬件上通过一个与门(AND Gate)合并,最终生成一个被载波调制好的、干净的红外波形,直接从IO脚推出去驱动红外LED。反过来,在学习(接收)模式下,这套硬件又能化身为一对“耳朵”:Timer3监听原始的、带着载波的红外信号,用来测算载波频率;Timer1则接收已经解调好的数字波形,精准地捕获其上升沿和下降沿,从而还原出原始的编码数据。

这种硬件集成的方案,其价值在于把最耗CPU时间的波形生成和精确计时工作,完全甩给了专用外设。你的主CPU只需要在合适的时机(比如一个完整的红外帧发送或接收完毕)去处理一下数据就行,中间那些微秒级的时序控制完全不用操心,极大地解放了CPU,也保证了系统的实时性和低功耗。这对于电池供电的无线设备来说,简直是福音。下面,我就结合实际的寄存器操作和代码片段,把这套机制掰开揉碎了讲清楚。

2. 硬件架构与工作模式深度解析

要玩转红外功能,首先得在脑子里把芯片内部的硬件连接图画出来。手册里的框图是静态的,我们需要理解的是数据流和控制流。

2.1 红外生成模式的信号通路

在红外生成模式下,整个信号链是这样的:

  1. Timer3通道1:它被配置为输出比较模式,生成一个固定占空比(比如33%)的方波,这个方波的频率就是红外载波频率,通常是38kHz。
  2. Timer1通道1:它也被配置为输出比较模式,但生成的是红外编码信号。这个信号在“有脉冲”(Mark)时为高电平,“无脉冲”(Space)时为低电平。
  3. 与门(AND Gate):这是关键所在。Timer3通道1的输出(载波)和Timer1通道1的输出(编码)同时送入一个硬件与门。与门的逻辑是“两者都为高,输出才为高”。
  4. 最终输出:与门的输出直接连接到芯片的某个特定IO引脚(例如P1.1),作为IR Out。这样一来,只有当Timer1输出高电平(表示发送红外脉冲)时,Timer3的载波方波才能通过,形成一段被调制了的38kHz脉冲群;当Timer1输出低电平时,与门输出恒为低,红外LED熄灭。这就完美实现了幅移键控(ASK)调制

这里有个非常重要的细节:为了避免输出信号出现毛刺(glitch),Timer1和Timer3的计数器在启动时是同步的。手册里提到“The timing of the Timer 3 channel 1 output and Timer 1 channel 1 output signals is synchronized”。这种同步通常由硬件内部保证,确保了编码信号的边沿与载波信号的边沿对齐,不会产生短暂的错误脉冲。

2.2 红外学习模式的信号通路

切换到学习模式时,信号流方向反了过来:

  1. 前端电路:红外PIN二极管接收到红外信号,经过一个外部解调电路(通常是一个三极管或专用解调IC)。这个电路的作用是滤除38kHz载波,将ASK调制信号还原成数字电平(即编码信号)。同时,从PIN二极管出来的原始调制信号也会直接接入另一路。
  2. Timer3通道1:配置为输入捕获模式,其输入引脚连接的是未经解调的原始红外信号。它的任务是测量输入脉冲的周期,从而计算出载波的频率。这对于学习不同设备的红外码(因为载波频率可能有36kHz, 38kHz, 40kHz等)至关重要。
  3. Timer1通道2:配置为输入捕获模式,其输入引脚连接的是解调后的数字编码信号。它的任务是精确记录编码信号每一个上升沿和下降沿到来的时刻(即捕获当时的计数器值),从而计算出脉冲宽度(Mark的时长)和间隔宽度(Space的时长)。

注意:手册示意图中学习模式用的是Timer1 Ch2,但实际使用中,Timer1的任何通道(0-4)理论上都可以配置为捕获模式。选择哪个通道取决于你的具体引脚分配和电路设计。通道2可能因其引脚位置或与DMA触发器的关联而被推荐。

2.3 核心控制位:IRGEN

模式切换的钥匙是一个叫做IRCTL.IRGEN的寄存器位。这个位在Timer1的寄存器区域内。

  • IRGEN = 0:Timer1和Timer3独立工作,它们的输出走正常的IO引脚功能。
  • IRGEN = 1:硬件内部进行重路由。Timer1通道1的输出不再直接通向其IO引脚,而是作为一路输入送往前文提到的那个与门,与Timer3通道1的输出进行逻辑与操作,最终结果从IR Out引脚输出。同时,Timer1的时钟Tick输入可能会与Timer3联动以实现同步。

这个设计非常巧妙,通过一个比特位的切换,就完全改变了两个外设的功能组合和物理连接,实现了“一发一收”两种截然不同的硬件配置。

3. 寄存器配置与实操步骤详解

理论懂了,接下来就是动手配置。我会以最常见的场景为例:生成38kHz载波调制的NEC协议红外码,以及学习同样的红外码。

3.1 红外信号生成配置(以NEC协议为例)

假设系统时钟为32MHz,我们目标是生成38kHz载波,载波占空比33%,并调制一个NEC协议的引导码(9ms Mark, 4.5ms Space)。

第一步:配置Timer3产生38kHz载波

  1. 计算参数:38kHz的周期 T = 1 / 38000 ≈ 26.3us。系统Tick频率取决于CLKCONCMD.TICKSPD,假设我们设为16MHz(分频后)。Timer3的时钟源为此Tick频率再经过预分频。为方便计算,我们选择预分频DIV=1(即不分频),Timer3时钟为16MHz。
    • Timer3工作在模数模式(Modulo),周期由T3CC0决定。T3CC0= 时钟频率 / 目标频率 = 16,000,000 / 38,000 ≈ 421。我们取421。
    • 要产生33%占空比,高电平时间 = 周期 * 0.33 ≈ 139。所以设置T3CC1 = 139
    • 手册例子中T3CC0 = 3 × T3CC1即对应33%占空比(因为T3CC1是翻转点,从0到T3CC1输出一种状态,T3CC1T3CC0输出另一种状态)。
  2. 寄存器配置
    // 配置P1.1为外设功能(Timer3 Ch1输出) P1SEL |= 0x02; // 假设Timer3 Ch1复用在该引脚 P1DIR |= 0x02; // 设置为输出 // 配置Timer3为模数模式,不分频 T3CTL = 0x02; // MODE[1:0]=10 (模数模式), DIV[2:0]=000 (/1) // 设置周期 T3CC0 = 421; // 设置比较值,用于输出翻转,实现33%占空比 T3CC1 = 139; // 配置通道1为输出比较模式,设置“比较时翻转输出”模式 T3CCTL1 = 0x1C; // MODE=1 (比较模式), CMP[2:0]=010 (翻转输出), IM=1 (使能中断可选) // 启动Timer3 T3CTL |= 0x10; // START=1
    此时,Timer3通道1输出引脚上应该能看到一个38kHz、占空比约33%的方波。

第二步:配置Timer1生成NEC编码波形NEC协议的一位数据由560us的Mark(载波脉冲)和560us或1690us的Space(静默)组成。我们需要Timer1产生一个控制信号,在需要发送Mark时为高,发送Space时为低。

  1. 计算参数:Timer1时钟同样假设为16MHz(不分频)。560us需要的计数器增量 = 0.00056 * 16,000,000 = 8960。这超出了8位范围,但Timer1是16位定时器(最大值65535),完全够用。
  2. 寄存器配置
    // 首先,确保IRGEN位为0,直到我们完成配置,避免意外输出 IRCTL &= ~0x01; // 配置Timer1为模数模式,用于控制编码周期 T1CTL = 0x02; // MODE[1:0]=10 (模数模式), DIV[1:0]=00 (/1) // 假设我们使用DMA或CPU来动态更新比较值以生成波形。 // 这里以生成一个固定的9ms Mark, 4.5ms Space引导码为例: // 9ms Mark: 计数器值 = 0.009 * 16,000,000 = 144,000 > 65535,说明需要分频。 // 将Timer1预分频设为/8,则时钟为2MHz。 T1CTL = 0x0A; // MODE=10, DIV=01 (/8) -> 2MHz // 9ms Mark 需要计数值 = 0.009 * 2,000,000 = 18,000 // 4.5ms Space 需要计数值 = 0.0045 * 2,000,000 = 9,000 // 但Timer1在模数模式下,一个完整的周期(Mark+Space)由T1CC0定义。 // 对于引导码,我们可以将整个13.5ms作为一个周期,用T1CC1控制Mark的结束点。 // 总周期 T1CC0 = 18,000 + 9,000 = 27,000 // Mark结束点 T1CC1 = 18,000 T1CC0H = (27000 >> 8); T1CC0L = (27000 & 0xFF); T1CC1H = (18000 >> 8); T1CC1L = (18000 & 0xFF); // 配置Timer1通道1为输出比较模式,并设置为“比较时置位,计数到0时清零”模式。 // 这能确保在每个周期开始时输出高(Mark),当计数器等于T1CC1时比较事件发生(但我们的动作是“清除输出”?这里需要仔细选择模式)。 // 查看手册,对于模数模式,模式011是“Set output on compare-up, clear on 0”。这不符合要求。 // 模式101是“Clear when equal T1CC0, set when equal T1CC1”。这看起来符合:当计数器等于T1CC1时置位(开始Mark),等于T1CC0时清零(结束Mark,开始Space)。但注意,计数器是从0到T1CC0。所以: // - 计数器从0开始,不等于T1CC1,输出取决于初始化(通常为0)。 // - 当计数器增加到等于T1CC1时,输出置位(变高,Mark开始)。 // - 当计数器增加到等于T1CC0时,输出清零(变低,Mark结束,Space开始)。 // - 计数器归零,进入下一个周期。 // 这正是我们需要的! T1CCTL1 = 0x2C; // MODE=1, CMP[2:0]=101 (Clear when equal T1CC0, set when equal T1CC1), IM=1 (可选)

第三步:联动输出与发送

  1. 启用红外生成模式:将Timer1和Timer3的输出通过硬件与门合并。
    IRCTL |= 0x01; // 设置IRGEN位为1
    一旦设置此位,Timer1通道1的物理输出将被重定向,与Timer3通道1的输出进行与操作后从IR Out引脚输出。
  2. 启动Timer1
    T1CTL |= 0x01; // 确保Timer1处于运行模式(MODE已设,START位实质在T1CTL[4]?注意:Timer1的START控制可能在其他位置或通过模式选择隐含启动。对于Timer1,设置模数模式并写入T1CNTL通常会启动。更稳妥是使用T1CTL.CLR位启动)。 // 通常,写入T1CNTL会复位并启动计数器。或者直接设置T1CTL.MODE为非00即启动。 // 根据手册,写入T1CNTL会清零计数器。所以我们可以: T1CNTL = 0x00; // 写入任何值都会清零并启动计数器
  3. 发送完整数据帧:上面的配置只发送了一个固定的引导码。要发送完整的NEC码(地址、命令、重复码),需要在每个位周期(1.125ms或2.25ms)动态更新T1CC0T1CC1的值。这通常通过DMA(直接存储器访问)Timer1中断来实现。你可以预先计算好整个帧所有高低电平切换点对应的计数器值,存入一个数组,然后让DMA自动搬运到T1CC1寄存器,或者在中斷服务程序里手动更新。

实操心得:在调试红外发射时,最头疼的就是波形不对。强烈建议使用逻辑分析仪或示波器抓取IR Out引脚的实际波形。首先单独测试Timer3的输出,确保38kHz方波正确。然后单独测试Timer1的输出(在IRGEN=0时),确保编码时序正确。最后再开启IRGEN,观察调制后的波形。这样分层调试,问题定位会快很多。

3.2 红外信号学习配置

学习模式的目标是测量未知红外信号的载波频率和脉冲宽度。

第一步:硬件连接与引脚配置

  1. 将红外接收头(或PIN二极管加解调电路)的输出(解调后的数字信号)连接到Timer1的某个捕获通道引脚,例如P0.3(假设对应Timer1 Ch2)。
  2. 将红外接收头的原始输出(未解调的载波信号)连接到Timer3的捕获通道引脚,例如P0.4(假设对应Timer3 Ch1)。
  3. 配置这些引脚为外设输入功能,并禁用上拉电阻以避免干扰。
    // 配置Timer1 Ch2 (P0.3) 为外设输入,用于捕获解调后的编码 P0SEL |= 0x08; // P0.3 用作外设 P0INP &= ~0x08; // 根据需要设置输入模式,通常为三态 // 配置Timer3 Ch1 (P0.4) 为外设输入,用于捕获载波 P0SEL |= 0x10; // P0.4 用作外设 P0INP &= ~0x10;

第二步:配置Timer3进行载波频率检测目标:测量输入脉冲的周期。

  1. 配置Timer3为自由运行模式,这样计数器会从0x00到0xFF循环,提供一个时间基准。
    T3CTL = 0x00; // MODE=00 (自由运行), DIV根据需要的分辨率设置,例如/1
  2. 配置Timer3通道1为输入捕获模式,捕获上升沿(或下降沿,或双边沿)。捕获到边沿时,当前的计数器值T3CNT会被锁存到T3CC1寄存器,并产生中断。
    T3CCTL1 = 0x04; // MODE=0 (捕获模式), CAP[1:0]=01 (上升沿捕获), IM=1 (使能中断)
  3. 在中断服务程序中,读取两次连续上升沿捕获到的T3CC1。两者的差值(考虑计数器溢出)就是载波一个周期对应的计数值。根据Timer3的时钟频率,即可计算出载波频率。
    #pragma vector = T3_VECTOR __interrupt void T3_ISR(void) { if(T3CCTL1 & 0x01) { // 检查CH1IF标志(简化判断,实际需查TIMIF寄存器) static uint16_t last_capture = 0; uint16_t current_capture = T3CC1; uint16_t period_ticks = current_capture - last_capture; // 注意处理溢出 last_capture = current_capture; // 计算频率: Freq = Timer3_Clock / period_ticks // 将频率值存入变量,用于后续平均或判断 TIMIF &= ~0x04; // 清除T3CH1IF中断标志(具体位需查手册) } }

第三步:配置Timer1进行脉冲宽度学习目标:测量解调后信号(即编码)的Mark和Space宽度。

  1. 配置Timer1为自由运行模式,提供高精度的时间基准。由于Timer1是16位,其溢出周期更长,适合测量较长的脉冲(如NEC的9ms引导码)。
    T1CTL = 0x01; // MODE=01 (自由运行), DIV根据需求设置
  2. 配置Timer1通道2为输入捕获模式,捕获双边沿。这样,无论是Mark开始(上升沿)还是Space开始(下降沿)都能被记录。
    T1CCTL2 = 0x0C; // MODE=0, CAP[1:0]=11 (双边沿捕获), IM=1
  3. 在中断服务程序中,记录每次捕获的计数器值T1CC2。连续两次捕获值之间的差值,就是上一个电平(Mark或Space)的持续时间。通过判断是上升沿还是下降沿(可以读取IO口状态或通过标志位区分,但手册中捕获模式本身不直接提供边沿方向,通常需要软件记录前一个状态),可以重建出完整的红外编码序列。
    #pragma vector = T1_VECTOR __interrupt void T1_ISR(void) { if(T1STAT & 0x04) { // 检查CH2IF标志 static uint16_t last_capture = 0; static uint8_t last_level = 0; // 假设0为低(Space),1为高(Mark) uint16_t current_capture = T1CC2L | (T1CC2H << 8); uint16_t pulse_width_ticks = current_capture - last_capture; // 处理溢出 last_capture = current_capture; // 读取当前输入引脚电平,判断是Mark开始还是Space开始 uint8_t current_level = (P0 & 0x08) ? 1 : 0; // 读取P0.3 if(current_level != last_level) { if(current_level == 1) { // 当前是上升沿,说明刚结束的是一个Space // 记录Space宽度: pulse_width_ticks } else { // 当前是下降沿,说明刚结束的是一个Mark // 记录Mark宽度: pulse_width_ticks } last_level = current_level; } T1STAT &= ~0x04; // 清除CH2IF标志 } }

注意事项:在学习模式下,两个定时器都在高速运行和捕获,中断可能非常频繁(尤其是38kHz载波)。这会给CPU带来较大负担。因此,在实际产品中,学习功能通常是在一个专门的“学习模式”下启用,此时系统可以暂时专注于处理红外信号。对于载波频率检测,也可以采用多次采样求平均的方法来提高准确性。

4. 关键参数计算与模式选择背后的逻辑

为什么这么配置?参数怎么来的?这里藏着很多容易踩坑的细节。

4.1 时钟树与分频选择

CC253x/CC254x的定时器时钟源是系统时钟分频后的“Tick”频率。CLKCONCMD.TICKSPD寄存器控制着这个基础频率。Timer1和Timer3的DIV分频器在此基础上进行二次分频。选择分频比的核心是在分辨率、溢出周期和中断频率之间取得平衡

  • 高分辨率需求:如果你需要测量非常窄的脉冲(例如某些高速红外协议),或者生成非常精确的载波频率,那么应该选择较小的分频值(甚至不分频),让定时器跑在更高的频率下,这样每个计数单位代表的时间更短,精度更高。
  • 长周期需求:如果你需要测量或生成很长的脉冲(如NEC的几十毫秒),而定时器的位数有限(Timer3只有8位,最大255;Timer1为16位,最大65535),那么就需要通过增大分频值来降低定时器时钟频率,从而让计数器在溢出前能覆盖更长的时间。例如,用16位Timer1测量9ms脉冲,若系统Tick为16MHz,不分频时计数值为144,000,已超过65535,必须分频(/8或更高)才能测量。
  • 中断频率:在输入捕获模式下,每次捕获都会产生中断。如果信号边沿很密集(如载波信号),高中断频率会拖垮CPU。此时可以考虑使用DMA将捕获值自动搬运到内存,或者适当提高分频比以降低中断频率,但会牺牲时间分辨率。

计算公式总结

  • 定时器时钟频率 =CLKCONCMD.TICKSPD/TxCTL.DIV
  • 定时器计数周期 = 1 / 定时器时钟频率
  • 实际时间 = 计数值 * 定时器计数周期
  • 生成波形的频率 = 定时器时钟频率 /TxCC0(模数模式下)

4.2 输出比较模式的选择

在生成红外编码时,Timer1通道1的输出比较模式选择至关重要。手册中提供了多种模式(Set on compare, Clear on compare, Toggle, 以及几种在上下计数模式下的特殊行为)。对于简单的脉冲生成,模式101(Clear when equal T1CC0, set when equal T1CC1)和模式110(Set when equal T1CC0, clear when equal T1CC1)非常有用

  • 模式101:计数器从0开始,在等于T1CC1时输出置高,在等于T1CC0时输出清零。这完美适配了“在一个周期内,先高电平一段时间,后低电平一段时间”的需求,只需设置T1CC1为高电平结束点,T1CC0为周期结束点。
  • 模式110:逻辑相反,在等于T1CC0时置高,等于T1CC1时清零。可以根据编码逻辑灵活选择。

为什么不用简单的Toggle模式?因为Toggle模式每次比较事件就翻转一次输出,要生成一个固定占空比的脉冲,需要精确控制两次比较事件(一次开、一次关),并且需要动态更新比较值,控制逻辑更复杂。而模式101/110只需要在周期开始时设置好T1CC0T1CC1,硬件就能自动生成一个完整的脉冲,更适合用DMA进行流式数据发送。

4.3 模数模式 vs 上下计数模式

  • 模数模式:计数器从0线性增加到TxCC0,然后归零重启。这是最常用的模式,用于生成固定周期的PWM或测量周期信号。在红外生成中,Timer3常用此模式生成固定频率载波。
  • 上下计数模式:计数器从0增加到TxCC0,再减少到0,如此往复。此模式可以生成中心对齐的PWM,在某些电机控制中能减少谐波。在红外应用中,此模式的一个妙用是配合输出比较模式011100,可以简化某些对称波形的生成,但在标准的ASK红外调制中不常用。

5. 常见问题排查与实战经验

调红外功能,十有八九会碰到波形不对、收不到、学不准的问题。下面是我踩过的一些坑和解决办法。

5.1 问题一:红外发射无输出或波形异常

  • 检查IRGEN位:这是最容易被忽略的!确认IRCTL.IRGEN是否已设置为1。如果为0,Timer1和Timer3的输出是独立的,不会进行与操作,也就没有调制效果。
  • 检查引脚复用:确认你使用的IO引脚(通常是P1.1作为IR Out)是否已经正确配置为外设功能(PxSEL寄存器),而不是普通的GPIO。
  • 检查Timer同步:确保Timer1和Timer3在启动前都已正确配置,并且先启动载波Timer3,再启动编码Timer1,最后再打开IRGEN。顺序混乱可能导致初始同步问题。
  • 测量各点波形:用示波器分别测量:
    1. Timer3通道1输出引脚(在IRGEN=0时):应有38kHz方波。
    2. Timer1通道1输出引脚(在IRGEN=0时):应有你期望的编码波形(如9ms高,4.5ms低)。
    3. IR Out引脚(在IRGEN=1时):应看到被38kHz调制了的编码波形。在Mark期间是密集的38kHz脉冲群,在Space期间是平坦的低电平。
  • 驱动能力不足:红外LED需要一定的驱动电流(通常20-50mA)。芯片IO口的拉电流可能不够,需要增加一个三极管(如NPN型2N3904或MOSFET)来驱动LED。记得串联一个限流电阻(如10-100欧姆)。

5.2 问题二:红外学习不到信号或数据错误

  • 解调电路问题:大部分商用红外接收头(如VS1838B)内部已经集成了解调电路,输出就是干净的数字信号。如果你用的是单独的PIN二极管,那么外部的解调电路(通常是一个三极管放大器加带通滤波)至关重要,电路没调好,信号质量就差,导致捕获不稳定。
  • 输入引脚配置:确保用于捕获的IO口配置为输入模式,并且禁用内部上拉电阻PxINP寄存器),因为外部电路可能有自己的偏置,内部上拉会产生冲突。
  • 捕获边沿选择:对于解调后的编码信号,使用双边沿捕获是最可靠的,因为它能记录下每个电平变化的精确时刻。对于载波信号,通常使用上升沿捕获来测量周期。
  • 中断服务程序效率:学习模式下的中断非常频繁。确保你的中断服务程序(ISR)尽可能短小精悍,只做最基本的读取捕获值和保存到缓冲区的工作。复杂的计算(如换算成时间单位)应该放到主循环中。避免在ISR内调用耗时函数或进行浮点运算。
  • 计数器溢出处理:在自由运行模式下,计数器会循环溢出。计算两个捕获值之间的时间差时,必须考虑溢出。使用16位或32位变量来记录扩展的计数值。
    static uint32_t extended_timer1_count = 0; static uint16_t last_t1cnt = 0; // 在定时器溢出中断或主循环中定期处理 if(T1STAT & 0x80) { // 溢出标志 extended_timer1_count += 65536UL; // Timer1是16位,溢出加65536 T1STAT &= ~0x80; } // 在捕获中断中 uint16_t current_capture = T1CC2; uint32_t full_capture = extended_timer1_count + current_capture; // ... 计算与上一次full_capture的差值
  • 抗干扰与软件滤波:红外信号容易受到环境光干扰。可以在软件中加入简单的滤波算法,比如连续捕获到N个周期接近的载波频率,才认为是一个有效的信号头;或者对脉冲宽度进行范围判断,剔除明显过短或过长的噪声脉冲。

5.3 问题三:功耗考虑

红外LED是耗电大户。在非发射状态下,务必确保IR Out引脚处于高阻态或输出低电平。手册特别指出:“The IR output pin should be placed in the high-impedance state or pulled down during reset to avoid unnecessary power consumption”。在你的代码初始化阶段和进入低功耗模式前,检查并设置好相关引脚的状态。

6. 进阶应用与DMA技巧

对于连续发送一长串复杂的红外码(比如空调的复杂指令),或者高速学习,频繁的CPU中断更新比较值或读取捕获值会成为瓶颈。这时,DMA(直接存储器访问)就是你的神器。

6.1 使用DMA辅助红外发射

Timer1有三个DMA触发源:T1_CH0,T1_CH1,T1_CH2,分别在通道0、1、2的比较事件时触发。我们可以利用这个机制,实现“无人值守”的红外波形发送。

  1. 准备数据缓冲区:在内存中创建一个数组,里面按顺序存放你要发送的每一个脉冲/间隔结束点对应的T1CC1比较值(如果你使用模式101,则T1CC0固定为周期值,T1CC1动态变化)。
  2. 配置DMA通道:将DMA通道的源地址指向这个数组,目标地址指向T1CC1HT1CC1L寄存器(注意是16位传输)。设置传输模式为“单次触发,每次传输一个字(16位)”。
  3. 配置DMA触发源:选择T1_CH1作为触发源。这意味着,每次Timer1通道1发生比较匹配(即完成当前脉冲/间隔),就会自动触发DMA,将下一个比较值从内存搬运到T1CC1寄存器。
  4. 启动流程:初始化Timer1和DMA,启动Timer1。当第一个比较事件发生时,DMA自动装载第二个比较值,如此循环,直到DMA传输完数组中所有数据,可以产生一个中断通知CPU发送完成。

这样,CPU只需要在开始时启动发送,结束时处理一下完成中断,中间所有的时序控制全部由Timer1硬件和DMA自动完成,CPU可以休眠或处理其他任务,极大地提高了系统效率。

6.2 使用DMA辅助红外学习

同样,在输入捕获模式下,DMA可以在每次捕获事件发生时,自动将T1CCn(捕获到的计数值)搬运到内存中的一个大型缓冲区。这避免了频繁的捕获中断,尤其适用于学习高速或长时间的红外信号。

配置DMA通道,以T1_CH2(如果使用通道2捕获)为触发源,目标地址为内存数组,源地址为T1CC2L(注意可能是8位访问,需要根据数据手册确认)。这样,每个边沿到来时,计数值就被自动保存,CPU可以定期或在缓冲区满后,再对这批数据进行处理(解码)。

7. 不同红外协议适配要点

不同的红外协议(NEC, RC-5, RC-6, Sony SIRC等)主要区别在载波频率编码方式(脉宽调制PWM或脉冲位置调制PPM)和数据帧结构。我们的硬件框架是通用的,适配不同协议主要在于软件对定时器参数和数据处理逻辑的调整。

  • NEC协议:38kHz载波,PWM编码。引导码(9ms Mark + 4.5ms Space)后跟32位数据(地址、命令及反码)。每位数据:560us Mark + 560us/1690us Space。适配要点:Timer3载波设为38kHz。Timer1用于生成引导码和位数据,需要动态更新T1CC0/T1CC1来产生不同宽度的Space。
  • RC-5协议:36kHz载波,双相编码(曼彻斯特编码)。每位中间都有跳变。适配要点:载波频率改为36kHz。编码生成更复杂,因为每个位周期内需要一次电平翻转,可能需要Timer1工作在Toggle模式,或者使用两个比较通道配合。
  • 学习兼容:在学习时,Timer3的载波频率检测结果可以用来判断是哪种协议(38k vs 36k)。Timer1捕获到的脉冲宽度模式,则用于分析是PWM还是PPM编码,进而调用相应的解码算法。

最后,分享一个我个人的调试习惯:在项目初期,我会用一个已知能正常工作的红外遥控器(比如电视机的),先确保我的学习电路和代码能正确解码它的信号。然后再用我自己的发射代码去模拟这个遥控器的信号,看能否控制设备。用已知正确的信号作为“金标准”,能帮你快速定位问题是出在发射端还是接收端,或者是协议理解有误。红外通信虽然是个老技术,但把这些硬件定时器的细节吃透,在资源受限的嵌入式设备上实现稳定可靠的收发,依然是一件很有成就感的事情。

http://www.jsqmd.com/news/1266841/

相关文章:

  • CC13x2/CC26x2 WDT与TRNG寄存器级配置:嵌入式系统可靠性与安全基石
  • AI开发新手俱乐部:几天学会编码建APP,还送优质工具
  • LeagueSkinChanger:英雄联盟皮肤修改器的终极完整指南
  • 多表关联一跑就挂?JOIN调优这些坑别再踩了
  • 入住半年有感!2026长兴自住业主聊聊,选对装修公司到底有多省心 - 装企自媒体训练营辉哥
  • 抖音无水印下载神器:3分钟快速上手的终极完整指南
  • C672x DSP SPI驱动开发:从寄存器配置到实战代码详解
  • 茉莉花插件:3步轻松搞定Zotero中文文献管理,效率提升80%[特殊字符]
  • 2026金镯断绳想变现?武汉易奢福上门回收,免费估价当场转账不压价 - 奢侈品回收探店ing
  • 具身智能进入Token时代:从像素处理到语义推理的范式变迁
  • 电动汽车V2G技术:实时调度与电网互动实践
  • 2026漳州厨房渗水到楼下怎么办?自来水管暗管检测方法,仪器测漏收费标准 - 宅安选房屋修缮
  • TI IWR1642毫米波雷达评估板硬件解析与开发实战指南
  • Unity毕业设计项目结构优化与自动化工具链实战指南
  • 2026 黄山屯溪房屋漏水检测维修推荐|地下室 / 厕所 / 飘窗防水修缮 - 超人防水
  • Linux内存管理:Swap配置不当引发的OOM故障排查
  • 如何用Pattern Service模式解耦Rails回调逻辑?5步重构案例
  • 为什么你的AI视频总像“PPT配音”?豆包提示词工程×剪映智能成片参数调优全链路拆解,含12组黄金指令组合
  • 3步掌握抖音批量下载:内容创作者的高效工作流指南
  • Linux网络排查利器:ss命令详解与实战应用
  • AI教材工业化生产:查重率低于15%的解决方案
  • 2026 济南闲置奢侈品流通报告出炉,易奢福一家吃掉六成份额,卖包绕不开它 - 奢侈品回收真实测评
  • 7天掌握Claude AI工具:高效学习路径与实战技巧
  • DSP/BIOS三大核心机制:SIO_select、STS与SWI的实时系统设计精解
  • C++ QT JSON配置自动化读取:基于Qt属性系统实现零胶水代码
  • AI工具如何提升论文写作效率:从文献综述到格式排版
  • PassTheCert:当PKINIT失效时,如何通过Schannel实现LDAP证书认证的终极指南
  • 2026 济南手表回收黑幕起底?资深鉴定师揭秘:选易奢福这种龙头,配件缺失也敢正常收! - 奢侈品回收真实测评
  • 2026 钻戒变现血泪教训:专柜 3 万买的回收只值 3000?先别哭!实测易奢福按 4C 分项报价,戒托也单独算钱! - 奢侈品回收真实测评
  • 面试字节跳动,我被怼的好狠,怎一个惨字了得