详解DSP F28069的CLA模块,及代码讲解(适用于2803x、2805x、2806x 型号)

CLA特性:

• 时钟速率与主 CPU 一致 (SYSCLKOUT)。
• 一个独立的架构使得 CLA 能够独立于主 C28x CPU 之外进行算法执行。
– 完整的总线架构:
• 程序地址总线和程序数据总线
• 数据地址总线、 数据读取总线、 和数据写入总线
– 独立的 8 级管道。
– 12 位程序计数器 (MPC)
– 4 个 32 位结果寄存器 (MR0-MR3)
– 2 个 16 位辅助寄存器 (MAR0, MAR1)
– 状态寄存器 (MSTF)
• 指令集包括:
– IEEE 单精度(32 位) 浮点数学运算
– 带有并行载入或者存储的浮点数学
– 带有并行加法或者减法的浮点乘
– 1/X 和 1/sqrt(X) 估值
– 数据类型转换。
– 条件分支指令和调用
– 数据载入/存储操作
• CLA 程序代码能够包含多达 8 个任务或者中断处理例程。
– 每一个任务的开始地址由 MVECT 寄存器指定。
– 只要任务符合 CLA 内的程序内存空间, 对任务大小就没有限制。
– 每次处理并完成一个任务。 无任务嵌套。
– 任务完成时, 在 PIE 内标志一个任务专用中断。
– 当一个任务结束时, 下一个具有最高优先级的等待任务自动开始。
• 任务触发机制:
– 借助于 IACK 指令的 C28x CPU
– 任务 1 至 任务 7: 相应的 ADC 或 ePWM 模块中断。 例如:
Task1:ADCINT1 或EPWM1_INT;
Task2:ADCINT2 或EPWM2_INT;
Task3:ADCINT3 或EPWM3_INT;
Task4:ADCINT4 或EPWM4_INT;
Task5:ADCINT5 或EPWM5_INT;
Task6:ADCINT6 或EPWM6_INT;
Task7:ADCINT7 或EPWM7_INT;
Task8:ADCINT8 或CPU Timer0;
• 内存和共用外设:
– 两个专用消息 RAM 用于 CLA 和主 CPU 间的通信。
– C28x CPU 能够将 CLA 程序和数据内存映射到主 CPU 空间或者 CLA 空间。
– CLA 可直接访问 ADC 结果寄存器、 比较器寄存器、 和 ePWM+HRPWM 寄存器。

CLA 内存:

CLA 可以访问三种类型的内存:程序RAM、数据RAM 和消息RAM。CLA RAM 由CSM 模块保
护。需要给CLA 配置一下三个类型的内存区。

  1. CLA Program Memory
    CLA 程序可以加载到指定的内存块中。重置时,所有内存块都映射到CPU 上。当映射到CPU 空间时,CPU 可以将CLA 程序代码复制到内存中。在调试期间,内存也可以直接由Code Composer Studio™加载。一旦内存被CLA 代码初始化,CPU 通过设置MMEMCFG[PROGE]位将其映射到CLA 程序空间。当一个内存块被配置为CLA 程序内存时,调试访问只允许在CLA 没有获取新
    指令的周期上进行。所有CLA 程序获取都是作为32 位读取操作执行的,并且所有操作码必须对齐到偶数地址。因为所有CLA 操作码都是32 位的,所以这种对齐是自然发生的。
  2. CLA Data Memory
    指定的内存位置可以作为CLA 的数据内存块。在重置时,所有块都映射到CPU 内存空间。
    一旦内存被CLA 数据初始化,CPU 通过设置相应的MMEMCFG[RAMxE]位将其映射到CLA 数据空间。
    当内存块被配置为CLA 数据内存时,CLA 读写访问与CPU 访问一起被仲裁。用户可以选择通过写入适当的
    MMEMCFG[RAMnCPUE]位来开启CPU 读取或写入内存保护。
  3. CLA Shared Message RAMs
    CLA to CPU 消息RAM:
    CLA 可以使用这个块向CPU 传递数据。这个块对CLA 来说既可读又可写。这个块也可以被CPU 读,但是被CPU 写的操作会被忽略。
    CPU 到CLA 消息RAM:
    CPU 可以使用这个块向CLA 传递数据和消息。这个消息RAM 对CPU 来说既可读又可写。CLA 可以执行读操作,但其写操作将被忽略。

EALLOW Protection

CPU 状态寄存器1 (ST1)中的EALLOW 位表示CPU 的保护状态。同样的MSTF (CLA status register)中的MEALLOW 位表示CLA
的写保护状态。MEALLOW CLA 指令允许CLA 对EALLOW 保护寄存器进行写访问。同样的MEDIS CLA 指令将禁用写访问。通过
这种方式,CLA 可以独立于CPU 启用/禁用写访问。

CLA Tasks and Interrupt Vectors

CLA 程序代码被划分为任务或中断服务例程。任务没有固定的起始位置或长度。CLA 程序内存可以根据需要进行划分。CLA 使
用中断向量的内容(MVECT1 到MVECT8)来确定任务从哪里开始;任务由MSTOP 指令终止。CLA 支持8 个任务。任务1 优先级最
高,任务8 优先级最低,任务可以由外设中断或软件请求。
外设中断触发:
例如,Task 1 (MVECT1)可以通过写MPISRCSEL1 [PERINT1SEL]=2 来设置由触发EPWM1_INT 。要禁用由
外设触发的任务,用户必须配置MPISRCSEL1[PERINTxSEL]位字段为“无中断源”选择
软件触发:
CPU 软件可以通过写入MIFRC 寄存器或IACK 指令来触发任务。IACK 指令更有效,因为它不需要您发
出EALLOW 来设置MIFR 位。
设置MCTL[IACKE]位使能IACK 特性。IACK 指令操作数中的每一位都对应一个任务。
例如IACK #0x0001 将在MIFR 寄存器中设置第0 位来启动任务1。同样,IACK #0x0003 将在MIFR 寄存
器中设置第0 位和第1 位来启动任务1 和任务2。

CLA 有自己的获取机制,可以独立于CPU 运行和执行任务。一次只服务一个任务;没有任务嵌套。
如果CLA 是空闲的(当前没有任务正在运行),那么同时被标记(MIFR)和启用(MIER)的最高优
先级中断请求将启动。流程如下:

  1. 相关的RUN 寄存器位(MIRUN)被设置,标志位(MIFR)被清除
  2. CLA 在相关中断向量(MVECTx)指示的位置开始执行。MVECT 在低64K 内存空间中包含
    任务的绝对16 位地址。
  3. CLA 执行指令,直到找到MSTOP 指令为止。这表示任务的结束。
  4. MIRUN 位被清除。
  5. CLA 回到空闲状态。

一旦一个任务完成,下一个优先级最高的挂起任务将自动得到服务,并重复此序列。

CLA 通常独立于CPU 运行。在CLA 和CPU 正在尝试当前访问内存或外围寄存器,仲裁过程将发生。唯一的例外是ADC 结果寄存器,当CPU 和CLA 两者读取时不会产生冲突
CPU 和CLA 同时运行。
可能发生访问冲突的接口包括:
• CLA Message RAMs
• CLA Program Memory
• CLA Data RAMs

• CLA to CPU Message RAM:

允许以下访问:
– CPU reads
– CLA reads and writes
– CPU debug reads and writes
忽略以下操作:
– CPU writes
访问优先级为(最高优先级优先):

  1. CLA write
  2. CPU debug write
  3. CPU data read, program read, CPU debug read
  4. CLA data read

• CPU to CLA Message RAM:
允许以下访问:
– CPU reads and writes
– CLA reads
– CPU debug reads and writes
忽略以下操作:
– CLA writes
访问优先级为(最高优先级优先):
5. CLA read
6. CPU data write, program write, CPU debug write
7. CPU data read, CPU debug read
8. CPU program read

CLA Program Memory:

程序内存的行为取决于MMEMCFG[PROGE]位的状态。这个位控制内存是映射到CLA 空间
还是CPU 空间。
• MMEMCFG[PROGE] == 0
在这种情况下,内存被映射到CPU。CLA 将停止,没有任务允许进来。

  • 任何CLA 获取都将被视为非法操作码条件,如第10.5.4 节所述。如果遵循正确的
    过程来映射程序内存,则不会出现这种情况。
  • 不能进行CLA 读写
  • 内存块表现为映射到CPU 内存空间,跟任何普通RAM 块一样。
    访问优先级为(最高优先级优先):
  1. CPU data write, program write, debug write
  2. CPU data read, program read, debug read
  3. CPU fetch, program read

• MMEMCFG[PROGE] == 1
在这种情况下,内存块被映射到CLA 空间。CPU 只能进行调试访问。
—不能进行CLA 读写
-允许CLA 读取

  • CPU 获取返回0,这是一个非法的操作码,将导致ITRAP 中断。
    —CPU 数据读取和程序读取返回0
    —CPU 数据写入和程序写入均被忽略
    访问优先级为(最高优先级优先):
  1. CLA fetch
  2. CPU debug write
  3. CPU debug read
    (注意:因为CLA 读取比CPU 调试读取具有更高的优先级,所以如果CLA 在循环中执行,CLA
    可能会永久地阻塞调试访问。这可能发生在最初开发CLA 代码时,由于一个错误。为了避免这
    个问题,当CLA 运行时,程序内存将返回所有0x0000 用于CPU 调试读(忽略写)。当CLA 暂停
    或空闲时,可以执行正常的CPU 调试读写访问。)

CLA Data Memory:

有三个独立的数据存储块。数据内存的行为取决于MMEMCFG[RAM0E]、MMEMCFG[RAM1E]和
MMEMCFG[RAM2E]位的状态。这些位决定内存块是映射到CLA 空间还是CPU 空间。
• MMEMCFG[RAMxE] == 0, MMEMCFG[RAMxCPUE] = 0/1
在这种情况下,内存块被映射到CPU。
– CLA fetches cannot occur to this block.
– CLA reads return 0.
– CLA writes are ignored.
– The memory block behaves as any normal RAM block mapped to the CPU memory space.

• MMEMCFG[RAMxE] == 1, MMEMCFG[RAMxCPUE] = 0
在这种情况下,内存块被映射到CLA 空间。CPU 只能进行调试访问。
– CLA fetches cannot occur to this block.(CLA取指令不能发生在这空间。)
– CLA read and CLA writes are allowed.
– CPU fetches return 0
– CPU data reads and program reads return 0.
– CPU data writes and program writes are ignored.
访问优先级为(最高优先级优先):

  1. CLA data write
  2. CPU debug write
  3. CPU debug read
  4. CLA read

• MMEMCFG[RAMxE] == 1, MMEMCFG[RAMxCPUE] = 1
在这种情况下,内存块被映射到CLA 空间。除了调试访问外,CPU 还有对内存的读和写访
问。
– CLA fetches cannot occur to this block.
– CLA read and CLA writes are allowed.
– CPU fetches return 0
– CPU data reads and writes are allowed.
– CPU program reads return 0 while program writes are ignored.
访问优先级为(最高优先级优先):
5. CLA data write
6. CPU debug access write/CPU data write
7. CPU debug access read/ CPU data read
8. CLA read

Peripheral Registers (ePWM, HRPWM, Comparator, eCAP, eQEP)

对寄存器的访问遵循以下规则:
-如果CPU 和CLA 同时请求访问,那么CLA 将具有优先级,而主CPU 将被暂停。
-如果一个CPU 访问正在进行,而另一个CPU 访问正在挂起,那么CLA 将优先于挂起的CPU 访
问。在这种情况下,CLA 访问将在当前CPU 访问完成时开始。
-当CPU 访问正在进行时,任何传入的CLA 访问将被停止
-当CLA 访问正在进行时,任何传入的CPU 访问将被停止。

  • CPU 写操作优先于CPU 读操作。
    • CLA 写操作优先于CLA 读操作。
      -如果CPU 正在执行read-modify-write 操作,而CLA 对同一位置进行写操作,则如果该
      操作发生在CPU 读写之间,CLA 写操作可能丢失。出于这个原因,您不应该将CPU 和CLA
      访问混合到同一个位置。

Building a CLA Application

控制律加速器既可以用CLA 汇编代码(使用第10.7 节中描述的指令)编程,也可以用精简的C
语言子集编程。CLA 程序集代码与C28x 代码位于同一个项目中。唯一的限制是CLA 代码必
须在它自己的程序集部分中。使用.sect 汇编指令可以很容易地做到这一点。这并不会阻止
CLA 和C28x 代码被链接到链接器命令文件中的相同内存区域。
系统和CLA 初始化由主CPU 执行。这通常是在C 或c++中完成的,但也可以包括C28x 汇编
代码。主CPU 还将CLA 代码复制到程序内存中,如果需要,初始化CLA 数据RAM。一旦系
统初始化完成,应用程序开始运行,CLA 将使用CLA 程序集代码(或任务)为其中断提供服务。
主CPU 可以在执行CLA 程序的同时执行其他任务。
The CLA Type 0 requires Codegen V5.2.0 or later with the compiler switch: --cla_support=cla0.

典型的CLA 初始化序列
典型的CLA 初始化顺序由主CPU 执行。

  1. Copy CLA code into the CLA program RAM(复制CLA 代码到CLA 程序RAM 中)
    CLA 源代码最初可以驻留在闪存或来自通信外设或主CPU 可以访问它的任何地方的数据流中。调试器
    还可以用于在开发期间将代码直接加载到CLA 程序RAM 中。
  2. Initialize CLA data RAM, if necessary(如有必要,初始化CLA 数据RAM)
    用任何必需的数据系数或常数填充CLA 数据RAM。
  3. Configure the CLA registers
    配置CLA 寄存器,但是保持中断禁用直到最后(leave MIER = 0):
    • Enable the CLA peripheral clock using the assigned PCLKCRn register
    • Populate the CLA task interrupt vectors
    初始化时,每个向量都需要使用要执行的任务的起始地址进行初始化CLA 接收相关的中断。该
    地址是与分配的CLA 程序内存块的基址的偏移量。
    • Select the task interrupt sources
    对于每个任务,在CLA1TASKSRCSELx 寄存器中选择中断源。如果任务是软件触发的,请
    选择“不中断”。
    • Enable IACK to start a task from software, if desired(如果需要,启用IACK 从软件启动任务)
    要启用IACK 指令启动任务,请设置MCTL[IACKE]位。使用IACK 指令可以避免设置和清除EALLOW 位。
    • Map CLA data RAM to CLA space, if necessary(如果需要,将CLA 数据RAM 映射到CLA 空
    间)
    通过向MMEMCFG[RAMxE]位写入1,将数据RAM 映射到CLA 空间。一旦设置了MMEMCFG[RAMxE]位,CPU 将限制对内存块的访问。CPU 访问CLA 数据RAM 可以通过MMEMCFG[RAMxCPUE]位授予。使能后经过
    两个SYSCLK 周期MMEMCFG 更新生效。
    • Map CLA program RAM to CLA space(将CLA 程序RAM 映射到CLA 空间)
    通过设置MMEMCFG[PROGE] 位将CLA 程序RAM 映射到CLA 空间。一旦设置了
    MMEMCFG[PROGE]位,CPU 将只有调试访问CLA 程序RAM。使能后经过两个SYSCLK 周期MMEMCFG
    更新生效。
  4. Initialize the PIE vector table and registers(初始化PIE 向量表和寄存器)
    当一个CLA 任务完成时,PIE 中相关的中断将被标记。CLA 溢出和下溢标志在PIE 中也有相关的中断。
  5. Enable CLA tasks/interrupts
    在中断启用寄存器(MIER)中设置适当的位以允许CLA 为中断提供服务。
  6. Initialize other peripherals(初始化其他外设)
    初始化将为启用的CLA 任务生成中断触发器的任何外设(例如ePWM、ADC 和其他)。

CLA 现在已准备好为中断提供服务,消息ram 可用于在CPU 和CLA 之间传递数据。CLA 程序
和数据ram 的映射通常只在初始化过程中发生。如果在初始化后需要更改RAM 映射,则必
须禁用CLA中断,并且在修改RAM所有权之前必须完成所有任务(通过检查MIRUN寄存器)。

Resetting the CLA

• Hard Reset
将1 写入MCTL[HARDRESET]位将执行CLA 的硬复位。硬复位的行为与系统复位(通过XRS
或调试器)相同。在这种情况下,所有CLA 配置和执行寄存器将被设置为默认状态,CLA 执行将停止。
• Soft Reset
写入1 到MCTL[SOFTRESET]位执行CLA 的软复位。如果一个任务正在执行,它将停止,相
关的MIRUN 比特位将被清除。中断启用(MIER)寄存器内的所有比特位也将被清除,这样就不会有新进程
启动。

CLA 流水线与C28x 流水线非常相似,有八个阶段:

  1. Fetch 1 (F1)
    在F1 阶段,程序读地址被放置在CLA 程序地址总线上。
  2. Fetch 2 (F2)
    在F2 阶段,使用CLA 程序数据总线读取指令。
  3. Decode 1 (D1)(指令译码1)
    在D1 期间,指令被解码。
  4. Decode 2 (D2)
    生成数据读地址。由于使用间接寻址的后增量,MAR0 和MAR1 的变化发生在D2
    阶段。在此阶段还根据MSTF 寄存器标志做出条件分支决策。
  5. Read 1 (R1)
    将数据读地址放在CLA 数据读地址总线上。如果存在内存冲突,R1 阶段将被停止。
  6. Read 2 (R2)
    使用CLA 数据到读取数据的总线上读取数据值。
  7. Execute (EXE)(执行)
    执行该操作。由于加载即时值或从内存中加载值而对MAR0 和MAR1 的更改发生
    在这个阶段。
  8. Write (W)
    将写地址和写数据放在CLA 写数据总线上。如果存在内存冲突,则W 阶段将被暂
    停。

CLA 流水线对齐

大多数CLA 指令不需要任何特殊的流水线考虑。本节列出了少数需要特别考虑的操作。
• Write Followed by Read(写然后读)
在C28x 和CLA 流水线中,读操作都发生在写操作之前。这意味着如果一个读操作紧跟在
一个写操作之后,那么读操作将首先完成,如表10-1 所示。在大多数情况下,这不会导致问题,
因为一个内存位置的内容不依赖于另一个内存位置的状态。对于外设的访问,对一个位置的写
操作可能会影响到另一个位置的值,代码必须等待写操作完成后才能发出读操作,如表10 - 2。

对于28x CPU,这种行为是不同的。对于28x CPU,对同一位置的任何先写后读保护都被称为
先写后读保护。这种保护会自动暂停管道,以便在读操作之前完成写操作。此外,一些外围帧
被保护,这样一个28 倍CPU 写入帧内的一个位置将总是在读取帧之前完成。CLA 没有这种保
护机制。相反,代码必须等待执行读取。
并行指令是并行执行两个操作的单个操作码。以下类型的并行指令是可用的:与移动操作并行的
数学运算,或两个数学运算并行。这两种操作在一个周期内完成,并且没有特殊的流水线对齐
要求。

CLA的介绍就到这里,下面我们来对TMS320F28069进行实际的配置。

CLA读取ADC值并且控制ePWM波形的实验

实验内容

  • ADC采样主要通过ePWM来触发采样转换,ADC转换成功后通过ADCINT1来触发CLA的Task1处理数据; ADC配置详解地址
    adc.h
/** ADC.h**  Created on: 2023年2月24日*      Author: chends*/#ifndef ADC_H_
#define ADC_H_#include "DSP28x_Project.h"#define Interrupt_Allow 2    //0-ADC轮询模式;1-ADC中断模式;2-CLA处理模式void delayUs(Uint16 n);
void ADC_Init(void);
Uint32 GetChResult(Uint16 CH_sel,Uint8 ACQPS_Value,Uint8 Trig_Sel);
void InitAdcConfigAndIO(void);#if Interrupt_Allow ==1
void OpenAdcInterrupt_PIE(void);
__interrupt void ADCINT1Isr_dasen(void);
#endif#endif /* ADC_H_ */

ADC.c

/** ADC.c**  Created on: 2023年2月24日*      Author: chends*      参考F2806x_Adc.c*/#include "ADC.h"
#include "usart.h"
#include <stdio.h>/** 粗略的延时函数,大于或等于1ms*/
void delayUs(Uint16 n)
{Uint16 i;Uint32 j;for(i=0;i<n;i++)for (j = 0; j < 90; j++);    //>= 1us
}/** ADC模块初始化*/
void ADC_Init(void)
{EALLOW;SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;//使能ADC时钟(*Device_cal)();//调用在boot ROM中的校准ADC和内部振荡器的EDIS;EALLOW;AdcRegs.ADCCTL1.bit.ADCPWDN=1;//1-给核心内部的模拟电路通电AdcRegs.ADCCTL1.bit.ADCBGPWD=1;//1-给带隙缓冲器核心内的电路通电AdcRegs.ADCCTL1.bit.ADCREFPWD=1;//1-给核心内部的参考缓冲电路通电AdcRegs.ADCCTL1.bit.ADCENABLE=1;//1-启用ADC。必须在ADC转换前设置(建议在设置ADC上电位后直接设置)AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;  //选择内部的参考电源EDIS;delayUs(1000);//在转换前需要经过1ms延时//设置ADC时钟 = SYSCLK/2             //  CLKDIV2EN |  CLKDIV4EN | ADCCLKEALLOW;                             //------------------------------------AdcRegs.ADCCTL2.bit.CLKDIV2EN=1;    //      0     |     0     |  SYSCLKAdcRegs.ADCCTL2.bit.CLKDIV4EN=0;    //      0     |     1     |  SYSCLKEDIS;                               //      1     |     0     |  SYSCLK/2//      1     |     1     |  SYSCLK/4delayUs(1000);//Delay before converting ADC channels
}/** ADC 通道初始化 以及 IO初始化*/
void InitAdcConfigAndIO(void)
{EALLOW;/* Configure ADC pins using AIO regs*///AIOx Pin总是连通着ADC Channel x和/Comparator input x,不需要额外设置//但是有些AIOx需要关闭它的IO输入输出路径,以防止影响采集GpioCtrlRegs.AIOMUX1.bit.AIO2 =2;//bit5:4, 00/01时,AIO2 enabled;10/11时,AIO2 disabled (default)GpioCtrlRegs.AIOMUX1.bit.AIO4 =2;GpioCtrlRegs.AIOMUX1.bit.AIO6 =2;GpioCtrlRegs.AIOMUX1.bit.AIO10 =2;GpioCtrlRegs.AIOMUX1.bit.AIO12 =2;GpioCtrlRegs.AIOMUX1.bit.AIO14 =2;AdcRegs.ADCCTL2.bit.ADCNONOVERLAP=0;//1-Overlap of sample is not allowed//0-Overlap of sample and conversion is allowedAdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;//0-当ADC开始转换时产生INT脉冲//1-INT脉冲生成发生在ADC结果锁存到其结果寄存器之前的1个周期AdcRegs.ADCINTFLGCLR.all=0x1ff; //清除ADCINT1-9的中断标志AdcRegs.ADCINTOVFCLR.all=0X1FF; //清除1-9的中断溢出标志,连续模式下可以忽略,因为连续模式溢出时会重头开始启动转换。//(如果设置了相应的ADCINTFLG位,并且生成了选择的额外EOC触发器,则会发生溢出条件。)AdcRegs.INTSEL1N2.all=0;    //禁用ADCINT1、2AdcRegs.INTSEL1N2.bit.INT1CONT=0;//0-在ADCINTy标志(在ADCINTFLG寄存器中)被用户清除之前,不会产生更多的ADCINTy脉冲。AdcRegs.INTSEL1N2.bit.INT2CONT=0;//1-无论是否清除标志位,只要产生EOC脉冲,就会产生ADCINTy脉冲。(连续模式)AdcRegs.INTSEL1N2.bit.INT1E=1;//启用ADCINT1AdcRegs.INTSEL1N2.bit.INT2E=0;//禁用ADCINT2AdcRegs.INTSEL1N2.bit.INT1SEL=0x0f;//EOC15触发ADCINT1AdcRegs.INTSEL1N2.bit.INT2SEL=0;//EOC0触发ADCINT2AdcRegs.INTSEL3N4.all=0;    //禁用ADCINT3、4AdcRegs.INTSEL5N6.all=0;    //禁用ADCINT5、6AdcRegs.INTSEL7N8.all=0;    //禁用ADCINT7、8AdcRegs.INTSEL9N10.all=0;   //禁用ADCINT9AdcRegs.SOCPRICTL.all=0;  //关于优先级等配置AdcRegs.ADCSAMPLEMODE.all=0;  //全部设置为顺序采样模式AdcRegs.ADCINTSOCSEL1.all=0;    //无ADCINT触发SOCAdcRegs.ADCINTSOCSEL2.all=0;EDIS;
}
Uint32 GetChResult(Uint16 CH_sel,Uint8 ACQPS_Value,Uint8 Trig_Sel)
{Uint32 mean=0;EALLOW;AdcRegs.ADCSOC0CTL.bit.TRIGSEL=Trig_Sel;//0-只允许软件触发AdcRegs.ADCSOC1CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC2CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC3CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC4CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC5CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC6CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC7CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC8CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC9CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC10CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC11CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC12CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC13CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC14CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC15CTL.bit.TRIGSEL=Trig_Sel;AdcRegs.ADCSOC0CTL.bit.ACQPS  = ACQPS_Value;//设置采样窗口值AdcRegs.ADCSOC1CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC2CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC3CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC4CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC5CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC6CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC7CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC8CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC9CTL.bit.ACQPS  = ACQPS_Value;AdcRegs.ADCSOC10CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC11CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC12CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC13CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC14CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC15CTL.bit.ACQPS = ACQPS_Value;AdcRegs.ADCSOC0CTL.bit.CHSEL=CH_sel;//通道选择AdcRegs.ADCSOC1CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC2CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC3CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC4CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC5CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC6CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC7CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC8CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC9CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC10CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC11CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC12CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC13CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC14CTL.bit.CHSEL=CH_sel;AdcRegs.ADCSOC15CTL.bit.CHSEL=CH_sel;EDIS;delayUs(10);if(Trig_Sel==0)AdcRegs.ADCSOCFRC1.all=0xffff;  //软件触发SOC1-S0C15转换#if Interrupt_Allow==0//Wait for ADCINT1 to trigger, then add ADCRESULT0-15 registers to sumwhile (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0);AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//Must clear ADCINT1 flag since INT1CONT = 0//AdcRegs.ADCINTOVFCLR.bit.ADCINT1=1;mean +=AdcResult.ADCRESULT0;mean +=AdcResult.ADCRESULT1;mean +=AdcResult.ADCRESULT2;mean +=AdcResult.ADCRESULT3;mean +=AdcResult.ADCRESULT4;mean +=AdcResult.ADCRESULT5;mean +=AdcResult.ADCRESULT6;mean +=AdcResult.ADCRESULT7;mean +=AdcResult.ADCRESULT8;mean +=AdcResult.ADCRESULT9;mean +=AdcResult.ADCRESULT10;mean +=AdcResult.ADCRESULT11;mean +=AdcResult.ADCRESULT12;mean +=AdcResult.ADCRESULT13;mean +=AdcResult.ADCRESULT14;mean +=AdcResult.ADCRESULT15;mean >>=4;
#endifreturn mean;
}#if Interrupt_Allow == 1
void OpenAdcInterrupt_PIE(void)
{EALLOW;PieVectTable.ADCINT1 = &ADCINT1Isr_dasen;   //自定义中断函数EDIS;//开启CPU 第10组中断并使能第10组中断的第1 个小中断,即ADCINT1IER |=M_INT1;PieCtrlRegs.PIEIER1.bit.INTx1=1;PieCtrlRegs.PIEACK.bit.ACK1=1;//写1去清除ACK位//使能总中断EINT;ERTM;
}char NUMCHAR_[16];
__interrupt void ADCINT1Isr_dasen(void)
{Uint32 mean=0;float32 val;if(AdcRegs.ADCINTFLG.bit.ADCINT1){AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//Must clear ADCINT1 flag since INT1CONT = 0mean +=AdcResult.ADCRESULT0;mean +=AdcResult.ADCRESULT1;mean +=AdcResult.ADCRESULT2;mean +=AdcResult.ADCRESULT3;mean +=AdcResult.ADCRESULT4;mean +=AdcResult.ADCRESULT5;mean +=AdcResult.ADCRESULT6;mean +=AdcResult.ADCRESULT7;mean +=AdcResult.ADCRESULT8;mean +=AdcResult.ADCRESULT9;mean +=AdcResult.ADCRESULT10;mean +=AdcResult.ADCRESULT11;mean +=AdcResult.ADCRESULT12;mean +=AdcResult.ADCRESULT13;mean +=AdcResult.ADCRESULT14;mean +=AdcResult.ADCRESULT15;mean >>=4;val=(float32)mean/4096;val *=3.3;sprintf(NUMCHAR_,"ADC INT_val:%f V\r\n", val);UARTa_SendString(NUMCHAR_);}PieCtrlRegs.PIEACK.bit.ACK1=1;//写1去清除ACK位
}
#endif
//在main.c文件中引用以下代码配置ADC//adcADC_Init();InitAdcConfigAndIO();
#if Interrupt_Allow == 1OpenAdcInterrupt_PIE();
#endif
GetChResult(1,9,5);//5-epwm1a SOCa 触发
  • ePWM使用ePWM1和ePWM2来产生相移全桥(ZVSFB)的PWM波形; ePWM配置详解地址
    ePWM.h
/** ePWM.h**  Created on: 2023年2月28日*      Author: chends*/#ifndef EPWM_H_
#define EPWM_H_#include "DSP28x_Project.h"void ePWM_init(void);
void ZVSFB_ePWM1Config(void);
void ZVSFB_ePWM2Config(void);#endif /* EPWM_H_ */

ePWM.c

/** ePWM.c**  Created on: 2023年2月28日*      Author: chends*/#include "ePWM.h"/** 初始化化ePWM模块*  使能时钟,时基时钟同步,配置GPIO脚等*/
void ePWM_init(void)
{EALLOW;//gpio口配置:禁用所选输出引脚的内部上拉降低功耗;设置为ePWM输出引脚GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;    // Disable pull-up on GPIO0 (EPWM1A)GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;    // Disable pull-up on GPIO1 (EPWM1B)GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;    // Disable pull-up on GPIO2 (EPWM2A)GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1;    // Disable pull-up on GPIO3 (EPWM2B)GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO0 as EPWM1AGpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO1 as EPWM1BGpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;   // Configure GPIO2 as EPWM2AGpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1;   // Configure GPIO3 as EPWM2BSysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK=1;   //使能ePWM1的时钟SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK=1;   //使能ePWM2的时钟SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=0;    //停止ePWM模块的TB时钟;ZVSFB_ePWM1Config();//配置预定标的值和ePWM1模块;ZVSFB_ePWM2Config();//配置预定标的值和ePWM2模块;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=1;    //打开ePWM模块的TB时钟;EDIS;}/** 配置预定标的值和ePWM模块*/
void ZVSFB_ePWM1Config(void)
{/************************<<EPWM1配置 start>>***************************//***********************时基模块配置*********************************///TBCLK = SYSCLKOUT / (HSPCLKDIV × CLKDIV)=90MHz/(128 * 14)=50.233KHzEPwm1Regs.TBCTL.bit.CLKDIV=7;       //分频值128EPwm1Regs.TBCTL.bit.HSPCLKDIV=7;    //分频值14EPwm1Regs.TBPRD=5000;             //周期值  输出频率为f=TBCLK/TBPRD=50.233KHz/5000=10HzEPwm1Regs.TBCTL.bit.PHSDIR=1;       //相位方向位。0-在同步事件之后向下计数;1-在同步事件之后向上计数//EPwm1Regs.TBCTL.bit.SWFSYNC=1;    //软件强制同步脉冲,置1时,生成一次同步脉冲//同步输出选择。这些位选择EPWMxSYNCO信号的源。//0- EPWMxSYNC; 1- CTR=0,时间基准计数器等于零;2- CTR=CMPB;3- 关闭EPWMxSYNCO信号。EPwm1Regs.TBCTL.bit.SYNCOSEL=1;     //CTR=0时产生输出同步信号EPwm1Regs.TBCTL.bit.PRDLD=0;        //0-使用影子寄存器模式;1-立即加载TBPRD寄存器,而不使用影子寄存器。EPwm1Regs.TBCTL.bit.PHSEN=0;        //0-不使用同步信号//计数器模式位//0-向上计数模式;1-向下计数模式;2-向上向下计数模式;3-停止-冻结计数器操作(默认为复位)EPwm1Regs.TBCTL.bit.CTRMODE=0;EPwm1Regs.TBPHS.half.TBPHS=0;       //设置相位寄存器为0EPwm1Regs.TBCTR=0;                  //清除计数值/****************************计数器比较模块(CC)配置*****************************/EPwm1Regs.CMPCTL.bit.SHDWAMODE=0;   //0-影子模式;1-立即加载模式EPwm1Regs.CMPCTL.bit.SHDWBMODE=0;   //0-影子模式;1-立即加载模式//从影子寄存器加载到活动寄存器模式选择//0- CTR=0时加载;1- CTR=PRD时加载;2- CTR=0或PRD时,加载;3- 不加载(冻结)。EPwm1Regs.CMPCTL.bit.LOADAMODE = 0;EPwm1Regs.CMPCTL.bit.LOADBMODE = 0;EPwm1Regs.CMPA.half.CMPA=2500;EPwm1Regs.CMPB =1250;/****************************动作限定模块(AQ)配置***************************///当计数器等于活动的CMPA寄存器并且计数器在递增时进行操作。//0-无动作;1-强制EPWMxA输出低;2-强制EPWMxA输出高;3-翻转EPWMxA输出EPwm1Regs.AQCTLA.bit.CAU=1;//计数器等于零时的动作//0-无动作;1-强制EPWMxA输出低;2-强制EPWMxA输出高;3-翻转EPWMxA输出EPwm1Regs.AQCTLA.bit.ZRO=2;/*************************死区产生模块(DB)配置*****************************/EPwm1Regs.DBCTL.bit.HALFCYCLE=0;//半周期时钟使能位。0-启用全周期时钟;1-启用半周期时钟/*死区输入模式控制(bit5 bit4)*00- EPWMxA In(来自动作限定模块)是下降边缘和上升边缘延迟的来源*01- EPWMxB输入上升沿延时器,EPWMxA输入下降沿延时器*10- EPWMxA输入上升沿延时器,EPWMxB输入下降沿延时器*11- EPWMxB In(来自动作限定模块)是下降边缘和上升边缘延迟的来源*/EPwm1Regs.DBCTL.bit.IN_MODE=0;/* 上升沿延时器输出(EPWMxA)和下降沿输出(EPWMxB)的信号极性选择控制(bit3 bit2)* 00- EPWMxA和EPWMxB都不反向,AH模式* 01- EPWMxA反向,EPWMxB不反向。ALC模式* 10- EPWMxB反向,EPWMxA不反向。AHC模式* 11- EPWMxA和EPWMxB都反向,AL模式*/EPwm1Regs.DBCTL.bit.POLSEL=2;/*死区输出模式控制(bit1 bit0)* 00-两个输出信号都绕过了死带生成器。在这种模式下,动作限定器的EPWMxA和EPWMxB输出信号都直接传递给PWM斩波模块。在这种模式下,POLSEL和IN_MODE位不起作用。* 01-禁用上升边缘延迟器。动作限定器符的EPWMxA信号直接传递给PWM斩波子模块的EPWMxA输入。下降沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxB输入* 10-禁用下降边缘延迟器。动作限定器符的EPWMxB信号直接传递给PWM斩波子模块的EPWMxB输入。上升沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxA输入* 11-上升沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxA输入,下降沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxB输入。*/EPwm1Regs.DBCTL.bit.OUT_MODE=11;//上升沿延迟计数。10位计数器。(全周期模式)RED=DBRED*T(TBCLK);(半周期模式)RED=DBRED*T(TBCLK)/2EPwm1Regs.DBRED=50;//下降边缘延迟计数。10位计数器 (全周期模式)FED=DBFED*T(TBCLK);(半周期模式)FED=DBFED*T(TBCLK)/2EPwm1Regs.DBFED=50;/************************* PWM 斩波(PC)模块配置*****************************/EPwm1Regs.PCCTL.bit.CHPEN=0;//0-禁用PWM斩波模块;1-启用PWM斩波模块/************************* 错误联防(TZ)模块配置*****************************/EPwm1Regs.TZSEL.all=0;  //禁用所有的TZ模块的CBC和OSHT触发源EPwm1Regs.TZDCSEL.all=0;    //禁用所有的数字比较输出事件/*数字比较输出A事件1对EPWMxA的动作:* 0- EPWMxA=高阻抗状态* 1- 强制EPWMxA进入高电平。* 2- 强制EPWMxA进入低电平。* 3- 不动作,禁用*/EPwm1Regs.TZCTL.bit.DCAEVT1=3;EPwm1Regs.TZCTL.bit.DCAEVT2=3;//同上解释EPwm1Regs.TZCTL.bit.DCBEVT1=3;EPwm1Regs.TZCTL.bit.DCBEVT2=3;EPwm1Regs.TZCTL.bit.TZA=3;EPwm1Regs.TZCTL.bit.TZB=3;EPwm1Regs.TZEINT.bit.CBC=0;    //禁用CBC事件中断EPwm1Regs.TZEINT.bit.DCAEVT1=0;//禁用DCAEVT1中断EPwm1Regs.TZEINT.bit.DCAEVT2=0;//禁用DCAEVT2中断EPwm1Regs.TZEINT.bit.DCBEVT1=0;//禁用DCBEVT1中断EPwm1Regs.TZEINT.bit.DCBEVT2=0;//禁用DCBEVT2中断EPwm1Regs.TZEINT.bit.OST=0;//禁用OST中断//清除TZFLG的所有标志位EPwm1Regs.TZCLR.all=0X7F;//1-对TZFRC相应位写入1强制相应事件触发条件并设置TZFLG相应位 。0-不使用。EPwm1Regs.TZFRC.all=0;/************************* 事件触发(ET)模块配置*****************************/EPwm1Regs.ETSEL.bit.SOCBEN=0;//0-禁止产生EPWMxSOCB脉冲去触发ADC转换EPwm1Regs.ETSEL.bit.SOCBSEL=0;//由于SOCB禁用,此处无用EPwm1Regs.ETSEL.bit.SOCAEN=1;//1-允许产生EPWMxSOCA脉冲去触发ADC转换/*EPWMxSOCA脉冲产生的选择选项* 0-允许DCAEVT1.soc事件触发产生* 1-允许TBCTR=0时触发产生* 2-允许TBCTR=TBPRD时触发产生* 3-允许TBCTR=0或TBCTR=TBPRD时触发产生* 4-允许向上计数模式下TBCTR=CMPA时触发产生* 5-允许向下计数模式下TBCTR=CMPA时触发产生* 6-允许向上计数模式下TBCTR=CMPB时触发产生* 7-允许向下计数模式下TBCTR=CMPB时触发产生*/EPwm1Regs.ETSEL.bit.SOCASEL=6;EPwm1Regs.ETSEL.bit.INTEN=0;//0-禁止EPWMx_INT生成EPwm1Regs.ETSEL.bit.INTSEL=0;//由于EPWMx_INT禁用,此处无用EPwm1Regs.ETPS.bit.SOCBPRD=0;//关闭SOCB事件计数器。不会产生EPWMxSOCB脉冲/*ePWM ADC转换触发A事件(EPWMxSOCA)周期选择* 0-禁用SOCA事件计数器。不会产生EPWMxSOCA脉冲* 1-在第一个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =1* 2-在第二个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =2* 3-在第三个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =3*/EPwm1Regs.ETPS.bit.SOCAPRD=3;EPwm1Regs.ETPS.bit.INTPRD=0;//禁用中断事件计数器。不会产生中断,ETFRC[INT]将被忽略。EPwm1Regs.ETCLR.bit.INT=1;//ePWM中断(EPWMx_INT)标志清除位:写1时清除ETFLG[INT]标志位,并允许生成进一步的中断脉冲(由于禁用中断,此处无用)EPwm1Regs.ETCLR.bit.SOCA=1;//ePWM ADC转换触发A(EPWMxSOCA)标志清除位:写1清除ETFLG[SOCA]标志位EPwm1Regs.ETCLR.bit.SOCB=1;//ePWM ADC转换触发B(EPWMxSOCB)标志清除位:写1清除ETFLG[SOCB]标志位(由于禁用SOCB,此处无用)EPwm1Regs.ETFRC.bit.SOCA=0;//EPWMxSOCA软件强制触发位:写1-在EPWMxSOCA上生成脉冲并设置SOCBFLG位。此位用于测试目的。(只有需要启用EPWMxSOCA脉冲时才有用,即ETSEL.SOCAEN=1)EPwm1Regs.ETFRC.bit.SOCB=0;//EPWMxSOCA软件强制触发位:写1-在EPWMxSOCB上生成脉冲并设置SOCBFLG位。此位用于测试目的。(只有需要启用EPWMxSOCB脉冲时才有用,即ETSEL.SOCBEN=1)EPwm1Regs.ETFRC.bit.INT=0;//EPWMxINT软件强制触发位:写1-在EPWMxINT上生成一个中断,并设置INT标志位。此位用于测试目的(只有需要启用EPWMx_INT脉冲时才有用,即ETSEL.INTEN=1)/************************* 数字比较(DC)模块配置*****************************///暂无使用/************************<<EPWM1配置 end>>***************************/}/** 配置预定标的值和ePWM模块*/
void ZVSFB_ePWM2Config(void)
{/************************<<EPWM2配置 start>>***************************//***********************时基模块配置*********************************///TBCLK = SYSCLKOUT / (HSPCLKDIV × CLKDIV)=90MHz/(128 * 14)=50.233KHzEPwm2Regs.TBCTL.bit.CLKDIV=7;       //分频值128EPwm2Regs.TBCTL.bit.HSPCLKDIV=7;    //分频值14EPwm2Regs.TBPRD=5000;             //周期值  输出频率为f=TBCLK/TBPRD=50.233KHz/5000=10HzEPwm2Regs.TBCTL.bit.PHSDIR=1;       //相位方向位。0-在同步事件之后向下计数;1-在同步事件之后向上计数//EPwm1Regs.TBCTL.bit.SWFSYNC=1;    //软件强制同步脉冲,置1时,生成一次同步脉冲//同步输出选择。这些位选择EPWMxSYNCO信号的源。//0- EPWMxSYNC; 1- CTR=0,时间基准计数器等于零;2- CTR=CMPB;3- 关闭EPWMxSYNCO信号。EPwm2Regs.TBCTL.bit.SYNCOSEL=3;     //关闭EPWMxSYNCO信号EPwm2Regs.TBCTL.bit.PRDLD=0;        //0-使用影子寄存器模式;1-立即加载TBPRD寄存器,而不使用影子寄存器。EPwm2Regs.TBCTL.bit.PHSEN=1;        //1-使能同步信号输入,触发移相//计数器模式位//0-向上计数模式;1-向下计数模式;2-向上向下计数模式;3-停止-冻结计数器操作(默认为复位)EPwm2Regs.TBCTL.bit.CTRMODE=0;EPwm2Regs.TBPHS.half.TBPHS=5000-1250;       //设置相位寄存器为0EPwm2Regs.TBCTR=0;                  //清除计数值/****************************计数器比较模块(CC)配置*****************************/EPwm2Regs.CMPCTL.bit.SHDWAMODE=0;   //0-影子模式;1-立即加载模式EPwm2Regs.CMPCTL.bit.SHDWBMODE=0;   //0-影子模式;1-立即加载模式//从影子寄存器加载到活动寄存器模式选择//0- CTR=0时加载;1- CTR=PRD时加载;2- CTR=0或PRD时,加载;3- 不加载(冻结)。EPwm2Regs.CMPCTL.bit.LOADAMODE = 0;EPwm2Regs.CMPCTL.bit.LOADBMODE = 0;EPwm2Regs.CMPA.half.CMPA=2500;EPwm2Regs.CMPB =1250;/****************************动作限定模块(AQ)配置***************************///当计数器等于活动的CMPA寄存器并且计数器在递增时进行操作。//0-无动作;1-强制EPWMxA输出低;2-强制EPWMxA输出高;3-翻转EPWMxA输出EPwm2Regs.AQCTLA.bit.CAU=1;//计数器等于零时的动作//0-无动作;1-强制EPWMxA输出低;2-强制EPWMxA输出高;3-翻转EPWMxA输出EPwm2Regs.AQCTLA.bit.ZRO=2;/*************************死区产生模块(DB)配置*****************************/EPwm2Regs.DBCTL.bit.HALFCYCLE=0;//半周期时钟使能位。0-启用全周期时钟;1-启用半周期时钟/*死区输入模式控制(bit5 bit4)*00- EPWMxA In(来自动作限定模块)是下降边缘和上升边缘延迟的来源*01- EPWMxB输入上升沿延时器,EPWMxA输入下降沿延时器*10- EPWMxA输入上升沿延时器,EPWMxB输入下降沿延时器*11- EPWMxB In(来自动作限定模块)是下降边缘和上升边缘延迟的来源*/EPwm2Regs.DBCTL.bit.IN_MODE=0;/* 上升沿延时器输出(EPWMxA)和下降沿输出(EPWMxB)的信号极性选择控制(bit3 bit2)* 00- EPWMxA和EPWMxB都不反向,AH模式* 01- EPWMxA反向,EPWMxB不反向。ALC模式* 10- EPWMxB反向,EPWMxA不反向。AHC模式* 11- EPWMxA和EPWMxB都反向,AL模式*/EPwm2Regs.DBCTL.bit.POLSEL=2;/*死区输出模式控制(bit1 bit0)* 00-两个输出信号都绕过了死带生成器。在这种模式下,动作限定器的EPWMxA和EPWMxB输出信号都直接传递给PWM斩波模块。在这种模式下,POLSEL和IN_MODE位不起作用。* 01-禁用上升边缘延迟器。动作限定器符的EPWMxA信号直接传递给PWM斩波子模块的EPWMxA输入。下降沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxB输入* 10-禁用下降边缘延迟器。动作限定器符的EPWMxB信号直接传递给PWM斩波子模块的EPWMxB输入。上升沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxA输入* 11-上升沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxA输入,下降沿延时器的信号经过极性选择后传递给PWM斩波子模块的EPWMxB输入。*/EPwm2Regs.DBCTL.bit.OUT_MODE=11;//上升沿延迟计数。10位计数器。(全周期模式)RED=DBRED*T(TBCLK);(半周期模式)RED=DBRED*T(TBCLK)/2EPwm2Regs.DBRED=50;//下降边缘延迟计数。10位计数器 (全周期模式)FED=DBFED*T(TBCLK);(半周期模式)FED=DBFED*T(TBCLK)/2EPwm2Regs.DBFED=50;/************************* PWM 斩波(PC)模块配置*****************************/EPwm2Regs.PCCTL.bit.CHPEN=0;//0-禁用PWM斩波模块;1-启用PWM斩波模块/************************* 错误联防(TZ)模块配置*****************************/EPwm2Regs.TZSEL.all=0;  //禁用所有的TZ模块的CBC和OSHT触发源EPwm2Regs.TZDCSEL.all=0;    //禁用所有的数字比较输出事件/*数字比较输出A事件1对EPWMxA的动作:* 0- EPWMxA=高阻抗状态* 1- 强制EPWMxA进入高电平。* 2- 强制EPWMxA进入低电平。* 3- 不动作,禁用*/EPwm2Regs.TZCTL.bit.DCAEVT1=3;EPwm2Regs.TZCTL.bit.DCAEVT2=3;//同上解释EPwm2Regs.TZCTL.bit.DCBEVT1=3;EPwm2Regs.TZCTL.bit.DCBEVT2=3;EPwm2Regs.TZCTL.bit.TZA=3;EPwm2Regs.TZCTL.bit.TZB=3;EPwm2Regs.TZEINT.bit.CBC=0;    //禁用CBC事件中断EPwm2Regs.TZEINT.bit.DCAEVT1=0;//禁用DCAEVT1中断EPwm2Regs.TZEINT.bit.DCAEVT2=0;//禁用DCAEVT2中断EPwm2Regs.TZEINT.bit.DCBEVT1=0;//禁用DCBEVT1中断EPwm2Regs.TZEINT.bit.DCBEVT2=0;//禁用DCBEVT2中断EPwm2Regs.TZEINT.bit.OST=0;//禁用OST中断//清除TZFLG的所有标志位EPwm2Regs.TZCLR.all=0X7F;//1-对TZFRC相应位写入1强制相应事件触发条件并设置TZFLG相应位 。0-不使用。EPwm2Regs.TZFRC.all=0;/************************* 事件触发(ET)模块配置*****************************/EPwm2Regs.ETSEL.bit.SOCBEN=0;//0-禁止产生EPWMxSOCB脉冲去触发ADC转换EPwm2Regs.ETSEL.bit.SOCBSEL=0;//由于SOCB禁用,此处无用EPwm2Regs.ETSEL.bit.SOCAEN=0;//0-禁止产生EPWMxSOCA脉冲去触发ADC转换;1-允许产生EPWMxSOCA脉冲去触发ADC转换/*EPWMxSOCA脉冲产生的选择选项* 0-允许DCAEVT1.soc事件触发产生* 1-允许TBCTR=0时触发产生* 2-允许TBCTR=TBPRD时触发产生* 3-允许TBCTR=0或TBCTR=TBPRD时触发产生* 4-允许向上计数模式下TBCTR=CMPA时触发产生* 5-允许向下计数模式下TBCTR=CMPA时触发产生* 6-允许向上计数模式下TBCTR=CMPB时触发产生* 7-允许向下计数模式下TBCTR=CMPB时触发产生*/EPwm2Regs.ETSEL.bit.SOCASEL=6;EPwm2Regs.ETSEL.bit.INTEN=0;//0-禁止EPWMx_INT生成EPwm2Regs.ETSEL.bit.INTSEL=0;//由于EPWMx_INT禁用,此处无用EPwm2Regs.ETPS.bit.SOCBPRD=0;//关闭SOCB事件计数器。不会产生EPWMxSOCB脉冲/*ePWM ADC转换触发A事件(EPWMxSOCA)周期选择* 0-禁用SOCA事件计数器。不会产生EPWMxSOCA脉冲* 1-在第一个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =1* 2-在第二个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =2* 3-在第三个事件上生成EPWMxSOCA脉冲:ETPS[SOCACNT] =3*/EPwm2Regs.ETPS.bit.SOCAPRD=3;EPwm2Regs.ETPS.bit.INTPRD=0;//禁用中断事件计数器。不会产生中断,ETFRC[INT]将被忽略。EPwm2Regs.ETCLR.bit.INT=1;//ePWM中断(EPWMx_INT)标志清除位:写1时清除ETFLG[INT]标志位,并允许生成进一步的中断脉冲(由于禁用中断,此处无用)EPwm2Regs.ETCLR.bit.SOCA=1;//ePWM ADC转换触发A(EPWMxSOCA)标志清除位:写1清除ETFLG[SOCA]标志位EPwm2Regs.ETCLR.bit.SOCB=1;//ePWM ADC转换触发B(EPWMxSOCB)标志清除位:写1清除ETFLG[SOCB]标志位(由于禁用SOCB,此处无用)EPwm2Regs.ETFRC.bit.SOCA=0;//EPWMxSOCA软件强制触发位:写1-在EPWMxSOCA上生成脉冲并设置SOCBFLG位。此位用于测试目的。(只有需要启用EPWMxSOCA脉冲时才有用,即ETSEL.SOCAEN=1)EPwm2Regs.ETFRC.bit.SOCB=0;//EPWMxSOCA软件强制触发位:写1-在EPWMxSOCB上生成脉冲并设置SOCBFLG位。此位用于测试目的。(只有需要启用EPWMxSOCB脉冲时才有用,即ETSEL.SOCBEN=1)EPwm2Regs.ETFRC.bit.INT=0;//EPWMxINT软件强制触发位:写1-在EPWMxINT上生成一个中断,并设置INT标志位。此位用于测试目的(只有需要启用EPWMx_INT脉冲时才有用,即ETSEL.INTEN=1)/************************* 数字比较(DC)模块配置*****************************///暂无使用/************************<<EPWM2配置 end>>***************************/}
在main.c文件中引用以下代码配置ePWM
ePWM_init();
  • CLA部分主要读取ADC结果值,并把结果转化成电压,根据电压值来设置ePWM2波形的相位值。(关系式:phase=5000 - (voltage * 2500)/3.3 。当电压=3.3V时,移相180°;当电压=0V时,移相0°。)

1- 配置cmd文件给CLA分配内存,根据下图分配

MEMORY
{PAGE 0 :   /* Program Memory 存放程序 *//* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */RAML0       : origin = 0x008000, length = 0x000800     /* on-chip RAM block L0 */RAML1       : origin = 0x008800, length = 0x000400     /* on-chip RAM block L1 */RAML3       : origin = 0x009000, length = 0x001000   /* on-chip RAM block L3 这块内存用来存放CLA的程序,必需*/OTP         : origin = 0x3D7800, length = 0x000400     /* on-chip OTP */FLASHH      : origin = 0x3D8000, length = 0x004000     /* on-chip FLASH */FLASHG      : origin = 0x3DC000, length = 0x004000     /* on-chip FLASH */FLASHF      : origin = 0x3E0000, length = 0x004000     /* on-chip FLASH */FLASHE      : origin = 0x3E4000, length = 0x004000     /* on-chip FLASH */   FLASHD      : origin = 0x3E8000, length = 0x004000     /* on-chip FLASH */
//   FLASHC      : origin = 0x3EC000, length = 0x004000     /* on-chip FLASH */FLASHA_B    : origin = 0x3F0000, length = 0x007F80     /* on-chip FLASH */CSM_RSVD    : origin = 0x3F7F80, length = 0x000076     /* Part of FLASHA.  Program with all 0x0000 when CSM is in use. */BEGIN       : origin = 0x3F7FF6, length = 0x000002     /* Part of FLASHA.  Used for "boot to Flash" bootloader mode. */CSM_PWL_P0  : origin = 0x3F7FF8, length = 0x000008     /* Part of FLASHA.  CSM password locations in FLASHA */FPUTABLES   : origin = 0x3FD590, length = 0x0006A0  /* FPU Tables in Boot ROM */IQTABLES    : origin = 0x3FDC30, length = 0x000B50    /* IQ Math Tables in Boot ROM */IQTABLES2   : origin = 0x3FE780, length = 0x00008C    /* IQ Math Tables in Boot ROM */IQTABLES3   : origin = 0x3FE80C, length = 0x0000AA    /* IQ Math Tables in Boot ROM */ROM         : origin = 0x3FF3B0, length = 0x000C10     /* Boot ROM */RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */PAGE 1 :   /* Data Memory 存放数据*//* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation *//* Registers remain on PAGE1                                                  */BOOT_RSVD   : origin = 0x000000, length = 0x000050     /* Part of M0, BOOT rom will use this for stack */RAMM0       : origin = 0x000050, length = 0x0003B0     /* on-chip RAM block M0 */RAMM1       : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */RAML2       : origin = 0x008C00, length = 0x000400     /* on-chip RAM block L2 */RAML4       : origin = 0x00A000, length = 0x002000     /* on-chip RAM block L4 */RAML5       : origin = 0x00C000, length = 0x002000     /* on-chip RAM block L5 */RAML6       : origin = 0x00E000, length = 0x002000     /* on-chip RAM block L6 */RAML7       : origin = 0x010000, length = 0x002000     /* on-chip RAM block L7 */RAML8       : origin = 0x012000, length = 0x001800     /* on-chip RAM block L8 */USB_RAM     : origin = 0x040000, length = 0x000800     /* USB RAM        */FLASHC      : origin = 0x3EC000, length = 0x004000     /* on-chip FLASH *///下面两个内存用来CLA与CPU交互使用,必需CLATOCPU_MSGRAM  :origin = 0x001480, length = 0x000080CPUTOCLA_MSGRAM  :origin = 0x001500, length = 0x000080
}/* Allocate sections to memory blocks.Note:codestart user defined section in DSP28_CodeStartBranch.asm used to redirect codeexecution when booting to flashramfuncs  user defined section to store functions that will be copied from Flash into RAM
*/SECTIONS
{/* Allocate program areas: */.cinit              : > FLASHA_B,   PAGE = 0.pinit              : > FLASHA_B,   PAGE = 0.text               : > FLASHA_B,   PAGE = 0codestart           : > BEGIN,      PAGE = 0ramfuncs            : LOAD = FLASHD,RUN = RAML0,LOAD_START(_RamfuncsLoadStart),LOAD_END(_RamfuncsLoadEnd),RUN_START(_RamfuncsRunStart),LOAD_SIZE(_RamfuncsLoadSize),PAGE = 0csmpasswds          : > CSM_PWL_P0, PAGE = 0csm_rsvd            : > CSM_RSVD,   PAGE = 0/* Allocate uninitalized data sections: */.stack              : > RAMM0,      PAGE = 1.ebss               : > RAML2,    PAGE = 1.esysmem            : > RAML2,    PAGE = 1/* Initalized sections to go in Flash *//* For SDFlash to program these, they must be allocated to page 0 */.econst             : > FLASHA_B,   PAGE = 0.switch             : > FLASHA_B,   PAGE = 0/* Allocate IQ math areas: */IQmath              : > FLASHA_B,   PAGE = 0            /* Math Code */IQmathTables        : > IQTABLES,   PAGE = 0, TYPE = NOLOAD/* Allocate FPU math areas: */FPUmathTables       : > FPUTABLES,  PAGE = 0, TYPE = NOLOADDMARAML5              : > RAML5,      PAGE = 1DMARAML6            : > RAML6,      PAGE = 1DMARAML7            : > RAML7,      PAGE = 1DMARAML8            : > RAML8,      PAGE = 1   /***************** CLA程序设置存放在FLASHE区,运行在RAML3区,PAGE 0**********************/Cla1Prog               : LOAD = FLASHE,RUN  = RAML3,LOAD_START(_Cla1funcsLoadStart), //FLASHE中存放的首地址LOAD_END(_Cla1funcsLoadEnd), //FLASHE中存放的尾地址RUN_START(_Cla1funcsRunStart), //RAML3中运行的首地址LOAD_SIZE(_Cla1funcsLoadSize),   //存放在FLASHE中的程序大小PAGE = 0Cla1ToCpuMsgRAM       : > CLATOCPU_MSGRAM, PAGE = 1   //Cla1ToCpuMsgRAM分配到CLATOCPU_MSGRAM内存区CpuToCla1MsgRAM       : > CPUTOCLA_MSGRAM, PAGE = 1   //CpuToCla1MsgRAM分配到CPUTOCLA_MSGRAM内存区/* Uncomment the section below if calling the IQNexp() or IQexp()functions from the IQMath.lib library in order to utilize therelevant IQ Math table in Boot ROM (This saves space and Boot ROMis 1 wait-state). If this section is not uncommented, IQmathTables2will be loaded into other memory (SARAM, Flash, etc.) and will takeup space, but 0 wait-state is possible.*//*IQmathTables2    : > IQTABLES2, PAGE = 0, TYPE = NOLOAD{IQmath.lib<IQNexpTable.obj> (IQmathTablesRam)}*//* Uncomment the section below if calling the IQNasin() or IQasin()functions from the IQMath.lib library in order to utilize therelevant IQ Math table in Boot ROM (This saves space and Boot ROMis 1 wait-state). If this section is not uncommented, IQmathTables2will be loaded into other memory (SARAM, Flash, etc.) and will takeup space, but 0 wait-state is possible.*//*IQmathTables3    : > IQTABLES3, PAGE = 0, TYPE = NOLOAD{IQmath.lib<IQNasinTable.obj> (IQmathTablesRam)}*//* .reset is a standard section used by the compiler.  It contains the *//* the address of the start of _c_int00 for C Code.   /*/* When using the boot ROM this section and the CPU vector *//* table is not needed.  Thus the default type is set here to  *//* DSECT  */.reset              : > RESET,      PAGE = 0, TYPE = DSECTvectors             : > VECTORS,    PAGE = 0, TYPE = DSECT}

CLAShared.h 声明变量及任务入口地址

#ifndef CLA_SHARED_H
#define CLA_SHARED_H#ifdef __cplusplus
extern "C" {#endif//
// Included Files
//
//  #include "IQmathLib.h"#include "DSP28x_Project.h"//
// Defines
//extern float32  VoltFilt;extern float32 ClaVal;//
// The following are symbols defined in the CLA assembly code
// Including them in the shared header file makes them
// .global and the main CPU can make use of them.
//extern Uint32 Cla1Task1;extern Uint32 Cla1Task2;extern Uint32 Cla1Task3;extern Uint32 Cla1Task4;extern Uint32 Cla1Task5;extern Uint32 Cla1Task6;extern Uint32 Cla1Task7;extern Uint32 Cla1Task8;extern Uint32 Cla1Prog_Start;extern Uint32 Cla1T1End;extern Uint32 Cla1T2End;extern Uint32 Cla1T3End;extern Uint32 Cla1T4End;extern Uint32 Cla1T5End;extern Uint32 Cla1T6End;extern Uint32 Cla1T7End;extern Uint32 Cla1T8End;#ifdef __cplusplus
}
#endif /* extern "C" */#endif  // end of CLA_SHARED definition//
// End of File
//

main.c文件中配置CAL的程序

#include <stdio.h>
#include "ADC.h"
#include "ePWM.h"
#include "usart.h"
#include "CLAShared.h"
#include <string.h>//定义CLA与CPU交互的变量
#pragma DATA_SECTION(VoltFilt,   "Cla1ToCpuMsgRAM");  //把VoltFilt存放在Cla1ToCpuMsgRAM内存块中
#pragma DATA_SECTION(ClaVal,    "Cla1ToCpuMsgRAM");       //把ClaVal存放在Cla1ToCpuMsgRAM内存块中
float32 VoltFilt;   //定义变量
float32 ClaVal;//声明外部变量,定义在cmd文件中
extern Uint16 Cla1funcsLoadStart;
extern Uint16 Cla1funcsLoadEnd;
extern Uint16 Cla1funcsRunStart;
extern Uint16 Cla1funcsLoadSize;void init_cla(void);    //CLA初始化函数interrupt void cla1_isr1(void);   //CLA执行任务Task1后,在CPU中触发的中断函数void init_cla(void)
{EALLOW;//在PCLKCR3寄存器中使能CLA时钟,一般这句话不用写,因为在InitSysCtrl();函数中就已经配置了所有外设的时钟;SysCtrlRegs.PCLKCR3.bit.CLA1ENCLK=1;//将CLA的TASK函数绑定到中断向量表上Cla1Regs.MVECT1 = (Uint16) (&Cla1Task1 - &Cla1Prog_Start)*sizeof(Uint32);Cla1Regs.MVECT8 = (Uint16) (&Cla1Task8 - &Cla1Prog_Start)*sizeof(Uint32);//设置每个TASK的触发源,有三种选项,PWM触发、ADC触发以及软件触发Cla1Regs.MPISRCSEL1.bit.PERINT1SEL=CLA_INT1_ADCINT1;Cla1Regs.MPISRCSEL1.bit.PERINT2SEL=CLA_INT2_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT3SEL=CLA_INT3_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT4SEL=CLA_INT4_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT5SEL=CLA_INT5_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT6SEL=CLA_INT6_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT7SEL=CLA_INT7_NONE;Cla1Regs.MPISRCSEL1.bit.PERINT8SEL=CLA_INT8_NONE;//将CLA代码拷贝入CLA的代码段,因为CLA的代码需要单独放在一个固定的位置,所以需要执行这一段代码memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);//如果需要使用到软件触发,那么需要执行Cla1Regs.MCTL.bit.IACKE = 1;Cla1Regs.MCTL.bit.IACKE = 1;//使能软件中断Cla1Regs.MIER.all = (M_INT1  | M_INT8);//使能2个任务中断//将CLA的数据段和程序段都映射到CLA空间Cla1Regs.MMEMCFG.bit.PROGE = 1;//把RAML3映射为CLA的程序空间// Enable INT 11.1 in the PIE (CLA Task1)// Enable INT 11 at the CPU level// Enable Global interrupts with INTM// Enable Global realtime interrupts with DBGM//EALLOW;PieVectTable.CLA1_INT1 = &cla1_isr1;   //自定义中断函数EDIS;PieCtrlRegs.PIEIER11.bit.INTx1 = 1; //task1触发的中断在11.1的中断线上,使能中断线IER |= M_INT11;    //使能中断组11EINT;ERTM;//触发TASK8Cla1ForceTask8();}interrupt void cla1_isr1(void)
{char NUMCHAR_[64];AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//Must clear ADCINT1 flag since INT1CONT = 0PieCtrlRegs.PIEACK.all = 0xFFFF;sprintf(NUMCHAR_,"CLA TEST: sample time: %d;cla_val:%f V.\r\n",(Uint16)VoltFilt,ClaVal);//串口打印数据UARTa_SendString(NUMCHAR_);sprintf(NUMCHAR_,"CLA ePWM2 TBPHS: %d.\r\n",EPwm2Regs.TBPHS.half.TBPHS);//串口EPwm2的相位值,看看CLA有没有修改到UARTa_SendString(NUMCHAR_);
}int main(void)
{InitSysCtrl();InitPieCtrl();IER = 0x0000;IFR = 0x0000;InitPieVectTable();init_cla();Usart_Init(9600);    //此函数需要各位自己写//adcADC_Init();InitAdcConfigAndIO();
#if Interrupt_Allow == 1OpenAdcInterrupt_PIE();
#endifePWM_init();msg="Hello,CLA TEST!\r\n\0";UARTa_SendString(msg);GetChResult(1,9,5);//5-epwm1a SOCa 触发while(1);
}

CLA的主程序,使用汇编编写。CLA.asm

// Include variables and constants that will be shared in the
;// C28x C-code and CLA assembly code.  This is accomplished by
;// using .cdecls to include a C-code header file that contains
;// these variables and constants.cdecls   C,LIST,"CLAShared.h";// To include an MDEBUGSTOP (CLA breakpoint) as the first instruction
;// of each task, set CLA_DEBUG to 1.  Use any other value to leave out
;// the MDEBUGSTOP instruction.CLA_DEBUG .set  1;// CLA code must be within its own assembly section and must be
;// even aligned.  Note: since all CLA instructions are 32-bit
;// this alignment naturally occurs and the .align 2 is most likely
;// redundant.sect        "Cla1Prog"
_Cla1Prog_Start.align       2_Cla1Task1:.if CLA_DEBUG == 1MDEBUGSTOP.endifMUI16TOF32 MR0, @_AdcResult.ADCRESULT0 ;获取ADC结果0MNOPMUI16TOF32 MR1, @_AdcResult.ADCRESULT1  ;获取ADC结果1MADDF32 MR2, MR1, MR0                    ;MR2 = MR1 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT2  ;获取ADC结果2MADDF32 MR2, MR2, MR0                 ;MR2 = MR2 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT3 ;获取ADC结果3MADDF32 MR2, MR2, MR0                  ;MR2 = MR2 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT4 ;获取ADC结果4MADDF32 MR2, MR2, MR0                  ;MR2 = MR2 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT5 ;获取ADC结果5MADDF32 MR2, MR2, MR0                  ;MR2 = MR2 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT6 ;获取ADC结果6MADDF32 MR2, MR2, MR0                  ;MR2 = MR2 + MR0MUI16TOF32 MR0,   @_AdcResult.ADCRESULT7 ;获取ADC结果7MADDF32 MR2, MR2, MR0                  ;MR2 = MR2 + MR0MMPYF32    MR1, MR2, #0.125               ;把累加的8给结果求平均值,MR1=MR2*0.125MMPYF32    MR2, MR1, 0.000805           ; MR2  = MR1  * 3.3/4096,把ADC值转出电压值MMOV32      @_ClaVal, MR2               ;存放电压值到ClaVal;相位值的运算phase=5000 - (voltage * (2500/3.3))  MMPYF32      MR0, MR2, #-757.575758       MADDF32    MR1, MR0, #5000.0MMOV32     @_VoltFilt, MR1                   ;存放相位MF32TOUI16 MR2, MR1                      ;把浮点数转存为16位整数MMOV16    @_EPwm2Regs.TBPHS.half.TBPHS, MR2  ;设置EPWM2相位MSTOP                                  ;结束
_Cla1T1End:_Cla1Task2:MSTOPMNOPMNOPMNOP
_Cla1T2End:_Cla1Task3:MSTOPMNOPMNOPMNOP
_Cla1T3End:_Cla1Task4:MSTOPMNOPMNOPMNOP
_Cla1T4End:_Cla1Task5:  MSTOPMNOPMNOPMNOP
_Cla1T5End:_Cla1Task6:MSTOPMNOPMNOPMNOP
_Cla1T6End:    _Cla1Task7:MSTOPMNOPMNOPMNOP
_Cla1T7End:_Cla1Task8:;==============================================
; This task initializes the filter input delay
; line (X0 to X4) to zero
;==============================================.if CLA_DEBUG == 1MDEBUGSTOP.endifMMOVF32        MR0, #0.0MMOV32     @_VoltFilt, MR2    ;初始化VoltFilt为0MSTOP
_Cla1T8End:_Cla1Prog_End:.end.include "CLAShared.h"

实验现象

把ADC输入口短接到3.3V,串口读取的数据如下:

在ADC输入口接不同电压下,用示波器观察PWM波形:


结尾

CLA可以使用C语言编程,此此使用汇编来写,性能更佳。下次,出一篇CLA 使用C语言编写的文章。

DSP TMS320F2803x、TMS320F2806x CLA开发笔记(代码基于TMS320F28069 详解)相关推荐

  1. DSP TMS320F2803x、TMS320F2806x CPU Timer定时器开发笔记(代码基于TMS320F28069 详解)

    详解DSP F28069的 CPU Timer定时器模块,及代码讲解 32-Bit CPU Timers 0/1/2 代码讲解 timer.h /** Timer.h** Created on: 20 ...

  2. DSP TMS320F2803x、TMS320F2806x COMP比较器模块开发笔记(代码基于TMS320F28069 详解)

    详解DSP F28069的COMP比较器模块,及代码讲解(适用于2802x.2803x.2806x.M35x.M36x 型号) 比较器 (COMP) 模块 比较器模块是一个真正的模拟电压比较器在VDD ...

  3. DSP TMS320F2803x、TMS320F2806x CLA开发笔记(代码基于TMS320F28069 详解)- 使用C语言编程CLA

    CLA的相关介绍请看上篇 here CLA使用C语言编程的配置 cmd文件部分 /**********需要定义的变量*************/ CLA_SCRATCHPAD_SIZE = 0x100 ...

  4. Android开发笔记之:Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)

    本篇文章是对Android中的Log进行了详细的分析介绍,需要的朋友参考下 在Android群里,经常会有人问我,Android Log是怎么用的,今天我就把从网上以及SDK里东拼西凑过来,让大家先一 ...

  5. DSP TMS320F2803x、TMS320F2806x ADC开发笔记(代码基于TMS320F28069)

    TMS320F2803x.TMS320F2806x ADC开发笔记 ADC模块框图 SOC结构 中断结构 ADC转换时序 直接上代码 ADC.C文件如下: /** 粗略的延时函数,大于或等于1ms*/ ...

  6. 爬虫笔记:Requests库详解

    什么是Requests 之前讲解了爬虫笔记:Urllib库详解发现确实有不方便的地方,比如加一个代理,cookie,发送post请求比较繁琐. Request库能用几句话实现这些. Requests ...

  7. java 检查bytebuf长度_Java学习笔记16-Netty缓冲区ByteBuf详解

    Java学习笔记16-Netty缓冲区ByteBuf详解 Netty自己的ByteBuf ByteBuf是为解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的. JDK Byt ...

  8. 【区块链开发入门】(四) Truffle详解篇2

    由于本篇篇幅较长,因此转为两篇文章.Truffle详解篇篇1请见:link 目录导航页 [区块链开发入门](一) 以太坊的搭建与运行 [区块链开发入门](二) 以太坊的编程接口 [区块链开发入门](三 ...

  9. iVX低代码平台系列详解 -- 概述篇(二)

    写在前面 ivx动手尝试电梯:ivx在线编辑器 iVX系列教程持续更新中 上篇文章可看:iVX低代码平台系列详解 – 概述篇(一) ivx目录 写在前面 一.iVX优势 1.快速学习 2.快速开发 3 ...

最新文章

  1. 钉钉、阿里云和PaaS平台的整合开发
  2. 编译器扩展SEH(1)
  3. 智能判断图片中是否存在某物体_智能家居组件漫谈——人体传感器
  4. Handler post用法整理
  5. mysql 货币显示_在MySQL中以正确的格式显示USD货币记录
  6. playframe 项目搭建
  7. Windows操作系统下使用pip安装pygame
  8. matlab 图片保存pdf,matlab中的图片保存技巧.pdf
  9. CSS格式化工具-直接可以使用
  10. 真的精采!AI赢了DOTA界的世界冠军 让人兴奋又纠结
  11. sourcetree添加gitignore不生效解决方案
  12. [转载]基于Servlet的Google Earth之旅
  13. 某电商网站销售python图书_手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取...
  14. java excel 合并单元格
  15. 项目经验不丰富、技术不突出的程序员怎么打动面试官?
  16. html怎么多行超出省略号,css+js 如何实现多行文字超出显示省略号(需要同时兼容ie chrome等浏览器)...
  17. 美国邮编及电话号码区域查询
  18. 基于opencv库对图像进行平移,旋转以及翻转
  19. 王者荣耀服务器ip地址配置文件,王者荣耀,关于设置的一些小技巧,知道以后你也是大神...
  20. 6.进程通信 无名管道 有名管道

热门文章

  1. 科大讯飞/百度/阿里/腾讯(BAT)智能语音识别(ASR)性能对比选择预计价格分享
  2. SystemVerilog中logic var reg wire的区别
  3. Animate.css 与wow.js 实现效果 保姆级教学
  4. 英飞凌的增长秘籍:用智慧“芯”驱动未来
  5. WEB前端学习——第六次作业(banner图片左右切换按钮)
  6. java 实例方法直接调用超类的实例方法_Java继承关系中,父类方法使用实例变量和调用实例方法的探究...
  7. 01背包输出路径、完全背包、多重背包
  8. mac下excel乱码解决方案
  9. JAVA阅读书籍推荐
  10. 小睿云知识:云电脑要什么配置