TI TMS470高端定时器HET之HAL Co Gen配置PWM输出功能

最近使用TI的TMS470的PWM功能时发现其使用HET实现的方式很特别。而且相关的资料很少,特意将相关内容记录下来,希望能辅助到大家的学习。

HET是什么?和普通的定时器Timer有什么区别?

在PWM输出功能之前首先肯定得先知道HET是什么。
HET,TI给的名字叫high-end timer,即高端定时器。注意,是高端定时器不是高级定时器。我看第一眼的时候也没反应过来。
那么这个所谓的高端定时器究竟有多高端?
其实HET默认的功能是非常少的,这个从应用手册中的里面就能看出来,这个HET根本没几个寄存器,也没有PWM的相关功能。但是当你详细阅读的时候会发现TI专门为定时器划定了一个RAM区域(0xFF46 0000~0xFF47 FFFF),这就是定时器的高端之处。
HET拥有一段RAM区域用户可以在这段区域中放置相关的指令,同时定时器拥有运行这些指令的能力。
简单的理解,可以把HET看成一个协处理器。其具有与CPU独立的指令集。用户可以通过对其编程(工具:HET IDE)实现多种功能。嵌入式系统通常会有一系列计时和通讯需求。 通常,这些需求会在系统设计时间解锁。 为支持更复杂的计时功能或保护通讯的灵活性,人们可能会有增加外部 ASIC 或 FPGA 的需求。 这些外部设备会增加成本、功耗、复杂性和电路板空间。而这个HET就能够在一定程度上替代这些额外部件,降低成本。

HET的PWM功能特色

传统的MCU拥有的PWM数量与功能是确定的。而TI的PWM生成器数量理论是无限个(当然实际上还是受限于输出引脚数量与RAM空间大小)
比如以STM32为例,定时器分为高级、通用和基本,其中只有高级定时器拥有PWM全部的功能,而基本定时器没有PWM功能。定时器虽然有多个输出通道,但是多通道的PWM拥有同一周期,只是占空比不同。每要生成一个占空比和周期完全不同的,PWM那么需要重新开启一个定时器。但是HET不同,由于PWM是虚拟的,相当于你可以拥有32个完整的PWM功能(因为TMS470只有32个HET输出引脚)而且你可以通过定制,生成3相位互补或者更高数量的协同PWM信号。这在STM32中无法通过硬件自动完成。
而且因为PWM是虚拟的,在Debug调试时可以让其连接Debug断点,当软件执行到断点时,PWM同样可以中断。
在TI论坛中就有一个3相互补的PWM历程:

HAL Co Gen生成PWM历程详解

接下来,我会通过HAL Co Gen生成一个PWM历程,并讲解其中的部分机理。
相关的官方内容在应用手册的12.7 HET->Instruction Set章节,可以一起参照阅读。
软件PWM生成配置
我配置了如图所示的PWM。生成工程后,在het.c就能够找到如下代码,大概在1258行附近

memcpy((void *)hetRAM, (const void *)hetPROGRAM, sizeof(hetPROGRAM));

这行代码的含义就是将hetPROGRAM的数据复制到MCU的0xFF46 0000位置,我之前说了,TMS470的HET专属空间就是这里。所以,我们要分析的内容就是hetPROGRAM这个数组。

/* CNT: Timebase
*       - Instruction                  = 0
*       - Next instruction             = 1
*       - Conditional next instruction = na
*       - Interrupt                    = na
*       - Pin                          = na
*       - Reg                          = T
*/
{
    /* Program */
    0x00001640U,
    /* Control */
    0x01FFFFFFU,
    /* Data */
    0xFFFFFF80U,
	/* Reserved */
	0x00000000U
},

一上面这个代码为例,我先说明下hetPROGRAM内的大致结构,上面代码就是一个命令,hetPROGRAM整个数组都是由一个一个命令构成的,HET总共有21个命令,大部分的命令都是只有3个有效的字,但是为了对齐TI都为其保留了一个,就4个对齐了。
命令类型
从注释中我们可以大概知道这个字的指令号为0,下一命令的指令号为1,有条件的下一指令号为空,没有中断,没有对应引脚。

CNT命令

CNT命令是PWM生成中的首个命令。
CNT命令
分析得出:
BRK = 0,关闭调试时软件断点。就是在Debug时的软件断点不会影响HET命令执行。
Next Program address = 1,接下来执行1区域(hetPROGRAM[1])所在的指令。
Opcode =6,查表12-36得知6代表命令代码CNT。
Angle Count = 0,指定计数器何时递增。只有在设置了新角度标志(NAF_global=1)时,ON的值才会使计数器值递增。每当组装器遇到CNT指令时,OFF值使计数器递增。
Register = 2,T类型寄存器(详:470应用手册表12-40)
Int ena = 0,中断不使能
Control = 1,确定在读取即时数据字段[24:0]时是否清除该字段。
Max count = 0xF FFFF = 1048575,指定20位整数值,用于定义数据字段中允许的最大计数值。当数据字段中的计数等于max时,数据字段重置为0,Z系统标志设置为1
Data = FFFFC,指定用作计数器的20位整数值。

使用HAL Co Gen生成的代码,这一段都没有什么修改的意义。

PWCNT命令

在CNT之后紧跟的就是PWCNT命令了,在这个命令中有两个数值需要关注,就是(2U << 7U) 中的2代表映射到Pin2,(3U << 3U)其中的3代表高低脉冲信号。
PWCNT命令

/* PWCNT: PWM 0 -> Duty Cycle
*         - Instruction                  = 1
*         - Next instruction             = 2
*         - Conditional next instruction = 2
*         - Interrupt                    = 1
*         - Pin                          = 2
*/
{
    /* Program */
    0x00002AE0U,
    /* Control */
    (0x00002006U | (2U << 7U) | (3U << 3U)),
    /* Data */
    0x00000000U,
	/* Reserved */
	0x00000000U
},

BRK = 0,关闭调试时软件断点。
Next Program address = 2,接下来执行2区域(hetPROGRAM[2])所在的指令。
Opcode = A,查表12-36得知A代表指令码分别为DJZ、ECNT、PWCNT、SCNT。
hr_lr = 1,指定高/低数据分辨率。如果hr_lr字段为高,则指令实现hr_data字段(当在hr引脚上执行操作时)。如果hr_lr字段为低,则忽略hr_data字段。
Sub-Opcode = 3,和Opcode一起分析就能明白代表指令是PWCNT。
Control = 0,确定在读取即时数据字段[24:0]时是否清除该字段。
En.Pin Action = 0,说明在PWM初始化的时候不开启输出。
Conditional address = 2,在有选择的情况下去执行2区域。这和Next Program address 的参数一致,因为PWM0还没有初始化完成。
Pin Select = (2U << 7U) ,结合最初的HAL Co Gen,这边设置我们选择的PWM0输出引脚Pin2。
Action = (3U << 3U),结合最初的HAL Co Gen,代表是高脉冲。
Int ena = 0,中断不使能。
Data = 0。

DJZ命令

DJZ命令

/* DJZ: PWM 0 -> Period
*         - Instruction                  = 2
*         - Next instruction             = 3
*         - Conditional next instruction = 41
*         - Interrupt                    = 2
*         - Pin                          = na
*/
{
    /* Program */
    0x00003A40U,
    /* Control */
    0x00029006U,
    /* Data */
    0x00000000U,
	/* Reserved */
	0x00000000U
},

BRK = 0,关闭调试时软件断点。
Next Program address = 3,接下来执行3区域(hetPROGRAM[3])所在的指令。
Opcode = A,查表12-36得知A代表指令码分别为DJZ、ECNT、PWCNT、SCNT。
Sub-Opcode = 2,和Opcode一起分析就能明白代表指令是DJZ。
Control = 0,确定在读取即时数据字段[24:0]时是否清除该字段。
Conditional address = 41,在有选择的情况下去执行41区域。
Register = 2,T类型寄存器(详:470应用手册表12-40)
Int ena = 0,中断不使能。
Data = 0。

后面就是相同的结构从PWM0-PWM7都进行了一遍。在里面可以看到,PWM1的PWCNT被初始化引脚为3,高脉冲。但是各位肯定会发现一个问题,就是我们明明将PWM1使能了,为什么在PWM1的PWCNT中还是0,这是因为PWM的输出配置不是通过这里控制的,而是通过后面还有一段MOV64进行控制。

MOV64命令

mov64命令很重要,输出控制、占空比、周期都在这里调整。
MOV64

/* MOV64: PWM 0 -> Duty Cycle Update
*         - Instruction                  = 41
*         - Next instruction             = 42
*         - Conditional next instruction = 2
*         - Interrupt                    = 1
*         - Pin                          = 2
*/
{
    /* Program */
    0x0002A101U,
    /* Control */
    (0x00002006U | (0x00000000U) | (0U << 20U) | (2U << 7U) | (3U << 3U)),
    /* Data */
    40032U,
	/* Reserved */
	0x00000000U
},

这是PWM0的第一条MOV64命令
BRK = 0,关闭调试时软件断点。
Next Program address = 42,接下来执行42区域(hetPROGRAM[42])所在的指令。
Opcode = 1,查表12-36得知MOV命令。
Remote Address = 1,远程地址。
Control = 0,确定在读取即时数据字段[24:0]时是否清除该字段。
En.Pin Action = (0U << 20U),说明在PWM默认不开启输出。
Conditional address = 2,在有选择的情况下去执行2区域。
Pin Select = (2U << 7U) ,结合最初的HAL Co Gen,这边设置我们选择的PWM0输出引脚Pin2。
Action = (3U << 3U),结合最初的HAL Co Gen,代表是高脉冲。
Register = 2,T类型寄存器(详:470应用手册表12-40)
Int ena = 0,中断不使能。
Data = 0x2001 = 8193。这个是占空比

/* MOV64: PWM 0 -> Period Update
*         - Instruction                  = 42
*         - Next instruction             = 3
*         - Conditional next instruction = 41
*         - Interrupt                    = 2
*         - Pin                          = na
*/
{
    /* Program */
    0x00003102U,
    /* Control */
    (0x00029006U | 0x00000000U),
    /* Data */
    79968U,
	/* Reserved */
	0x00000000U
},

这是PWM0的第二条MOV64命令
BRK = 0,关闭调试时软件断点。
Next Program address = 3,接下来执行3区域(hetPROGRAM[3])所在的指令。
Opcode = 1,查表12-36得知MOV命令。
Remote Address = 2,远程地址。
Control = 0,确定在读取即时数据字段[24:0]时是否清除该字段。
En.Pin Action = (0U << 20U),说明在PWM默认不开启输出。
Conditional address = 41,在有选择的情况下去执行41区域。
Pin Select = 0。
Action = 0。
Int ena = 0,中断不使能。
Register = 2,T类型寄存器(详:470应用手册表12-40)
Data = 0x3CCB = 15563。这个是周期

HET 命令运行逻辑

HET的运行流程就是一个循环,类似于while,命令的接续结构为链表结构。
学过双向链表结构的都知道,链表有两个指针分别代表前一个数据和后一个数据。后指针就是Next Program address,前指针就是Remote Address。只不过HET还多了一个Conditional address,有点类似goto命令,就是在PWM周期运行完成后跳转到MOV64命令去重新加载占空比和周期的计数值。
运行流程
有了这个图后整个逻辑就清晰了,HET会从hetPROGRAM的第一条指令运行,而默认第一条就是CNT命令,CNT命令完成后就是PWCNT和DJZ等命令。在正常的运行时是不会运行到MOV64的命令的,因为在40号的PCNT: Capture Period 7后就会跳转到57号的WCAP,57号WCAP以后又回到0步CNT。
只有在PWM计数结束后才会跳转到MOV64进行重新赋值和输出配置。

好了,以上就是HET的配置信息解读与基本运行逻辑。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值