概述
中科昊芯DSP_RISC-V笔记_PWM事件触发
- 课程要求
- ePWM 模块结构图
- ePWM模块寄存器映射
- Epwm讲解
- Epwm时基TB
- 时基频率配置TBCLK
- Epwm数据比较cc
- AQ输入事件选择
- 优先级判断
- AQ输出控制
- AQ的控制和状态寄存器
- 事件触发ET
- 中断EPWMINT产生
- ADC开始转换信号SOCA/B产生
- Epwm死区DB
- 输入选择交叉通路
- 边沿延迟控制
- 输出选择
- 错误联防TZ
- 错误联防TZ详讲
- 周期循环触发CBC事件
- 单次触发OSHT事件
- DC事件
- 中断触发
- 代码部分
课程要求
1.功能:(5分钟)
(1)输出如下侧图周期在2.2ms,高电平在55us到2145us变化的PWM波(脉冲计数0-10循环)
(2)产生死区时间在0至最大周期值变化的带死区PWM波,死区波形epwmxA与epwmxB置低,均存在取反延迟
(3)epwm1单次触发epwm1A置高,epwm1B置低(事件2) . epwm2周期循环触发epwm2A置高,epwm2B置低(事件3)
2.epwm讲解(30分钟)
3.程序讲解(40分钟)
4.调试(10分钟)
芯片手册PWM模块
ePWM 模块结构图
EPWMxSYNCI EPWMx。x表示还有3、4、5、6、7。
EQEPIERR 故障信号
EMUSTOP系统仿真信号
EPWMIENCLK中断事件触发信号
多个事件触发 PIE内部时钟响应
触发COMP 通过TBC接口 连接EPWMDC里面 产生相应的事件
EPWMDC 每个事件都可以触发ADC转换
EPWM支持高精度(HRPWM)
ePWM模块寄存器映射
Epwm讲解
ePWM 子模块关键内部信号互连示意图
Epwm时基TB
TB可以确定所有ePWM事件的时序。内部同步逻辑允许多个ePWM模块的TB能够作为一个系统协同工作。
配置TB可实现以下功能:
1.相对于系统时钟SYSCLKOUT,成比例缩放生成TBCLK,通过TBCTL[HSPCLKDIV]与TBCTL[CLKDIV]配置,实现以更慢的速率进行计数;
2.带宽调制的TB计数器TBCTR的计数周期TBPRD可配置,实现对事件发生频率的控制;
3.设置TB计数器的运行模式TBCTL[CTRMODE]:00向上,01向下,10向上向下计数模式11停止计数
·4.可通过配置相对相位TBPHS,实现不同epwm模块间的同步;
5.可通过硬件/软件启动模块间的同步,同时可通过配置TBCTL[PHSEN]屏蔽同步事件:
·(1)未被屏蔽时,同步事件发生时,会将TBPHS值写入到TBCTR。
·(2)同步事件发生,且同步被使能TBCTL[PHSEN]=1情况下,下一个TBCLK有效时,装载控制寄存器TBPHS的值到TBCTR。
(3)TBCTL[PSHDIR]用来控制同步事件发生之后,向上向下计数模式下,可配置TB计数器的计数方向。
(4)epwm模块同步源包括:a)同步输入信号i_epwmxsynci等于1,b)TB计数器等于零,c)TB计数器等于CMPB,d)DC事件,e)软件强
制同步TBCTL[SWFSYNC]=1,f)或不产生同步输出信号
·6.设备被仿真器挂起时,可配置成TBCTL[free,soft]控制TB计数器的行为
7.可以生成以下事件:a)CTR=PRD(某特定的)b)CTR=Zero:TBCTR=0x0000
8.通过TBCTL[PRDLD]控制,TBPRD寄存器的shadow影子功能:
a)PRDLD=1,不启动shadow,读写直接访问active寄存器
b)PRDLD=0.启动shadow机制,写访问两者都写到shadow寄存器,而读TBPRD返回shadow,读TBPRD返回active,此时若TBCTR=0x0000
时基频率配置TBCLK
·分频公式:TBCLK=SYSCLKOUT/(HSPCLKDIV*CLKDIV)
·CLKDIV(低速)最大值对应128,HSPCLKDIV(高速)最大值对应14,分别用一个8位和4位计数器控制,
·CLKDIV分为000-1分频001-2分频010-4分频011-8分频100-16分频101-32分频110-64分频
111-128分频
·HSPCLKDIV分为000-1分频001-2分频010-4分频011-6分频100-8分频101-10分频110-12
分频111-14分频
·i_tbclksync=0时,停止tbclk的计数器。
系统一般会将i_tbclksync清零后,即停止tbclk计数,从而可配置各个ePWM寄存器,之后置位
i_tbclksync,实现多个ePWM间的同步
Epwm数据比较cc
·负责产生两个独立事件:将来自TB子模块的计数器值TBCTR与其控制寄存器CMPA和CMPB进
行比较,生成CTR=CMPA和CTR=CMPB发送给AQ子模块。
·控制和状态寄存器
·CMPA,CMPAM,CMPAHR,CMPAHRM和CMPB有active和shadow寄存器,是否启用shadow机
制由CMPCTL[SHDWAMODE]和CMPCTL[SHDWBMODE]控制,默认值是0,启动shadow。
a)如果SHDWAMODE/SHDWBMODE=1,不启动shadow(影子寄存器),读写直接访问active寄存器;
b)SHDWAMODE/SHDWBMODE=O,启动shadow机制,读写直接访问shadow寄存器。
·CMPCTL[LOADAMODE]与CMPCTL[LOADBMODE]用来选择在启动shadow模式的情况下,
shadow寄存器的值何时加载到active寄存器,包括
a)CTR=PRD b)CTR=Zero c)CTR=PRD和CTR=PRD
CMPA和CMPAM,CMPAHR和CMPAHRM分别互为mirror寄存器
根据输入事件,确定在某个事件发生时作出何种响应,从而产生所需的EPWMxA和EPWMxB。
处理过程:
输入事件选择
优先级判断
对输出进行控制
控制和状态寄存器
EPwm1
AQ输入事件选择
输入事件来自TB和CC子模块,包括:
1.CTR=PRD2.CTR=Zero 3.CTR=CMPA 4.CTR=CMPB 5.软件强制事件
·其中,事件CTR=CMPA和CTR=CMPB,根据计数器当时的状态为递增或递减,再细分为
CAU,CAD,CBU,CBD四个事件
·软件强制事件由控制寄存器AQSFRC和AQCSFRC控制,可以细分为一次触发OSF和连续软件触
发CSF两种软件强制事件;等于OO时,不使能CSF,根据控制寄存器AQSFRC进行判断是否触发
OSF;等于01/10时,触发CSF,将相应的EPWMA或EPWMB拉低或置位。
优先级判断
·向上向下计数:
A.CTR=0→TBPRD
软件强制事件处最高级,CBU、CAU、ZRO、CBD、CAD事件依次为2~6优先级
B.CTR=TBPRD→TBCTR=1
软件强制事件处于最高级,CBD、CAD、PRD、CBU、CAU事件依次为2~6优先级
·向上计数
软件强制事件处于最高级,PRD,CBU,CAU,ZRO事件依次为2~5优先级
·向下计数
软件强制事件处于最高级,ZRO,CBD,CAD,PRD事件依次为2~5优先级
AQ输出控制
·根据输入事件,并经过优先级判断,AQ模块能够在下一个TBCLK时,将EPWMxA或EPWMxB
的输出作出相应的响应,包括:
·1.不动作
2.输出EPWMxA和/或EPWMxB置高
3.输出EPWMxA和/或EPWMxB置低
4.翻转EPWMxA和/或EPWMxB
AQ的控制和状态寄存器
包括AQCTLA,AQCTLB,AQSFRC,AQCSFRC
·1.AQSFRC[OTSFA]与AQSFRC[OTSFB]写入1会使能单次触发OSF软件强制事件,触发强制事
件之后,下一个TBCLK时,自动清零。
·2.AQCSFRC有active和shadow寄存器。其具体行为由AQSFRC[RLDCSF]控制:
00-装载事件计数等于0,01-装载事件计数等于周期值
10-装载事件计数等于0或周期值11-立即装载事件
事件触发ET
步进电机运动时,一般会有加减速运动,这个事件触发ET派上用场
·管理由TB,CC和DC子模块产生的事件,当在选定事件生成时,产生中断给CPU,和/或产生开始转换的脉
冲给ADC。
主要功能:
·1、接收来自TB、CC和DC子模块产生的事件输入并配置使能;
·2、触发一条中断请求信号EPWMINT发送给PEI,两条ADC开始转换信号SOCA/SOCB,发送给ADC;
·3、通过TB模块计数器的方向信息判断是向上计数或向下计数;
·4、指定事件触发的频率:每次、每隔一次或每三次事件发生;
·5、轮询、设置或清除事件标志。
·6、通过事件计数器和标志位,事件生成完全可见;
·7、允许软件强制中断和ADC开始转换。
中断EPWMINT产生
ADC开始转换信号SOCA/B产生
中断EPWMINT产生
通过配置ETSEL[INTSEL]控制以下事件可以允许触发中断:
a)CTR=Zero b)CTR=PRLc)CTR=Zero或CTR=PRD
d)CTRU=CMPA:CTR=CMPA且CTR在递增 e)CTRD=CMPA:CTR=CMPA且CTR在递减
f)CTRU=CMPB:CTR=CMPB且CTR在递增 g)CTRD=CMPB:CTR=CMPB且CTR在递减
·另外,通过ETFRC[INT]可以强制触发ET中断。ETFRC[INT]只在中断使能ETSEL[INTEN]=1时能够触发中断,但无论中断是
否使能,ETFRC[INT]都会将中断标志位ETFLG[INT]置位。
·使用控制寄存器ETPS[INTCNT]记录ETSEL[INTSEL]所指定事件发生的次数。
·控制寄存器ETPS[INTPRD]控制触发中断的频率,可以控制在事件发生一次,或两次,或三次时触发一次中断;若
ETPS[INTPRD]=0,则计数器不使能,无事件能够检测到,ETSFRC[INT]也被忽略不会触发中断;
a)当ETPS[INTCNT]增加到等于ETPS[INTPRD]时,计数停止。此时,如果中断被使能,且中断标记位未置位ETFLG[INT]=O,
则触发中断发送给PIE,置位中断标记位ETFLG[INT];
b)如果当ETPS[INTCNT]等于ETPS[INTPRD]时,中断使能,但其标记位已经置位,则计数器保持其值直到中断标记位被清零。
c)如果ETPS[INTCNT]等于ETPS[INTPRD]时,中断没有使能,或中断标记位已经被置位,则计数器暂停计数。
当中断标志未置位,且中断使能,且ETPS[INTPRD]不等于O时,如果ETFRC[INT]强制触发,或ETPS[INTCNT]等于
ETPS[INTPRD],或写等于ETPS[INTCNT]当前计数值到ETPS[INTPRD],会触发中断。
ADC开始转换信号SOCA/B产生
·可以配置ETSEL「SOCASEL1,确定可以触发SOCA脉冲的事件,除了那些能够产生中断的事件外,
还有来自DC子模块的DCAEVT1.soc事件可以触发SOCA。
ETPS[SOCAONT]计数器和ETPS[SOCAPRD]的行为与中断EPWMINT产生的机制非常类似,
不同处在于脉冲是连续产生的;当脉冲产生时,脉冲标志位ETFLG[SOCA]被锁存,但它不会阻
止后续的脉冲产生。ETSEL[SOCAEN]用于控制是否使能产生脉冲,但是输入事件依然能被计数,
直到计数器ETPS[SOCACNT]达到周期值ETPS[SOCAPRD]。
SOCB产生机制与SOCA相同。
Epwm死区DB
用于多路晶闸管或MOSFET/IGBT的上下桥臂延迟互补波形输出,避免管子在导通/关断过程中造
成直通(上下桥臂同时置高)
处理过程:
输入选择交叉通路
边沿延迟控制
输出选择
输入选择交叉通路
·通过DBCTL[IN_MODE]控制
·00EPWMxA在上升沿与下降沿边缘处均有延迟
·01EPWMxB在上升沿边缘处有延迟,EPWMxA在下降沿边缘处有延迟
·10EPWMxA在上升沿边缘处有延迟,EPWMxB在下降沿边缘处有延迟
11EPWMxB在上升沿与下降沿边缘处均有延迟
边沿延迟控制
·通过DBCTL[HALFCYCLE]可以选择所使用的时钟,TBCLK或TBCLK2X,当
DBCTL[HALFCYCLE]=1时,选择TBCLK2X,从而实现双分辨率的延迟控制
·延迟周期由DBRED与DBFED控制
·死区时间计算:FED=DBFEDTTBCLK/2 RED=DBREDTTBCLK/2
输出选择
·通过DBCTL[POLSEL]位实现对极性的控制,是否对边沿延迟后的EPWMA和EPWMB进行相位取反的控制。
A.00置高EPWMxA或EPWMxB中一路取反
B.01置低互补EPWMxA取反
C.10置高互补EPWMxB取反
D.11置低EPWMxA与EPWMxB均取反
·通过DBCTL[OUT_MODE]位实现对输出交叉通路的控制。当DBCTL[OUT_MODE]=00时,DB子模块可以完全
被bypass,在这种情况下,EPWM波形不受DB子模块的影响。
A.00无影响
B.01屏蔽上升沿延迟,通过DBCTL[IN_MODE]控制下降沿延迟出现在EPWMxB
C.10通过DBCTL[IN_MODE]控制在EPWMxA产生上升沿延迟输出
D.11通过DBCTL[IN_MODE]控制在EPWMxA输出产生上升沿延迟,在EPWMxB输出产生下降沿延迟
错误联防TZ
·可以通过编程,配置在发生外部故障或满足跳闸条件时,ePWM模块的输出作出相应的响应,这些条件
包括:TZ1~TZ6(低电平有效),数字比较DC子模块产生的强制事件DCAEVT1/2或DCBEVT1/2.
·TZ1TZ6的来源分别为:TZ1TZ3来源于GPIO MUX;TZ4来源于EQEP1模块的EQEP1ERR反向信
号;TZ5来源于系统时钟故障逻辑CLOCKFAIL的反向信号;TZ6来源于CPU的EMUSTOP输出。
·TZ子模块的主要功能:
1.TZ1~TZ6或DC强制事件可以被灵活地配置,映射到任何ePWM模块。
2.由TZCTL寄存器配置ePWM模块对TZn、DC强制事件中的一个,或全部作出响应,或均不做出响应,
响应可以是强制EPWMxA和/或EPWMxB的状态为高,低,高阻态,或无响应。
3.基于片上模拟比较器模块的输出和/或TZ1至TZ3信号的状态,支持数字比较DC trip。
4.可以配置ePWM对TZ信号做出响应的频率,分为:单次触发OSHT和周期循环触发CBC
5.支持软件强制trip
6.使能TZ触发中断
7.TZ模块可以完全被bypass。
错误联防TZ详讲
·Trip事件及处理方式
可以配置控制寄存器TZSEL选择TZ1~TZ6触发周期循环CBC事件或单次触发OSHT事件;DCAEVT1、
DCBEVT1可以直接触发trip或者触发OSHT事件;DCAEVT2、DCBEVT2可以直接触发trip或者触发周期循
环CBC事件。
1.周期循环触发CBC事件
2.单次触发OSHT事件
3.DC事件
4.Trip事件的优先级处理
多个trip事件发生时,优先级如下:
A. EPWMA: TZA>DCAEVT1>DCAEVT2
B. EPWMB: TZB>DCBEVT1>DCBEVT2
●中断触发
·控制寄存器
周期循环触发CBC事件
·可以用来限制电流
·由控制寄存器TZSEL中对应位控制TZ1~TZ6(低电平有效)或DC子模块的DCAEVT2、
DCBEVT2可以选择触发CBC事件,也可使用控制寄存器TZFRC[CBC]强制触发。
·CBC发生后,CBC trip事件标志位TZFLG[CBC]置位;CBC事件在TBCTR=OxO000时,如果其
触发事件已经结束,则自动清除CBC事件,但标志位TZFLG[CBC]需要手动写TZCLR[CBC]才可
清零。
·根据控制寄存器TZCTL[TZA]/TZCTL[TZB],EPWMxA/B输出即刻作出相应响应:高,低,高阻
态,或无响应;
·如果在TZEINT和PIE外设中使能了CBC,则产生EPWMX_TZINT中断。
单次触发OSHT事件
·用来应对严重的短路或过流情况
·由控制寄存器TZSEL中对应位控制TZ1~TZ6(低电平有效)或DC子模块的DCAEVT1、
DCBEVT1可以选择触发OSHT事件,也可使用控制寄存器TZFRC[OST]强制触发。
·OSHT发生后,OSHT trip事件标志位TZFLG[OST]置位;OST事件不会随触发条件无效而无效,
同时其标识位TZFLG[OST]也一直有效,直到手动写TZCLR[OST]才可清除。
·根据控制寄存器TZCTL[TZA]/TZCTL[TZB],EPWMxA/B输出即刻作出相应响应:高,低,高阻
态,或无响应;
·如果在TZEINT和PIE外设中使能了OST,则产生EPWMx_TZINT中断。
DC事件
·包括DCAEVT1、DCBEVT1和DCAEVT2、DCBEVT2,均可以直接触发tripEPWM
·DC事件发生后,根据控制寄存器TZCTL[DCAEVT1/2]或TZCTL[DCBEVT1/2]中所配置的,
EPWMxA/B输出即刻作出相应响应:高、低、高阻态,或无响应。
·DC trip事件标志位(TZFLG[DCAEVT1/2]/TZFLG[DCBEVT1/2])置位;当DC事件结束时,DC
trip触发的条件会自动清零,但标志位TZFLG[DCAEVT1/2]或TZFLG[DCBEVT1/2]需要手动写
TZCLR[DCAEVT1/2]或TZCLR[DCBEVT1/2]才可清零。
·如果在TZEINT和PIE外设中使能DCAEVT1/2或DCBEVT1/2,则产生EPWMX_TZINT中断。
中断触发
·通过控制寄存器TZEINT可以使能TZ触发中断。
·当中断使能的事件发生后,会拉低EPWMxTZINT(维持一个系统时钟SYSCLKOUT的周期),
发送给PIE进行中断处理。
·同时,会将TZFLG[INT]置位,表示曾触发过中断。TZFLG[INT]需要手动写控制寄存器
TZCLR[INT]才能清零,在其被清零之前,会一直阻止后续的中断产生。
·另外,手动写TZCLR清除所有的TZFLG也可以阻止后续中断的产生。
EPWM头文件
代码部分
epwm.c文件
#include "epwm.h"
EPWM_INFO epwm1_info;
EPWM_INFO epwm2_info;
EPWM_INFO epwm3_info;
#define EPWM1_TIMER_TBPRD 2000
#define EPWM1_MAX_CMPA 1950
#define EPWM1_MIN_CMPA 50
#define EPWM1_MAX_CMPB 1950
#define EPWM1_MIN_CMPB 50
#define EPWM2_TIMER_TBPRD 2000
#define EPWM2_MAX_CMPA 1950
#define EPWM2_MIN_CMPA 50
#define EPWM2_MAX_CMPB 1950
#define EPWM2_MIN_CMPB 50
#define EPWM3_TIMER_TBPRD 2000
#define EPWM3_MAX_CMPA 950
#define EPWM3_MIN_CMPA 50
#define EPWM3_MAX_CMPB 1950
#define EPWM3_MIN_CMPB 1050
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
//DB_INFO
#define EPWM1_MAX_DB 0x03E8
#define EPWM2_MAX_DB 0x03E8
#define EPWM3_MAX_DB 0x03E8
#define EPWM1_MIN_DB 0
#define EPWM2_MIN_DB 0
#define EPWM3_MIN_DB 0
#define DB_UP 1
#define DB_DOWN 0
/******************************************************************
*函数名:void InitEpwm1_Example(void)
*参 数:无
*返回值:无
*作 用:初始化Epwm1
******************************************************************/
void InitEPwm1Example()
{
/* Period = 4000*TBCLK counts*/
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;
/*epwm时基计数器相位=0*/
EPwm1Regs.TBPHS.half.TBPHS = 0x0000;
/*当时基计数器等于零(TBCTR = 0x0000)时,影子寄存器的内容将传输到活动寄存器TBPRD(活 动)←TBPRD(影子)*/
EPwm1Regs.TBCTR = 0x0000;
/*设置CMPA值为EPWM1_MAX_CMPA*/
EPwm1Regs.CMPA.half.CMPA = EPWM1_MAX_CMPA;
/*设置CMPB值为EPWM1_MAX_CMPB*/
EPwm1Regs.CMPB = EPWM1_MAX_CMPB;
/*增减计数模式*/
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
/*禁止TBCTR加载相位寄存器TBPHS中的值*/
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
/*高速时钟分频 1倍分频*/
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
/*时基时钟分频 1倍分频*/
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
/*CMPA寄存器工作模式选择:映射模式*/
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
/*CMPB寄存器工作模式选择:映射模式*/
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
/*当TBCTR=0x0000时,CMPA主寄存器从映射寄存器中加载数据*/
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
/*当TBCTR=0x0000时,CMPB主寄存器从映射寄存器中加载数据*/
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
/*当时间基准计数器的值等于CMPA的值,且正在增计数时,使EPWMxA输出高电平*/
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
/*当时间基准计数器的值等于CMPA的值,且正在减计数时,使EPWMxA输出低电平*/
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;
/*当时间基准计数器的值等于CMPB的值,且正在增计数时,使EPWMxB输出高电平*/
EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;
/*当时间基准计数器的值等于CMPB的值,且正在减计数时,使EPWMxB输出低电平*/
EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR;
/*选择EPWMx_INT产生的条件:TBCTR=0x0000时产生*/
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
/*使能产生中断信号EPWMx_INT*/
EPwm1Regs.ETSEL.bit.INTEN = 1;
/*ePWM中断(EPWMx_INT)周期选择:每发生三次事件产生中断信号EPWMx_INT*/
EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;
/*使能上升沿和下降沿延时信号*/
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
/*主低模式:EPWMxA和EPWMxB都反转极性*/
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_LO;
/*EPWMxA作为上升沿和下降沿时的信号源*/
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
/* 死区上升沿延时计数器*/
EPwm1Regs.DBRED = EPWM1_MIN_DB;
/*死区下降沿延时计数器*/
EPwm1Regs.DBFED = EPWM1_MIN_DB;
epwm1_info.EPwm1_DB_Direction = DB_UP;
EALLOW;
/* 使能TZ3作为ePWM的单次故障保护触发输入*/
EPwm1Regs.TZSEL.bit.OSHT3 = 1;
/*当外部触发事件发生时,强制EPWMxA为高电平*/
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_HI;
/*当外部触发事件发生时,强制EPWMxA为低电平*/
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
/*允许单次触发事件产生中断*/
EPwm1Regs.TZEINT.bit.OST = 1;
EDIS;
epwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;
epwm1_info.EPwmTimerIntCount = 0;
epwm1_info.EPwmRegHandle = &EPwm1Regs;
epwm1_info.EPwmMaxCMPA = EPWM1_MAX_CMPA;
epwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;
epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;
epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;
}
/******************************************************************
*函数名:void InitEpwm2_Example(void)
*参 数:无
*返回值:无
*作 用:初始化Epwm2
******************************************************************/
void InitEPwm2Example()
{
/* Period = 4000*TBCLK counts*/
EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD;
/*epwm时基计数器相位=0*/
EPwm2Regs.TBPHS.half.TBPHS = 0x0000;
/*当时基计数器等于零(TBCTR = 0x0000)时,影子寄存器的内容将传输到活动寄存器(TBPRD(活 动)←TBPRD(影子))*/
EPwm2Regs.TBCTR = 0x0000;
/*设置CMPA值为EPWM2_MIN_CMPA*/
EPwm2Regs.CMPA.half.CMPA = EPWM2_MIN_CMPA;
/*设置CMPB值为EPWM2_MAX_CMPB*/
EPwm2Regs.CMPB = EPWM2_MAX_CMPB;
/*增减计数模式*/
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
/*禁止TBCTR加载相位寄存器TBPHS中的值*/
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
/*高速时钟分频 1倍分频*/
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
/*时基时钟分频 1倍分频*/
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
/*CMPA寄存器工作模式选择:映射模式*/
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
/*CMPB寄存器工作模式选择:映射模式*/
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
/*当TBCTR=0x0000时,CMPA主寄存器从映射寄存器中加载数据*/
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
/*当TBCTR=0x0000时,CMPA主寄存器从映射寄存器中加载数据*/
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
/*当时间基准计数器的值等于CMPA的值,且正在增计数时,使EPWMxA输出高电平*/
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;
/*当时间基准计数器的值等于CMPB的值,且正在减计数时,使EPWMxB输出低电平*/
EPwm2Regs.AQCTLA.bit.CBD = AQ_CLEAR;
/*时基计数器等于零时,强制 EPWMxA 输出低电平*/
EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
/*时基计数器等于 PRD 时,强制 EPWMxA 输出为高电平*/
EPwm2Regs.AQCTLB.bit.PRD = AQ_SET;
/*时基计数器等于零时产生,ePWM 中断*/
EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
/*使能 EPWMx_INT 生成*/
EPwm2Regs.ETSEL.bit.INTEN = 1;
/*在 ETPS [INTCNT] = 1,1 上产生中断(第三个事件)*/
EPwm2Regs.ETPS.bit.INTPRD = ET_3RD;
/*对于输出 EPWMxA 的上升沿延迟和输出 EPWMxB 的下降沿延迟,完全启用了死区*/
EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
/*有源低互补(ALC)模式。 EPWMxA 被反相*/
EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
/*EPWMxA作为下降沿和上升沿延迟的信号源*/
EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
/*设置上升沿延迟*/
EPwm2Regs.DBRED = EPWM2_MIN_DB;
/* 设置下降沿延迟*/
EPwm2Regs.DBFED = EPWM2_MIN_DB;
epwm2_info.EPwm2_DB_Direction = DB_UP;
EALLOW;
/*启用 TZ2 作为此 ePWM 模块的 CBC 跳闸源*/
EPwm2Regs.TZSEL.bit.CBC2 = 1;
/*发生跳闸事件时,强制 EPWMxA 进入高电平*/
EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_HI;
/*发生跳闸事件时,将 EPWMxB 强制为低电平*/
EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
/*跳闸区域逐周期中断使能*/
EPwm2Regs.TZEINT.bit.CBC = 1;
EDIS;
epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_UP;
epwm2_info.EPwmTimerIntCount = 0;
epwm2_info.EPwmRegHandle = &EPwm2Regs;
epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA;
epwm2_info.EPwmMinCMPA = EPWM2_MIN_CMPA;
epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB;
epwm2_info.EPwmMinCMPB = EPWM2_MIN_CMPB;
}
/******************************************************************
*函数名:void InitEpwm3_Example(void)
*参 数:无
*返回值:无
*作 用:初始化Epwm3
******************************************************************/
void InitEPwm3Example()
{
/* Period = 4000*TBCLK counts*/
EPwm3Regs.TBPRD = EPWM3_TIMER_TBPRD;
/*epwm时基计数器相位=0*/
EPwm3Regs.TBPHS.half.TBPHS = 0x0000;
/*当时基计数器等于零(TBCTR = 0x0000)时,影子寄存器的内容将传输到活动寄存器(TBPRD(活 动)←TBPRD(影子))*/
EPwm3Regs.TBCTR = 0x0000;
/*设置CMPA值为EPWM3_MIN_CMPA*/
EPwm3Regs.CMPA.half.CMPA = EPWM3_MIN_CMPA;
/*设置CMPA值为EPWM3_MAX_CMPB*/
EPwm3Regs.CMPB = EPWM3_MAX_CMPB;
/*增减计数模式*/
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
/*禁止TBCTR加载相位寄存器TBPHS中的值*/
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE;
/*高速时钟分频 1倍分频*/
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
/*时基时钟分频 1倍分频*/
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
/*CMPA寄存器工作模式选择:映射模式*/
EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
/*CMPB寄存器工作模式选择:映射模式*/
EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
/*当TBCTR=0x0000时,CMPA主寄存器从映射寄存器中加载数据*/
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
/*当TBCTR=0x0000时,CMPA主寄存器从映射寄存器中加载数据*/
EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
/*时基计数器等于 PRD 时,强制 EPWMxA 输出为高电平*/
EPwm3Regs.AQCTLA.bit.PRD = AQ_SET;
/*当时间基准计数器的值等于CMPB的值,且正在减计数时,使EPWMxB输出低电平*/
EPwm3Regs.AQCTLA.bit.CBD = AQ_CLEAR;
/*时基计数器等于 PRD 时,强制 EPWMxB 输出为低电平。*/
EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR;
/*当时间基准计数器的值等于CMPA的值,且正在增计数时,使EPWMxB输出高电平*/
EPwm3Regs.AQCTLB.bit.CAU = AQ_SET;
/*时基计数器等于零时产生,ePWM 中断*/
EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
/*使能 EPWMx_INT 生成*/
EPwm3Regs.ETSEL.bit.INTEN = 1;
/*在 ETPS [INTCNT] = 1,1 上产生中断(第三个事件)*/
EPwm3Regs.ETPS.bit.INTPRD = ET_3RD;
/*对于输出 EPWMxA 的上升沿延迟和输出 EPWMxB 的下降沿延迟,完全启用了死区*/
EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
/*主动高互补(AHC)。 EPWMxB 被反相。*/
EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
/* EPWMxA作为下降沿和上升沿延迟的信号源。*/
EPwm3Regs.DBCTL.bit.IN_MODE = DBA_ALL;
/*设置上升沿延迟*/
EPwm3Regs.DBRED = EPWM3_MIN_DB;
/*设置下降沿延迟*/
EPwm3Regs.DBFED = EPWM3_MIN_DB;
epwm3_info.EPwm3_DB_Direction = DB_UP;
epwm3_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm3_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;
epwm3_info.EPwmTimerIntCount = 0;
epwm3_info.EPwmRegHandle = &EPwm3Regs;
epwm3_info.EPwmMaxCMPA = EPWM3_MAX_CMPA;
epwm3_info.EPwmMinCMPA = EPWM3_MIN_CMPA;
epwm3_info.EPwmMaxCMPB = EPWM3_MAX_CMPB;
epwm3_info.EPwmMinCMPB = EPWM3_MIN_CMPB;
}
epwm.h文件
#ifndef epwm_h_
#define epwm_h_
#include "dsc_config.h"
typedef struct
{
volatile struct EPWM_REGS *EPwmRegHandle;
uint16_t EPwm_CMPA_Direction;
uint16_t EPwm_CMPB_Direction;
uint16_t EPwmTimerIntCount;
uint16_t EPwmMaxCMPA;
uint16_t EPwmMinCMPA;
uint16_t EPwmMaxCMPB;
uint16_t EPwmMinCMPB;
uint16_t EPwm1_DB_Direction;
uint16_t EPwm2_DB_Direction;
uint16_t EPwm3_DB_Direction;
bool EPwm1TZFlag;
bool EPwm2TZFlag;
} EPWM_INFO;
void InitEPwm1Example(void);
void InitEPwm2Example(void);
void InitEPwm3Example(void);
void INTERRUPT epmw1_isr(void);
void INTERRUPT epmw2_isr(void);
void INTERRUPT epmw3_isr(void);
void INTERRUPT epwm1_tz_isr(void);
void INTERRUPT epwm2_tz_isr(void);
void InitLED(void);
void update_compare(EPWM_INFO*);
extern EPWM_INFO epwm1_info;
extern EPWM_INFO epwm2_info;
extern EPWM_INFO epwm3_info;
#endif/*epwm_h_*/
epwm_update.c文件
#include "epwm.h"
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
extern uint16 DebugCount;
/******************************************************************
*函数名:void update_compare(EPWM_INFO *epwm_info)
*参 数:无
*返回值:无
*作 用:改变pwm占空比
******************************************************************/
void update_compare(EPWM_INFO *epwm_info)
{
if (epwm_info->EPwmTimerIntCount >= 10)
{
epwm_info->EPwmTimerIntCount = 0;
if (epwm_info->EPwm_CMPA_Direction == EPWM_CMP_UP)
{
if (epwm_info->EPwmRegHandle->CMPA.half.CMPA < epwm_info->EPwmMaxCMPA)
{
epwm_info->EPwmRegHandle->CMPA.half.CMPA++;
}
else
{
epwm_info->EPwm_CMPA_Direction = EPWM_CMP_DOWN;
epwm_info->EPwmRegHandle->CMPA.half.CMPA--;
}
}
else
{
if (epwm_info->EPwmRegHandle->CMPA.half.CMPA <= epwm_info->EPwmMinCMPA)
{
epwm_info->EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm_info->EPwmRegHandle->CMPA.half.CMPA++;
}
else
{
epwm_info->EPwmRegHandle->CMPA.half.CMPA--;
}
}
if (epwm_info->EPwm_CMPB_Direction == EPWM_CMP_UP)
{
if (epwm_info->EPwmRegHandle->CMPB < epwm_info->EPwmMaxCMPB)
{
epwm_info->EPwmRegHandle->CMPB++;
}
else
{
epwm_info->EPwm_CMPB_Direction = EPWM_CMP_DOWN;
epwm_info->EPwmRegHandle->CMPB--;
}
}
else
{
if (epwm_info->EPwmRegHandle->CMPB <= epwm_info->EPwmMinCMPB)
{
epwm_info->EPwm_CMPB_Direction = EPWM_CMP_UP;
epwm_info->EPwmRegHandle->CMPB++;
}
else
{
epwm_info->EPwmRegHandle->CMPB--;
}
}
}
else
{
epwm_info->EPwmTimerIntCount++;
}
return;
}
epwm_int.c 文件中断服务函数
#include "epwm.h"
//DB_INFO
#define EPWM1_MAX_DB 0x03FF
#define EPWM2_MAX_DB 0x03FF
#define EPWM3_MAX_DB 0x03FF
#define EPWM1_MIN_DB 0
#define EPWM2_MIN_DB 0
#define EPWM3_MIN_DB 0
#define DB_UP 1
#define DB_DOWN 0
/******************************************************************
*函数名:void INTERRUPT epwm1_isr(void)
*参 数:无
*返回值:无
*作 用:中断服务函数改变pwm死区
******************************************************************/
void INTERRUPT epmw1_isr(void)
{
update_compare(&epwm1_info);
if (epwm1_info.EPwm1_DB_Direction == DB_UP)
{
if (EPwm1Regs.DBFED < EPWM1_MAX_DB)
{
EPwm1Regs.DBFED++;
EPwm1Regs.DBRED++;
}
else
{
epwm1_info.EPwm1_DB_Direction = DB_DOWN;
EPwm1Regs.DBFED--;
EPwm1Regs.DBRED--;
}
}
else
{
if (EPwm1Regs.DBFED == EPWM1_MIN_DB)
{
epwm1_info.EPwm1_DB_Direction = DB_UP;
EPwm1Regs.DBFED++;
EPwm1Regs.DBRED++;
}
else
{
EPwm1Regs.DBFED--;
EPwm1Regs.DBRED--;
}
}
epwm1_info.EPwmTimerIntCount++;
EPwm1Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;//中断服务函数的3组
}
/******************************************************************
*函数名:void INTERRUPT epwm2_isr(void)
*参 数:无
*返回值:无
*作 用:中断服务函数改变pwm死区
******************************************************************/
void INTERRUPT epmw2_isr(void)
{
update_compare(&epwm2_info);
if (epwm2_info.EPwm1_DB_Direction == DB_UP)
{
if (EPwm2Regs.DBFED < EPWM1_MAX_DB)
{
EPwm2Regs.DBFED++;
EPwm2Regs.DBRED++;
}
else
{
epwm2_info.EPwm1_DB_Direction = DB_DOWN;
EPwm2Regs.DBFED--;
EPwm2Regs.DBRED--;
}
}
else
{
if (EPwm2Regs.DBFED == EPWM1_MIN_DB)
{
epwm2_info.EPwm1_DB_Direction = DB_UP;
EPwm2Regs.DBFED++;
EPwm2Regs.DBRED++;
}
else
{
EPwm2Regs.DBFED--;
EPwm2Regs.DBRED--;
}
}
epwm2_info.EPwmTimerIntCount++;
EPwm2Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
/******************************************************************
*函数名:void INTERRUPT epwm3_isr(void)
*参 数:无
*返回值:无
*作 用:中断服务函数改变pwm死区
******************************************************************/
void INTERRUPT epmw3_isr(void)
{
update_compare(&epwm3_info);
if (epwm3_info.EPwm1_DB_Direction == DB_UP)
{
if (EPwm3Regs.DBFED < EPWM1_MAX_DB)
{
EPwm3Regs.DBFED++;
EPwm3Regs.DBRED++;
}
else
{
epwm3_info.EPwm1_DB_Direction = DB_DOWN;
EPwm3Regs.DBFED--;
EPwm3Regs.DBRED--;
}
}
else
{
if (EPwm3Regs.DBFED == EPWM1_MIN_DB)
{
epwm3_info.EPwm1_DB_Direction = DB_UP;
EPwm3Regs.DBFED++;
EPwm3Regs.DBRED++;
}
else
{
EPwm3Regs.DBFED--;
EPwm3Regs.DBRED--;
}
}
epwm3_info.EPwmTimerIntCount++;
EPwm3Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
epwm_tz.c
#include "epwm.h"
/******************************************************************
*函数名:void INTERRUPT epwm1_tz_isr()
*参 数:无
*返回值:无
*作 用:中断服务函数
******************************************************************/
void INTERRUPT epwm1_tz_isr(void)
{
epwm1_info.EPwm1TZFlag = true;
GpioDataRegs.GPACLEAR.bit.GPIO6 = 1;
// EALLOW;
// /*清除单次触发事件标志位*/
// EPwm1Regs.TZCLR.bit.OST = 1;
// /*清除中断标志位*/
// EPwm1Regs.TZCLR.bit.INT = 1;
// EDIS;
/*PIE中断应答*/
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}
/******************************************************************
*函数名:void INTERRUPT epwm2_tz_isr()
*参 数:无
*返回值:无
*作 用:中断服务函数
******************************************************************/
void INTERRUPT epwm2_tz_isr(void)
{
epwm2_info.EPwm2TZFlag = true;
EALLOW;
/*清除周期性触发事件标志位*/
EPwm2Regs.TZCLR.bit.CBC = 1;
/*清除中断标志位*/
EPwm2Regs.TZCLR.bit.INT = 1;
EDIS;
/* PIE中断应答*/
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}
最后
以上就是无情曲奇为你收集整理的中科昊芯DSP_RISC-V笔记(4)_PWM事件触发Epwm讲解的全部内容,希望文章能够帮你解决中科昊芯DSP_RISC-V笔记(4)_PWM事件触发Epwm讲解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复