ATOM模块详解:ATOM与TOM的区别、ATOM的多种操作模式、信号生成与路由

好,咱们接着聊GTM的核心模块。上一章我们把TOM模块讲透了,这一章重点看ATOM。很多工程师刚接触TC3xx时,都会问一个问题:ATOM和TOM到底有啥区别?说白了,TOM是个“老实人”,你给它配好参数,它就老老实实输出PWM。而ATOM呢?它是个“多面手”,能干的事情远不止输出波形这么简单。

ATOM与TOM的本质区别

先看硬件结构。TOM每个通道只有一个比较器,输出逻辑相对固定。ATOM每个通道内部,除了基本的比较器,还多了一个状态机动作控制器。这个状态机,就是ATOM的灵魂。

我打个比方。TOM像一把螺丝刀,只能拧螺丝。ATOM像一把瑞士军刀,能拧螺丝、能开瓶、能剪线。你想想看,同样是输出PWM,ATOM能做的事情就丰富多了。

具体区别我列个表,大家一目了然:

对比项 TOM ATOM
核心结构 比较器 + 输出逻辑 比较器 + 状态机 + 动作控制器
操作模式 固定PWM模式 多种模式(PWM、串行、IO捕捉等)
信号路由 直接输出到IO 可路由到内部子模块(DPLL、TIM等)
触发源 仅CN0匹配 CN0匹配 + 外部事件 + 软件触发
典型应用 普通PWM、电机控制 复杂时序、协议模拟、高精度测量

嗯,这里要注意:ATOM的每个通道,其实可以看作一个微型状态机。它内部有4个状态寄存器,可以定义不同的动作序列。这一点,是TOM完全不具备的。

ATOM的多种操作模式

ATOM支持的操作模式,我数了数,官方文档里列了7种。但实际项目中常用的,也就那么4种。我按使用频率给大家排个序。

1. PWM模式(最常用)

这个模式和TOM的PWM输出类似,但多了些花活。比如,你可以配置ATOM在PWM的上升沿或下降沿,触发一个内部事件。我在项目中遇到过,需要用一个PWM信号同时控制两个不同的外设,一个在上升沿动作,一个在下降沿动作。用ATOM的PWM模式,一个通道就搞定了。

配置代码示例:

// ATOM通道0配置为PWM模式
IfxGtm_Atom_Pwm_Config config;
IfxGtm_Atom_Pwm_initConfig(&config, &g_gtm);
config.atom = IfxGtm_Atom_0;
config.timerChannel = IfxGtm_Atom_Ch_0;
config.period = 10000;      // 周期
config.dutyCycle = 5000;    // 占空比50%
config.signalOutput = IfxGtm_Atom_Ch_0_OUT;
config.signalOutputInverted = IfxGtm_Atom_Ch_0_OUT_INV;
IfxGtm_Atom_Pwm_init(&g_atomPwm, &config);

2. 串行输出模式

这个模式很有意思。ATOM可以模拟一个简单的串行协议,比如SPI或自定义的3线协议。它内部的状态机,可以按照你定义的时序,逐位输出数据。

我记得有一次,客户要求用PWM引脚同时输出一个同步头和数据。如果用TOM,你得用两个通道,还得做同步。用ATOM的串行输出模式,一个通道就搞定了。配置时,你需要定义每个bit的宽度和电平。

小提示:串行输出模式适合低速协议,比如几百KHz以下。如果频率太高,建议还是用专用的SPI模块。ATOM的串行模式,更多是用于“救急”场景——比如PCB已经画好了,发现少了一根控制线。

3. IO捕捉模式

这个模式,说白了就是让ATOM去“监听”外部信号的变化。它可以捕捉上升沿、下降沿,或者某个电平的持续时间。我经常用它来做脉冲宽度测量。

举个例子,你需要测量一个霍尔传感器的脉冲宽度。用TIM模块当然也行,但TIM资源有限。ATOM的IO捕捉模式,可以分担一部分测量任务。配置时,你只需要指定触发边沿和捕捉的计数器。

// ATOM通道1配置为IO捕捉模式
IfxGtm_Atom_Io_Capture_Config captureConfig;
IfxGtm_Atom_Io_Capture_initConfig(&captureConfig, &g_gtm);
captureConfig.atom = IfxGtm_Atom_0;
captureConfig.channel = IfxGtm_Atom_Ch_1;
captureConfig.inputPin = &g_pinHallSensor;
captureConfig.edge = IfxGtm_Atom_Io_Capture_Edge_rising;
IfxGtm_Atom_Io_Capture_init(&g_atomCapture, &captureConfig);

4. 事件触发模式

这个模式比较特殊。ATOM可以响应内部事件,比如DPLL的同步信号,或者TIM的触发信号。你想想看,当DPLL检测到某个角度位置时,ATOM立刻输出一个脉冲。这种“事件驱动”的方式,在发动机控制中非常常见。

我曾经调试过一个喷油系统,要求曲轴转到特定角度时,精确输出喷油脉冲。用ATOM的事件触发模式,配合DPLL的角度信号,精度可以做到0.1度以内。

信号生成与路由

ATOM生成信号后,怎么送到目标引脚?这里有个关键概念:信号路由矩阵。TC3xx内部有一个复杂的交叉开关,可以把ATOM的输出,连接到任意一个GPIO引脚。

我刚开始接触时,也被这个路由搞晕过。后来总结了一个口诀:先配通道,再选输出,最后连引脚。具体来说,分三步:

  1. 配置ATOM通道:选择操作模式、设置参数
  2. 选择输出信号:每个ATOM通道有多个输出信号(比如OUT、OUT_INV、OUT_EVENT等)
  3. 连接GPIO:通过Port模块的配置,把信号路由到具体引脚

代码示例:

// 第一步:ATOM通道配置(略,见上文)
// 第二步:选择输出信号
config.signalOutput = IfxGtm_Atom_Ch_0_OUT;
// 第三步:连接GPIO
IfxPort_setPinMode(&MODULE_P00, 0, IfxPort_Mode_outputPushPullGeneral);

警告:ATOM的输出信号,不能直接连接到所有引脚。每个ATOM通道,有固定的输出映射表。比如ATOM0_CH0的输出,只能连接到P00.0、P10.2等几个引脚。配置前,一定要查芯片的引脚复用表。我曾经因为没查表,浪费了半天时间。

另外,ATOM的信号还可以路由到内部子模块。比如,你可以把ATOM的输出,送到TIM模块做进一步处理,或者送到DPLL做角度同步。这种内部路由,不需要经过GPIO,延迟更小。

内部路由的配置方式:

// 将ATOM0_CH0的输出路由到TIM0_CH0
IfxGtm_Atom_0_CH0_OUT -> IfxGtm_Tim_0_CH0_IN;
// 具体配置需要设置GTM的交叉开关寄存器
IfxGtm_setAtomOutputToTimInput(g_gtm, IfxGtm_Atom_0, IfxGtm_Atom_Ch_0, IfxGtm_Tim_0, IfxGtm_Tim_Ch_0);

避坑指南

最后,分享几个我踩过的坑:

  • 坑1:ATOM通道的时钟源。ATOM的时钟可以来自CMU_CLK0、CMU_CLK1或FXU。我建议统一用CMU_CLK0,除非你有特殊需求。混用时钟源,容易导致时序混乱。
  • 坑2:状态机的初始化。ATOM的状态机,上电后默认是IDLE状态。如果你直接配置输出,可能不会立即生效。记得先调用IfxGtm_Atom_setChannelAction,把状态机切换到RUNNING状态。
  • 坑3:中断处理。ATOM的中断,可以配置为比较匹配、溢出或事件触发。但要注意,中断服务函数里不要做耗时操作。我曾经在中断里调了一个printf,结果系统直接卡死。

好了,ATOM模块的核心内容就这些。下一章,我们会讲DPLL模块,那是GTM里最复杂、也最强大的部分。到时候,我会结合一个实际案例,带大家一步步配置DPLL。