• DSP28335学习记录(三)——ePWM


    本文记录dsp28335的中断的配置方法:


    目录

    一、ePWM模块内容

    1.1 时基模块TB

    1.2 计数比较模块CC

    1.3 动作模块AQ

    目前为止,以经可以实现基本PWM功能了。

    1.4 死区模块DB

     1.5 斩波模块PC

    1.6 错误联防模块 TZ

    1.7 SOC事件触发

    1.8 epwm事件中断


    一、ePWM模块内容

    F28335 的 ePWM 模块是个加强模块,与 F2812 的 PWM 模块有较大不同,在 F2812 中,PWM 模块采用事件管理器控制,与 eCAP 和 eQEP 共享定时器信号,而 F28335 中每个 ePWM 模块都是一个独立的小模块,这样的体系结构更方便我们使用与理 解。每个 ePWM 模块由两路 ePWM 输出组成,分别为 ePWMxA 和 ePWMxB,这一对 PWM 输出,可以配置成两路独立的单边沿 PWM 输出,或者两路独立的但互相相对称的 双边沿 PWM 输出,或者一对双边沿非对称的 PWM 输出,共有 6 对这样的 ePWM 模 普中 DSP28335 开发攻略 www.prechin.cn 276 块,因为每对 PWM 模块中的两个 PWM 输出均可以单独使用,所以也可以认为有 12 路单路 ePWM,除此之外还有 6 个 APWM,这 6 个 APWM 通过 CAP 模块扩展配置, 可以独立使用,所以 F28335 最多可以有 18 路 PWM 输出。每一组 ePWM 模块都包 含以下 7 个模块:时基模块 TB、计数比较模块 CC、动作模块 AQ、死区产生模块 DB、PWM 斩波模块 PC、错误联防模块 TZ、时间触发模块 ET,如下所示,

    每组 ePWM 模块支持以下特点:

    1. 专用 16 位时基计数器,控制输出的周期和频率。
    2. 两个互补对称 PWM 输出(ePWMxA 和 ePWMxB)可以配置如下方式: --两个独立的单边沿操作的 PWM 输出。 --两个独立的双边沿操作对称的 PWM 输出。 --一个独立的双边沿操作非对称的 PWM 输出。
    3. 软件实现 PWM 信号异步控制。
    4. 可编程的相位控制以支持超前或滞后其余的 PWM 模块
    5. 逐周期硬件同步相位
    6. 双边沿延时死区控制。
    7. 可编程错误联防。
    8. 产生错误时可以强制 PWM 输出高电平、低电平或者高阻态。
    9. 所有的事件都可以触发 CPU 中断和 ADC 开始转换信号。
    10. 高频 PWM 斩波,用于基于脉冲变压器的门极驱动

    1.1 时基模块TB

    TB模块的主要作用是定时器,计数器。

    需要设置时钟预分频,分频,周期,相位,计数方向,周期重载使能,其他通道时钟同步,影子寄存器使能。

    通过影子寄存器修改参数。因为定时器中每个脉冲来了都要在寄存器中修改值,读写频率很高,如果用户随意读写寄存器的值,很容易发生冲突,产生问题。影子寄存器相当于一个缓存器,专门给用户实时修改寄存器提供一个通道,只要开启影子寄存器功能,读写寄存器和源寄存器一样。

    1.2 计数比较模块CC

    计数器比较模块是以时基计数器的计数值作为输入,与比较寄存器CMPA和CMPB不断进行比较,当时基计数器的值等于CMPA时,就产生比较事件CTR = CMPA;当时基计数器的值等于CMPB时,就产生比较事件CTR = CMPB。计数寄存器模块有以下要点进行说明:

    • 计数比较模块进行恰当配置后,可以控制PWM波形的占空比。
    • 采用影子寄存器来更新比较寄存器可有效防止在PWM周期内出现故障以及毛。

    1.3 动作模块AQ

    配置pwm的高低电平变化的位置和极性。

    每个通道主要有3个点,0点,设置比较点,周期点。我们设置两个点就好。

    例如向上计数,从0到周期点,前两个点就是0点,和比较点。

    我们设置=0时,低电平;等于CMPA时,高电平。就得到下图波形。

    EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR;         //ZRO 是0; PRD是周期点
    EPwm6Regs.AQCTLA.bit.CAU = AQ_SET;              //CAU 是比较点A,向上计数

     向下计数,同理。B通道也是一样设置。

    目前为止,以经可以实现基本PWM功能了。

    1. // 禁止CPU全局中断
    2. DINT;
    3. // // 禁止CPU中断和清除所有CPU中断标志
    4. // IER = 0x0000;
    5. // IFR = 0x0000;
    6. // InitPieCtrl();
    7. // InitPieVectTable();
    8. //步骤 2.
    9. EALLOW;//关闭写保护
    10. SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;
    11. EDIS;//打开写保护
    12. InitEPwm6Gpio();
    13. EALLOW;//关闭写保护
    14. SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1; // ePWM
    15. SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks
    16. // 设置TBCLK寄存器功能
    17. EPwm6Regs.TBPRD = 10000; // 设置周期值为10000,等于15k
    18. EPwm6Regs.TBPHS.half.TBPHS = 0x0000; // 设置相移值为0
    19. EPwm6Regs.TBCTR = 0x0000; // 清除计数器的值
    20. // 设置比较寄存器功能
    21. EPwm6Regs.CMPA.half.CMPA = 0; // 设置CMPA比较寄存器A的值为0
    22. EPwm6Regs.CMPB = 0; // 设置CMPB比较寄存器B的值为0
    23. // 设置计数模式功能
    24. EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 上下计数模式
    25. EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁止相移值装载到计数器
    26. EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 计数器值为0的时候发出同步信号,使得ePWM2/3/4/5/6的计数与1同步,不会产生误差偏移累加
    27. EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // 高速时钟预分频为1 TBCLK=150MHz
    28. EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 时钟预分频为1, 最终时钟频率:TBCLK=SYSCKOUT/(HSPCLKDIV*CLKDIV)=150MHz/(1*1)=150MHz
    29. // ePWM频率=TBCLK/(2*TBPRD)=150000000/(2*50000)=1500Hz
    30. // EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW; //TBPRD 寄存器采用影子寄存器模式
    31. SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; //使能时基计时器
    32. // 设置装载模式功能
    33. EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 设定CMPA为影子模式
    34. EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // 设定CMPB为影子模式
    35. EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // 设定在计数值CTR=ZERO时,装载CMPA比较值
    36. EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // 设定在计数值CTR=ZERO时,装载CMPB比较值
    37. // 设置动作功能
    38. EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
    39. EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
    40. EPwm6Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM1B on Zero
    41. EPwm6Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM1B on event B, up count
    42. PieCtrlRegs.PIEIER3.bit.INTx6 = 1;//使能ePWM6中断
    43. EDIS;//打开写保护
    44. //步骤 3. 使能CPU级中断及全局中断
    45. IER |= M_INT3;
    46. EINT;//打开全局中断
    47. ERTM;//当使用仿真器调试时 开启DEBUG中断

    1.4 死区模块DB

    配置AB两个通道之间的死区。

    在控制同一桥臂上的两个开关管不能同时导通,如果同时导通,就会造成电源短路。因此输入同一桥臂上的两个开关管的驱动信号必须 要进行互补控制。

    模块框图:

    通过三个寄存器配置:

     工作模式:

    模式波形图演示:

    可以忽略文档中的名字,让人迷惑。

    实际上就是延时 + 翻转的排列组合。

    互补主高:双延时+B翻转

    互补主低:双延时+A翻转

    主高:双延时+不翻转

    主低:双延时+双翻转

     

    1. //死区参数
    2. #define DB_IN_A 0 //上下均输入A
    3. #define DB_IN_A_UP_B_DOWN 2 //上升沿输入A,下降沿输入B
    4. #define DB_IN_B_UP_A_DOWN 1 //上升沿输入B,下降沿输入A
    5. #define DB_IN_B 3 //上下均输入B
    6. #define DB_SEL_0 0 //不翻转
    7. #define DB_SEL_A_F 1 //A翻转
    8. #define DB_SEL_B_F 2 //B翻转
    9. #define DB_SEL_A_B_F 3 //AB都翻转
    10. #define DB_OUT_0 0 //上下沿都不延时
    11. #define DB_Y_DOWN 1 //下降沿延时
    12. #define DB_Y_UP 2 //上升沿延时
    13. #define DB_Y_UP_DOWN 3 //上下沿都延时
    14. //设置死区模块
    15. EPwm6Regs.DBCTL.bit.IN_MODE = DB_IN_A_UP_B_DOWN; //EPWMA上边沿延时输入源,EPWMB下边沿延时输入源
    16. EPwm6Regs.DBCTL.bit.POLSEL = DB_SEL_0; //EPWMA 和 EPWMB都不翻转
    17. EPwm6Regs.DBCTL.bit.OUT_MODE = DB_Y_UP_DOWN; //EPWMA 和 EPWMB 双边沿延时
    18. EPwm6Regs.DBRED = 750; //上升沿延时一个时钟周期 5us
    19. EPwm6Regs.DBFED = 750; //下升沿延时一个时钟周期 5us

     1.5 斩波模块PC

    该功能主要用于基于脉冲变压器的门级驱动型功率器件控制中。一次模块OSHT主要用于提供较大能量的第一个脉冲,迅速有效地开通功率开关,接下来的脉冲只要维持开关的状态就行,例如多数功率器件的开通电流要比维持电流大得多。

    效果就是这样子,把PWM波的高电平,编程高频脉冲序列。

     斩波模块框图:

    系统时钟8分频进入模块。

    • 载波PSCLK的频率和占空比由 CHPCTL 寄存器中 的 CHPFREQ 和 CHPDUTY 进行配置。PSCLK的频率可以通过CHPFREQ分频,3bit范围【0~7】。PSCLK的占空比被8等分,只能设置12.5%的倍数,1~7倍。

    • 单触发模块的第一个脉冲的宽度可以由 OSHTWTH 来确定(4bit范围【1~16】)。

    T(1stpulse)=T(SYSCLKOUT)*8*OSHTWTH  // (OSHTWTH  = 1-16)

    PWM 斩波器这 一功能模块可以用 CHPEN 位进行使能控制与禁止。

    例程,

    1. //PC斩波模块
    2. #define PC_FREQ_DIV1 1 //频率PSCLK = 系统时钟频率/8之后,再/PC_FREQ_DIV
    3. #define PC_DUTY_50 4 //占空比CHPDUTY = PC_DUTY*12.5%
    4. #define PC_OSHTWTH 16 //第一个脉冲持续时间T1stpulse = 系统时钟周期 × 8 × OSHTWTH
    5. //设置斩波模块
    6. EPwm6Regs.PCCTL.bit.CHPFREQ = PC_FREQ_DIV1; //载波分频
    7. EPwm6Regs.PCCTL.bit.CHPDUTY = PC_DUTY_50; //载波占空比
    8. EPwm6Regs.PCCTL.bit.OSHTWTH = PC_OSHTWTH; //首脉冲宽度
    9. EPwm6Regs.PCCTL.bit.CHPEN = 1; //启动PC模块

    1.6 错误联防模块 TZ

    通常用于系统保护,出现故障时,需要快速关闭PWM。

    每个 ePWM 模块都与 GPIO 多路复用引脚中的 6 个 TZn(TZ1-TZ6)信号脚连接。 这些信号脚用来响应外部错误或外部触发条件,当错误发生时,PWM 模块可以通过编程来响应这些问题。

    错误联防模块的主要作用如下:

    1. 错误联防引脚 TZ1-TZ6 可以灵活的映射到对应的 PWM 模块
    2. 针对错误信息,ePWMxA 和 ePWMxB 可以被强制或如下几种状态

      --高电平。

      --低电平。

      --高阻抗。

      --无动作。

    3. 在短路或者过流条件时,支持一次错误联防触发
    4. 针对限流操作时,支持周期错误联防触发
    5. 每个错误联防输入引脚都可以配置为一次或者周期错误联防触发。
    6. 任何一个错误联防引脚都可以产生中断
    7. 支持软件强制错误联防。
    8. 如果不需要此模块,可以选择禁止。

    每个 TZn 输入引脚可以单独配置一次触发或者周期触发。

    • 周期触发(CBC)。当出现TZ信号会触发中断,直接作用于PWM。当TZ信号消失,会自动清除标志位,自动复位。
    • 单次触发(OST)。当出现TZ信号会触发中断,直接作用于PWM。需要软件复位,或者重启机器。

    需要配置寄存器:

    需要配置寄存器:

    • TZSEL :选择单次和周期触发,选择TZ通道。
    • TZCTL:设置触发之后AB两路PWM的状态。
    • TZEINT:TZ模块使能。
    • TZCLR.bit.INT:当单次触发模式下,在中断函数结束前需要赋1,清除一下,否则之后将不再触发中断

    例程,

    1. //错误联防
    2. #define High_Impedance 0 //高阻态
    3. #define Force_High 1 //强制高
    4. #define Force_Low 2 //强制低
    5. #define NO_Change 3 //不变
    6. //错误联防模块
    7. EPwm6Regs.TZSEL.bit.OSHT2 = 1; //单次触发,选择通道TZ2 GPIO13复用2
    8. EPwm6Regs.TZCTL.bit.TZA = Force_High; //触发之后强制低
    9. EPwm6Regs.TZCTL.bit.TZB = Force_High; //触发之后强制低
    10. EPwm6Regs.TZEINT.bit.OST = 1; //TZ模块使能
    11. SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;
    12. GpioCtrlRegs.GPBMUX2.bit.GPIO50 = 0;
    13. GpioCtrlRegs.GPBDIR.bit.GPIO50 = 1;
    14. GpioCtrlRegs.GPBPUD.bit.GPIO50 = 0;
    15. GpioDataRegs.GPBCLEAR.bit.GPIO50 = 1;
    16. GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 1; //GPIO13为故障输入口 TZ2
    17. GpioCtrlRegs.GPADIR.bit.GPIO13 = 0;
    18. GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0;
    19. GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; //GPIO12为故障复位
    20. GpioCtrlRegs.GPADIR.bit.GPIO12 = 0;
    21. GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;
    22. //设置中断PIE
    23. PieVectTable.EPWM6_TZINT = &PMW_TZ_ISR;
    24. PieCtrlRegs.PIEIER2.bit.INTx6 = 1; //使能错误联防TZ2的触发中断
    25. IER |= M_INT2; //别忘了使能CPU INT2通道
    26. interrupt void PMW_TZ_ISR(void)
    27. {
    28. int i;
    29. //接下来写错误清除信号的检测,当接收到错误联防信号,错误联防中断被触发进入此程序,
    30. //接下来检测按键是否被按下,当按键被按下,则表明故障已经清除,可以恢复PWM信号输出,
    31. while(EPwm6Regs.TZFLG.bit.OST == 1)
    32. {
    33. //这里写当按键被按下,则:
    34. //1.把错误联防中断清除寄存器TZCLR.bit.OST = 1以清除OST事件标志位,恢复PWM信号输出
    35. if(GpioDataRegs.GPADAT.bit.GPIO12 == 0)
    36. {
    37. for(i=0;i<20000;i++)//延时去抖
    38. {}
    39. if(GpioDataRegs.GPADAT.bit.GPIO12 == 0)
    40. {
    41. EALLOW;
    42. EPwm6Regs.TZCLR.bit.OST = 1; //清除OST事件标志位
    43. EDIS;
    44. }
    45. while(GpioDataRegs.GPADAT.bit.GPIO12 == 0);
    46. }
    47. }
    48. EALLOW;
    49. EPwm6Regs.TZCLR.bit.INT = 1;
    50. PieCtrlRegs.PIEACK.bit.ACK6 = 1;//清零PIEACK对应位
    51. EDIS;
    52. }

    1.7 SOC事件触发

    事件触发模块的功能主要如下:

    ①接收来自时基模块和计数比较模块产生的相关事件的输入。

    ②利用时基模块中的方向信息识别是递增还是递减计数模式以便产生相应 的事件。

    ③使用预定标判断逻辑发出中断请求或者 ADC 开始转换启动信号:

    --每个事件。

    --每两个事件。

    --每三个事件。

    ④允许软件配置,强制产生中断事件或者 ADC 启动信号。

    主要是再PWM周期内,特定时间点会产生事件,用这个信号来触发启动ADC。

    例如我们要在PWM的每个周期开始时刻采样系统参数,就会用到这个。

    1、事件触发选择寄存器 ETSEL

     2、事件触发分频寄存器 ETPS 各位功能描述如下

     

    3、事件触发标志寄存器 ETFLG 各位功能描述如

    4、事件触发清除寄存器 ETCLR 各位功能描述如

     5、事件触发强制寄存器 ETFRC

     上面5个寄存器中的名字有SOC开头的,有INT开头的。

    SOC开头的是SOC事件触发相关。

    INT开头的是epwm的事件中断相关,两个没有关系。只是放在一个寄存器里了。

    在SOC模块中只需要设置:

    1. 事件触发选择寄存器 ETSEL。触发soc事件的条件,soc的使能。
    2. 事件触发分频寄存器 ETPS。产生soc信号需要几个soc事件。
    3. 事件触发清除寄存器 ETCLR。清除soc的标志位。

    例程,

    epwm部分:

    1. //SOC
    2. #define SOC_SEL_ZRO 1 //TBCTR = 0
    3. #define SOC_SEL_PRD 2 //TBCTR = TBPRD
    4. #define SOC_SEL_CAU 3 //TBCTR = CMPA, 向上计数
    5. #define SOC_SEL_CAD 4 //TBCTR = CMPA, 向下计数
    6. #define SOC_SEL_CBU 5 //TBCTR = CMPB, 向上计数
    7. #define SOC_SEL_CBD 6 //TBCTR = CMPB, 向下计数
    8. #define SOC_PRD_DIS 0 //禁止事件计数器
    9. #define SOC_PRD_1 1 //第1个事件,产生SOC信号
    10. #define SOC_PRD_2 2 //第2个事件,产生SOC信号
    11. #define SOC_PRD_3 3 //第3个事件,产生SOC信号
    12. //SOC事件ADC触发
    13. EPwm6Regs.ETSEL.bit.SOCASEL = SOC_SEL_PRD; //在0处产生soc
    14. EPwm6Regs.ETSEL.bit.SOCAEN = 1; //SOCA使能
    15. EPwm6Regs.ETPS.bit.SOCAPRD = SOC_PRD_1; //第一个事件时,产生soc
    16. EPwm6Regs.ETCLR.bit.SOCA = 1; //清楚SOCA标志位

     ADC部分:很简单。

    1. // Start SEQ1
    2. AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; //使能epwm_SOCA信号的触发SQE1
    3. AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; //使能SEQ1

    1.8 epwm事件中断

    配置寄存器和1.7中一样,只是不同位。

    设置思路和1.7类似。

    只需要设置:

    1. 事件触发选择寄存器 ETSEL。触发中断事件的条件,中断的使能。
    2. 事件触发分频寄存器 ETPS。产生进入中断需要几个事件。
    3. PIE设置。向量表重映射,通道使能。
    4. CPU中断使能。
    5. 在中断函数结束前,清除标志位。

    例程,

    1. // ETPS (Event Trigger Pre-scale)
    2. //===============================
    3. // INTPRD, SOCAPRD, SOCBPRD bits
    4. #define ET_DISABLE 0x0
    5. #define ET_1ST 0x1
    6. #define ET_2ND 0x2
    7. #define ET_3RD 0x3
    8. EALLOW;//关闭写保护
    9. // 设置事件模块的中断功能
    10. EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // 在CTR=TBPRD时,产生中断
    11. EPwm6Regs.ETSEL.bit.INTEN = 1; // 使能中断
    12. EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // 每一次满足中断条件就产生一次中断
    13. //ET事件触发模块的PIE设置
    14. PieVectTable.EPWM6_INT = &EPWM_IRQ;
    15. PieCtrlRegs.PIEIER3.bit.INTx6 = 1;//使能ePWM1中断
    16. EDIS;//打开写保护
    17. //步骤 3. 使能CPU级中断及全局中断
    18. IER |= M_INT2;
    19. IER |= M_INT3;
    20. EINT;//打开全局中断
    21. ERTM;//当使用仿真器调试时 开启DEBUG中断
    22. interrupt void EPWM_IRQ(void)
    23. {
    24. //pwm计数器周期开始时会进来,
    25. EPwm6Regs.ETCLR.bit.INT = 1; //清除epwm中断标志位
    26. PieCtrlRegs.PIEACK.bit.ACK6 = 1;//清零PIEACK对应位
    27. }

    待续。。

  • 相关阅读:
    java基于微信小程序的学习打卡系统 uniapp 小程序
    在智慧农业领域需要研究什么
    阿里云 :推出通义大模型编码助手产品【通义灵码】
    React 窗口防抖
    java中的set集合[69]
    mbox在react中的使用
    C++入门3+类和对象上
    Linux命令yum
    HTML+CSS+JS制作结婚邀请函代码(程序员专属情人节表白网站)
    Linux篇:进程
  • 原文地址:https://blog.csdn.net/qq_30835339/article/details/125432037