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引脚。
我刚开始接触时,也被这个路由搞晕过。后来总结了一个口诀:先配通道,再选输出,最后连引脚。具体来说,分三步:
- 配置ATOM通道:选择操作模式、设置参数
- 选择输出信号:每个ATOM通道有多个输出信号(比如OUT、OUT_INV、OUT_EVENT等)
- 连接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。