我是靠谱客的博主 无情曲奇,最近开发中收集的这篇文章主要介绍中科昊芯DSP_RISC-V笔记(4)_PWM事件触发Epwm讲解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

中科昊芯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讲解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部