CC13x2/CC26x2射频命令系统:触发与条件执行机制深度解析
2026/7/26 6:36:00 网站建设 项目流程

1. 项目概述与核心价值

在嵌入式无线通信系统的开发中,如何让射频操作像交响乐一样精准、有序地进行,是每个工程师都会面临的挑战。想象一下,你的设备需要在毫秒级甚至微秒级的时间窗口内完成数据包的发送、接收,同时还要处理来自外部传感器的信号,并且这一切都要在极低的功耗下完成。如果所有时序都由主CPU(系统CPU)通过轮询或中断来管理,不仅代码会变得复杂臃肿,实时性难以保证,功耗也会居高不下。这正是德州仪器CC13x2/CC26x2系列SimpleLink™无线MCU的射频命令系统所要解决的核心问题。

这套系统的价值,在于它将复杂的射频时序控制硬件化了。它提供了一个由专用射频CPU(Radio CPU)驱动的命令引擎,允许开发者预先编排好一系列射频操作(如设置射频参数、启动发射、启动接收等),并为其附加上精确的触发条件和执行逻辑。然后,主CPU就可以“提交”这个命令链,转而处理其他任务,由射频CPU在后台严格按照预设的时序自动执行。这就像为射频部分配备了一个专业的“执行导演”,主CPU只需下达“拍摄计划”,具体的“镜头调度”和“演员走位”都由导演自动完成。

本文将深入拆解这套命令系统中两个最核心的机制:触发机制条件执行。它们共同构成了射频操作精准调度与智能流转的基石。我们将不仅解读技术手册中的寄存器定义,更会结合实际的开发场景,探讨如何运用这些机制来设计高效、可靠的无线通信任务,并分享在调试过程中积累的实战经验和避坑指南。

2. 触发机制:为射频操作设定精准的“发令枪”

触发机制的本质,是为每一个射频操作命令定义一个启动的“时刻”或“事件”。在CC13x2/CC26x2的架构中,每个射频操作命令(Radio Operation Command)的数据结构里都包含一个startTrigger字段,它决定了这个命令何时开始执行。

2.1 触发定义字节的深度解析

触发条件由一个8位的“触发定义字节”来配置,其格式是理解整个机制的钥匙。我们逐位分析其含义:

Bit 0-3:triggerType(触发类型)这4位定义了十多种具体的触发条件,是机制灵活性的核心。手册中列举了从0到10的类型,我们需要理解其应用场景:

  • TRIG_NOW (0): 立即触发。命令在提交后,一旦轮到它执行(满足前序命令条件),就会立刻开始。这通常用于链中的第一个命令,或者不需要特定时序的立即操作。
  • TRIG_NEVER (1): 永不触发(除非被命令触发)。单独设置此类型且未启用命令触发(bEnaCmd=0)会导致错误。它的主要用途是配合命令触发(CMD_TRIGGER),实现由软件动态决定何时启动。
  • TRIG_ABSTIME (2): 在绝对时间触发。时间参数指向一个32位的RAT(Radio Timer)绝对计数值。当RAT计数到达该值时,命令启动。这适用于需要与系统绝对时间同步的场景,比如在预定的全球时间点发送信标。
  • TRIG_REL_SUBMIT (3): 相对于命令提交时刻触发。时间参数是一个以RAT tick为单位的相对偏移量。例如,设置偏移为1000,假设RAT频率为4MHz(1 tick=0.25us),则该命令将在提交后250us启动。
  • TRIG_REL_START (4): 相对于本命令的开始时刻触发。特别注意:此类型不允许用于startTrigger(即命令自身的启动触发器),否则会产生错误。它用于定义命令内部的某个动作(如“在开始发射后100us切换某个GPIO”),这通常在命令的附加参数中定义。
  • TRIG_REL_PREVSTART (5): 相对于前一个命令的开始时刻触发。这是构建严格时序链的关键。例如,命令A(发射)使用TRIG_NOW,命令B(接收)使用TRIG_REL_PREVSTART并设置时间参数为X,那么B将在A开始后的X个tick时启动,从而实现精确的“发后即收”时序。
  • TRIG_REL_FIRSTSTART (6): 相对于命令链中第一个命令的开始时刻触发。这对于需要以链首为时间基准的周期性或复杂序列非常有用。
  • TRIG_REL_PREVEND (7): 相对于前一个命令的结束时刻触发。当你不关心前一个命令何时开始,但必须在其完全结束后才能启动下一个操作时(例如,等待频率合成器稳定后再发射),这个类型就非常合适。
  • TRIG_REL_EVT1/EVT2 (8, 9): 相对于前一个命令定义的事件1或事件2触发。这是高级功能,允许命令内部的关键时间点(如“检测到前导码”、“完成CRC校验”)成为后续命令的触发基准。具体事件由每个命令自行定义。
  • TRIG_EXTERNAL (10): 在外部触发输入信号上触发。时间参数用于配置具体的输入源(如RFC_GPI0)和边沿(上升沿、下降沿或双边沿)。这实现了硬件事件(如传感器中断)直接触发射频操作,延迟极低。

Bit 4:bEnaCmd(启用命令触发)这是一个“逃生舱”或“后门”。当设置为1时,即使triggerType被设置为TRIG_NEVER或其他未来时间,该命令也可以被一个专门的CMD_TRIGGER命令立即启动。CMD_TRIGGER命令需要指定triggerNo来匹配目标命令。这为软件动态干预预置的时序计划提供了可能。

Bit 5-6:triggerNo(触发编号)bEnaCmd=1时,此字段指定了用于触发此命令的CMD_TRIGGER命令所使用的触发编号(0-3)。这允许多个命令共享同一个软件触发源,或者被独立的软件触发源控制。

Bit 7:pastTrig(过去触发处理)这是一个非常关键的容错和实时性处理位。考虑这种情况:你设置了一个在绝对时间T触发的命令,但由于系统CPU繁忙,命令链在T时刻之后才被提交给射频CPU。此时,触发时间已经在“过去”。

  • pastTrig = 0: 严格模式。对于启动触发器,这将产生一个ERROR_PAST_START错误。对于非启动触发器(如命令内部事件),该触发将被忽略。这确保了时序的绝对准确性,任何延迟都会导致失败,便于调试。
  • pastTrig = 1: 尽快模式。如果触发时间已过,射频CPU会尝试“尽快”执行该操作。但有一个重要细节:如果这是启动触发器,那么命令内部任何基于TRIG_REL_START的相对时间计算,仍然会以编程的(已过去的)开始时间T为基准,而不是实际的启动时间。这可能导致内部时序错乱,需要特别注意。

实操心得:pastTrig位的选择策略在低功耗间歇性工作的设备中(如每秒唤醒一次发送数据的传感器),我通常将pastTrig设为1。因为设备从深度睡眠唤醒、初始化射频、再提交命令链需要一定时间,很难保证第一次操作的绝对时间精准命中。设为“尽快”模式可以提高系统的鲁棒性。但在需要严格周期性或高精度时间同步(如TDMA网络)的应用中,必须设为0,并通过精确的唤醒和命令预加载来确保时序,任何“过去触发”都应被视为错误并进入异常处理流程。

2.2 时间参数与外部触发详解

除了TRIG_NOWTRIG_NEVER,其他触发类型都需要一个32位的startTime参数。

  • 绝对与相对时间:对于TRIG_ABSTIMEstartTime是RAT计时器的绝对目标值。对于TRIG_REL_*系列,startTime是相对于参考点的tick数偏移量。RAT通常由高频时钟(如4MHz)驱动,提供了微秒级的时间分辨率。
  • 外部触发配置:对于TRIG_EXTERNALstartTime参数的位域被重新解释,用于配置输入源和边沿。
    • inputMode(位2-3): 定义在哪种信号边沿上触发 (00: 上升沿,01: 下降沿,10: 双边沿)。
    • source(位8-12): 选择输入源。例如,22对应RFC_GPI023对应RFC_GPI1。这些RFC_GPI引脚可以通过芯片的I/O控制器映射到具体的物理引脚上。

注意事项:外部触发的“捕获”机制手册中提到,对于外部触发,射频CPU会配置RAT使用选定的输入事件作为“单次捕获”触发器。这里有一个潜在的坑:如果外部事件在射频CPU完成此设置之前就发生了,那么该事件将不会被捕获,并且pastTrig位会被忽略。这意味着你可能永远等不到这个触发。因此,在启用外部触发前,必须确保外部事件源处于稳定状态,或者在软件流程上保证配置完成后再使能事件源。

2.3 构建复杂时序链的实战技巧

理解了基本类型后,我们可以组合出复杂的时序。假设我们要实现一个“监听-响应”协议:设备大部分时间休眠,每秒唤醒并开启接收窗口(100ms),如果在窗口内收到特定唤醒包,则立即发送一个应答包,然后继续监听剩余窗口。

  1. 命令链设计:

    • Cmd1 (CMD_RX):startTrigger = TRIG_NOW,pastTrig=1。 立即启动接收。
    • Cmd2 (CMD_TX):startTrigger = TRIG_REL_PREVSTART,time = 0,pastTrig=1。 它的启动依赖于一个条件:仅当Cmd1因收到有效唤醒包而结束(结果为TRUE)时(这涉及到下一节的条件执行)。时间参数为0表示在Cmd1结束后立即开始。
    • Cmd3 (CMD_RX):startTrigger = TRIG_REL_PREVEND,time = 2000(假设500us),pastTrig=1。 在Cmd2发送结束后500us,重新开启接收,以接收可能的后续数据或继续监听。
  2. 时间基准管理:在长周期任务中(如每小时发送一次数据),使用TRIG_ABSTIME并基于RAT的绝对时间(可能由实时时钟RTC同步)是更可靠的选择,可以避免由于短周期任务延迟累积造成的时间漂移。

3. 条件执行:让命令链具备“智能决策”能力

触发机制解决了“何时做”的问题,而条件执行则解决了“做不做”以及“接下来做什么”的问题。它使得命令链不再是僵化的线性序列,而可以根据前一个命令的执行结果进行动态分支,实现了简单的状态机逻辑。

3.1 条件字节与执行规则

每个命令结构中都包含一个condition字节,用于定义在当前命令执行完毕后,如何决定下一个命令的执行路径。

条件字节格式:

  • Bit 0-3:rule(规则): 定义了核心的条件逻辑,共有6种规则。
  • Bit 4-7:nSkip(跳过数量): 当规则涉及“跳过”时,此字段表示跳过的命令数加1。0表示重复执行当前命令自身,1表示执行下一个命令(即不跳过),2表示跳过下一个命令,依此类推。

六种条件规则详解:

  1. COND_ALWAYS (0):总是执行下一个命令(除非前一个命令的结果是ABORT)。这是最常用的默认规则,用于构建顺序执行链。

  2. COND_NEVER (1):永不执行下一个命令。即使设置了pNextOp指针,也会被忽略(可以为NULL)。这用于终止一个命令链。例如,一个持续监听直到收到特定消息才停止的接收命令,就可以使用此规则,收到消息后通过其他方式(如中断)通知系统CPU启动新的链。

  3. COND_STOP_ON_FALSE (2): 如果本命令返回TRUE,则运行下一个命令;如果返回FALSE,则停止整个链的执行。射频CPU进入空闲状态,并产生LAST_COMMAND_DONE中断。这用于实现“成功才继续”的逻辑。例如,先执行一个信道评估命令(CMD_CCA),如果信道忙(返回FALSE)则停止,等待下次调度;如果信道空闲(返回TRUE)则继续执行发射命令。

  4. COND_STOP_ON_TRUE (3): 与上一条相反。如果本命令返回TRUE则停止,返回FALSE才继续。适用于“失败重试”或“找到目标即停止”的场景。例如,一个扫描多个信道的接收命令,一旦在某个信道收到数据(TRUE)就停止扫描,否则继续扫描下一个信道。

  5. COND_SKIP_ON_FALSE (4): 如果本命令返回TRUE,则运行下一个命令(nSkip通常为1)。如果返回FALSE,则跳过nSkip个命令。这实现了条件跳转。nSkip必须提前设置好。

  6. COND_SKIP_ON_TRUE (5): 如果本命令返回TRUE,则跳过nSkip个命令;如果返回FALSE,则运行下一个命令。同样是条件跳转,只是逻辑相反。

3.2 命令结果:TRUE, FALSE, ABORT

条件执行的基础是前一个命令的“结果”。每个射频操作命令结束时,都会产生以下三种结果之一:

  • TRUE: 通常表示命令成功完成其预期操作。例如,CMD_RX成功接收到一个完整且CRC正确的数据包;CMD_TX成功发送完一个数据包;CMD_CCA检测到信道空闲。
  • FALSE: 通常表示命令已执行完毕,但未达成主要目标。例如,CMD_RX在超时时间内未收到任何数据;CMD_CCA检测到信道繁忙。
  • ABORT: 表示命令因错误或外部干预而异常终止。产生ABORT的常见原因包括:
    • 收到了CMD_ABORT命令。
    • 命令参数非法(ERROR_PAR)。
    • 启动触发器非法或发生在过去且pastTrig=0ERROR_START_TRIG,ERROR_PAST_START)。
    • 条件字节非法(ERROR_CONDITION)。
    • 未执行CMD_RADIO_SETUP就尝试使用收发器(ERROR_NO_SETUP)。

关键特性:一旦命令以ABORT结束,无论其condition字段如何设置,整个命令链的执行都会立即终止,并产生LAST_COMMAND_DONE中断。ABORT具有最高优先级。

3.3 条件执行的高级应用与跳转逻辑

通过组合COND_SKIP_ON_*规则和nSkip字段,可以实现命令链内的循环和分支。

示例:实现一个简单的重传机制假设我们有一个命令链:CmdA (TX), CmdB (RX for ACK), CmdC (备用处理),我们希望在发送(CmdA)后等待应答(CmdB),如果收到应答(TRUE)就结束,如果超时未收到(FALSE)就重传一次。

  1. 链结构:

    • CmdA:condition = COND_SKIP_ON_FALSE,nSkip = 1pNextOp指向CmdB
    • CmdB:condition = COND_SKIP_ON_TRUE,nSkip = 2pNextOp指向CmdC
    • CmdC:condition = COND_NEVERpNextOp = NULL
    • CmdC之后,我们在内存中紧接着再放置一个CmdA的副本(或指向原CmdA的指针,但需要注意状态重置)。
  2. 执行流程:

    • 系统CPU提交链,从CmdA开始执行(发送)。
    • CmdA完成,结果为TRUE(发送成功)。根据其条件(COND_SKIP_ON_FALSE,结果为TRUE),它执行下一个命令,即CmdB(等待应答)。
    • CmdB执行:
      • 如果收到ACK (TRUE),根据其条件(COND_SKIP_ON_TRUE,结果为TRUE),它跳过2个命令。从CmdB位置跳过2个命令,会跳过CmdC和后面那个CmdA副本,链结束(因为CmdCpNextOpNULLCOND_NEVER)。
      • 如果超时 (FALSE),根据其条件(COND_SKIP_ON_TRUE,结果为FALSE),它执行下一个命令,即CmdC(备用处理,例如记录错误)。
      • CmdC执行后,因其condition = COND_NEVER,链结束。注意:这个设计下,超时后并未跳回CmdA重传。要实现重传,需要更精巧的指针编排,或者利用nSkip=0(重试当前命令)的特性,但需注意避免死循环。

避坑指南:条件跳转与内存布局使用COND_SKIP_ON_*时,nSkip计算的是命令结构指针的偏移量,而非逻辑顺序。你必须非常清楚命令结构在内存中的连续排列方式。一个常见的错误是,在动态分配或复杂链式中错误计算了nSkip值,导致跳转到错误的命令甚至非法内存地址,引发ERROR_POINTER错误。在开发初期,建议先用COND_ALWAYSCOND_NEVER构建线性链,稳定后再引入条件跳转,并仔细绘制内存布局图。

4. 命令结构与数据队列:触发与条件的载体

理解了原理,我们还需要知道这些机制如何落实到具体的代码和数据结构上。所有射频操作命令都基于一个通用的命令结构,而涉及数据收发的命令则需要与数据队列协同工作。

4.1 射频操作命令通用结构

如表25-9所示,每个射频操作命令的前14个字节是固定的:

字节索引字段名类型描述
0-1commandNoW命令ID(如0x0802代表CMD_RADIO_SETUP)。
2-3statusR/W命令执行状态码,由射频CPU更新。系统CPU可随时读取以查询进度或结果。
4-7pNextOpW指向下一个要执行的操作命令的指针。这是实现命令链和条件执行跳转的关键。
8-11startTimeW32位时间参数,与startTrigger配合使用。
12startTriggerW8位触发定义字节,定义本命令的启动条件。
13conditionW8位条件字节,定义本命令执行完毕后如何选择下一个命令。

关键点解析

  • pNextOp的灵活性:它不一定指向内存中紧接着的下一个命令结构。通过结合conditionnSkip,它可以实现非顺序的跳转。当conditionCOND_NEVER时,这个指针可以被忽略(设为NULL)。
  • status字段的实时性:系统CPU可以通过轮询或结合射频中断来读取此字段,以了解命令是正在进行(BUSY_PENDING)、已完成(DONE_OK),还是发生了错误(如ERROR_PAST_START)。这是调试复杂时序问题的重要依据。

4.2 数据队列与数据条目

对于收发数据(CMD_TX,CMD_RX)等命令,需要操作数据缓冲区。系统通过数据队列数据条目来管理这些缓冲区。

  • 数据队列结构 (dataEntryQueue):包含pCurrEntry(指向当前正被射频CPU使用的条目)和pLastEntry(指向队列中最后一个条目)两个指针。它管理着一个由数据条目构成的链表。
  • 通用数据条目结构 (dataEntry):这是一个链表节点,包含pNextEntry(指向下一个条目)、status(条目状态)、config(配置信息,如数据类型和长度格式)、length(数据长度)和data(数据缓冲区或指针)字段。
    • 状态流PENDING->ACTIVE->BUSY->FINISHED。系统CPU在提交条目前将其状态设为PENDING。射频CPU在开始处理时将其改为ACTIVE,处理中为BUSY,处理完毕为FINISHED,此时系统CPU可以回收缓冲区。
    • 配置config.type
      • 0: 通用数据条目,数据存储在条目自身的data数组中。
      • 2:指针条目data字段被替换为一个pData指针,指向实际的数据缓冲区。这在数据缓冲区需要被多个命令复用或位于特定内存区域时非常有用。
      • 3:部分读取RX条目。用于专有模式,允许在数据包未完全接收完毕前就开始读取部分数据,适用于流式传输或处理超长数据包。

触发、条件与数据队列的协同: 一个典型的RX命令链可能这样工作:CMD_RADIO_SETUP->CMD_RX(触发方式:TRIG_NOW, 条件:COND_STOP_ON_TRUE)。CMD_RX命令会关联一个RX数据队列。当射频CPU根据触发条件启动CMD_RX后,它会从队列中取出一个PENDING状态的数据条目,开始接收数据。如果成功收到一个包(结果TRUE),根据COND_STOP_ON_TRUE,链停止,产生中断通知系统CPU。系统CPU读取statusDONE_OK,并检查数据队列,找到状态为FINISHED的条目,从中提取数据。如果超时(结果FALSE),根据条件,链会继续执行下一个命令(如果有的话)。

5. 实战案例:构建一个低功耗周期性信标发射器

让我们用一个完整的、简化的案例来串联所有概念。目标:设备每秒钟唤醒一次,在唤醒后的第10毫秒精确发射一个信标包,然后立即返回深度睡眠。

5.1 系统设计

  1. 硬件定时器:使用RTC(实时时钟)或一个低频时钟源来产生1秒的周期性中断,唤醒系统CPU。
  2. 射频时序:使用RAT(射频定时器)来提供高精度的时间基准(假设为4MHz)。10ms对应40000个RAT tick。
  3. 命令链设计:我们需要两个命令。
    • Cmd1:CMD_RADIO_SETUP:配置射频模式和参数。我们希望它尽快执行。
    • Cmd2:CMD_TX:执行发射。我们需要它在系统唤醒后第10ms执行。

5.2 命令链配置与代码示意

以下是关键数据结构的配置思路(以伪代码和注释形式呈现):

// 假设 RAT 当前绝对时间为 ratNow uint32_t targetTime = ratNow + 40000; // 计算10ms后的绝对时间 // 命令链在内存中的连续存储 typedef struct { rfc_radioOp_t setupCmd; // CMD_RADIO_SETUP 结构体 rfc_radioOp_t txCmd; // CMD_TX 结构体 uint8_t txData[BEACON_SIZE]; // 发射数据缓冲区 } beaconCmdChain_t; beaconCmdChain_t cmdChain; // 1. 配置 SETUP 命令 cmdChain.setupCmd.commandNo = CMD_RADIO_SETUP_ID; cmdChain.setupCmd.startTime = 0; // 对于 TRIG_NOW,此字段忽略 cmdChain.setupCmd.startTrigger.byte = 0; cmdChain.setupCmd.startTrigger.field.triggerType = TRIG_NOW; cmdChain.setupCmd.startTrigger.field.pastTrig = 1; // 尽快执行 cmdChain.setupCmd.condition.byte = 0; cmdChain.setupCmd.condition.field.rule = COND_ALWAYS; // 总是执行下一个命令 cmdChain.setupCmd.pNextOp = &cmdChain.txCmd; // 指向TX命令 // ... 填充 CMD_RADIO_SETUP 特有的参数 (mode, txPower等) // 2. 配置 TX 命令 cmdChain.txCmd.commandNo = CMD_TX_ID; cmdChain.txCmd.startTime = targetTime; // 绝对触发时间 cmdChain.txCmd.startTrigger.byte = 0; cmdChain.txCmd.startTrigger.field.triggerType = TRIG_ABSTIME; // 绝对时间触发 cmdChain.txCmd.startTrigger.field.pastTrig = 0; // 严格要求时序,过去则报错 cmdChain.txCmd.condition.byte = 0; cmdChain.txCmd.condition.field.rule = COND_NEVER; // 发射后链结束 cmdChain.txCmd.pNextOp = NULL; // ... 配置TX数据队列,将 txData 关联到TX命令的数据条目 // 3. 系统CPU在RTC唤醒中断服务程序中执行 void RTC_Wakeup_ISR(void) { // 快速读取当前RAT时间,计算targetTime // 将targetTime写入 cmdChain.txCmd.startTime // 通过写入CMDR寄存器,将 &cmdChain.setupCmd 提交给射频CPU RFCDoorbellSendTo((uint32_t)&cmdChain.setupCmd); // 系统CPU可以立即进入睡眠,射频CPU将自动执行后续序列 }

5.3 潜在问题与调试技巧

  1. 时序抖动:虽然RAT精度很高,但系统CPU从唤醒、计算时间到提交命令存在延迟。这个延迟会导致targetTime可能已经略微过去。如果pastTrig=0,第一次提交就可能因ERROR_PAST_START而失败。解决方案:要么像上面一样设置pastTrig=1(接受微小抖动),要么在睡眠前就预加载命令链,并将startTrigger设为TRIG_REL_SUBMIT,提交命令本身作为启动参考点,但这需要射频部分在睡眠期间保持部分供电(更高功耗)。

  2. 命令链提交竞争:如果上一次发射的命令链还未执行完毕(例如,射频CPU还在处理),就提交新的命令链,会导致未定义行为。必须在提交新链前,通过检查射频CPU状态寄存器或等待LAST_COMMAND_DONE中断,确保射频CPU处于空闲(IDLE)状态。

  3. 状态字段检查:在调试阶段,在提交命令链后,定期或在中断服务程序中检查命令的status字段至关重要。如果看到ERROR_PAST_STARTERROR_START_TRIGERROR_CONDITION,就能快速定位到触发或条件配置的错误。

  4. 使用CMD_NOP进行调试CMD_NOP是一个只包含触发和条件的基本命令。在构建复杂链之前,可以先用几个CMD_NOP命令测试你的触发和条件逻辑是否正确。通过观察它们是否按预期顺序执行,可以验证你对pNextOpconditionnSkip的理解是否正确。

6. 高级话题与性能考量

6.1 外部触发的超低延迟响应

TRIG_EXTERNAL机制将外部硬件事件(如GPIO边沿)直接耦合到射频操作,实现了近乎零软件延迟的响应。这对于需要快速反应的应用(如无线触发、实时控制)至关重要。

实现要点

  1. 引脚映射:需要通过I/O控制器将物理GPIO映射到RFC_GPI0/1
  2. 去抖与滤波:射频CPU对输入信号的响应非常快,如果外部信号有毛刺,可能导致误触发。需要在硬件或软件(如果信号由另一个MCU产生)上增加适当的滤波。
  3. 事件捕获窗口:如前所述,确保在使能外部事件源之前,射频CPU已经完成了触发器的配置(即CMD_TXCMD_RX命令已提交且射频CPU已就绪)。

6.2 条件执行实现复杂协议状态机

通过精心设计命令链和条件规则,可以在硬件层面实现简单的协议状态机,极大减轻系统CPU的负担。

示例:简单的CSMA/CA(载波侦听多路访问)

  1. CmdA (CMD_CCA): 侦听信道。condition = COND_SKIP_ON_TRUE,nSkip = X。如果信道忙(TRUE),跳过后续的发射命令,执行退避或等待。如果空闲(FALSE),执行下一个命令(发射)。
  2. CmdB (CMD_TX): 发射数据包。condition = COND_ALWAYS
  3. CmdC (CMD_RX): 等待ACK。condition = COND_SKIP_ON_FALSE,nSkip = Y。如果收到ACK(TRUE),发送成功,链结束。如果超时(FALSE),跳转到退避或重传逻辑(可能指向另一个包含延迟CMD_NOP和重回CmdA的链)。

这个状态机完全由射频CPU驱动,系统CPU只在最终成功或彻底失败时被中断通知。

6.3 内存与功耗权衡

  • 命令链预存储:可以将常用的命令链(如连接建立序列、数据收发序列)预先存储在RAM甚至保留内存中。系统CPU在需要时只需更新少量参数(如时间、数据指针)即可提交,减少了实时计算和配置的开销,特别适合低功耗场景下的快速唤醒。
  • 动态命令构建:对于协议灵活多变的应用,可能需要动态构建命令链。这增加了软件复杂性,但提供了最大的灵活性。需要注意内存分配的对齐要求(命令结构需要32位对齐)以及避免内存碎片。
  • 射频CPU的功耗:只要射频CPU在执行命令链,它就会消耗能量。在设计长间隔、低占空比的应用时,要确保命令链执行完毕后,射频CPU能及时进入低功耗状态(通常通过以COND_NEVER结束的命令链实现),并且系统CPU能及时进入睡眠。

CC13x2/CC26x2的射频命令系统,通过硬件化的触发与条件执行机制,将开发者从繁琐的射频时序管理中解放出来。掌握startTrigger中各种时间与事件触发的精妙搭配,理解condition规则带来的流程控制能力,是编写高效、稳定无线固件的关键。从简单的周期性广播,到复杂的带有冲突避免和确认重传的协议,都可以通过精心编排的命令链来实现。记住,多利用CMD_NOP进行逻辑测试,勤于检查命令的status字段,你就能驾驭这套强大的系统,让你无线应用的设计如虎添翼。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询