|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1.PWM输出配置步骤1 @( f( |0 z6 ]6 m; d# c: l: j% ]
EPWM相关库函数在DSP2833x_EPwm.c和DSP2833x_EPwm.h文件中。
, D+ h6 _$ L' E" N: j(1)开启ePWM外设时钟及失能时基模块时钟
8 u, W! K4 ~: Z( `* b* R7 l( x使用ePWM外设需开启相应时钟,在对ePWM相关寄存器配置时需要先关闭时基模块时钟,待配置好后再开启,可以保证同步。
, i& m* q; c8 e% P, @' p0 b; B& D) a' u1 Z* q# Y8 R& o% D
EALLOW; h6 x( Q5 d3 q1 b
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM要保证时基同步的话,首先在配置TB/CC寄存器时先把时钟关闭,即所有TBCLK停止,不产生。等全部配置后之后再打开,保证时钟同步
# F) m3 C$ j- f: v4 N2 S. f0 l SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // 开启ePWM1外设时钟; A" l5 V. |, v" F; X& A8 B
EDIS;+ ]- \/ |2 ^2 v; G; u' c/ K
5 ]6 d5 [- s: e1 G# k* w9 i
(2)开启ePWM对应GPIO时钟及初始化配置, C0 \' F' c- W8 ]2 V& r: B
PWM输出通道对应F28335的IO口,所以需要使能对应的端口时钟,并将对应的IO口配置为ePWM输出功能。这里使用GPIO10、GPIO11的ePWM6A和ePWM6B功能,即对这两个IO口初始化,使能上拉和GPIO外设复用功能。6 h( o' _6 p2 }6 i$ p
. S: w l* ~% U& M* M
InitEPwm6Gpio();//开启时钟,对应ePWM复用功能的开启
" M4 s% J* }. z' v1
& s: j1 R! q5 {8 C l9 Q(3)初始化时基模块,即配置TB相关寄存器值(确定计数方式、周期、相位)
2 Y0 G4 ~( u" V; u通过配置时基模块,可以确定计数器的计数方式,周期频率,是否同步等。这里设置ePWM6计数方式为向上计数,不使用相位同步功能,计数器计数频率为系统时钟频率,计数器初值为0。8 l0 }3 Z x5 H* u" v' O
) @0 V# N w2 t- j0 g// Setup Sync: e( {: K! E- D& _# j/ C
EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 禁止(即不使用(输出))ePWMxSYNCO信号
" I3 U, C. r8 e$ G5 y* ^ // Allow each timer to be sync'ed0 ?2 j( r; p. ^( \/ V) d
EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁止TBCTR加载相位寄存器TBPHS中的值
% l2 L8 G; a u8 f EPwm6Regs.TBPHS.half.TBPHS = 0;//将相位寄存器中的值清零# ~* ^$ {6 ]% h* E, H3 s
EPwm6Regs.TBCTR = 0x0000; // Clear counter时间基准计数寄存器设置为0
1 h* e$ g/ [- ?! ?3 d EPwm6Regs.TBPRD = tbprd;//设定周期值. \4 R+ [/ u7 \
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up向上计数模式 T) y4 G5 D R/ a
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//采用系统时钟作为TBCLK7 L9 I0 `) x& E1 C& h: e1 K
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;//同样是配置TBCLK的时钟' T" D, H b$ |( M0 ?0 g& T4 ^ ]
4 M/ o" ]3 v9 t4 ?* z7 z
(4)初始化比较模块,配置CC相关寄存器4 ~ ^1 {% [ O7 v% ]' Q$ f
通过配置CC模块,可以确定比较寄存器值的加载方式,比较器值、占空比等。这里设置ePWM6加载方式为计数器为0加载、比较器值为0。( [: B/ m/ l5 Z/ W
8 p/ e+ D& ], u3 K! k+ t6 U5 D// Setup shadow register load on ZERO, M3 J! i1 @9 z3 K
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;// 使用影子寄存器" C3 q$ {5 ^: W0 K
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;// 使用影子寄存器1 c1 m T* B$ ?7 I
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;//CTR等于0时加载
9 s1 I8 }# ?0 } EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
9 }8 l2 C" P4 v d" r
- a" Y. ?" j8 E; g* H // Set Compare values0 D' B, c, O. v/ Y" x0 a
EPwm6Regs.CMPA.half.CMPA = 0; // Set compare A value& F* W! f7 R1 W& z6 N
EPwm6Regs.CMPB = 0; // Set Compare B value
) L( d7 V# r8 I2 V7 w& p1 H* v1 Q8 D& A0 z% Y
(5)初始化动作限定模块,配置AQ相关寄存器值/ r5 P4 j- d) G* o$ C% ^' z
通过配置AQ模块可以确定PWM输出波形方式等。这里配置ePWM6输出,当ePWMA计数器计数到0时输出低电平,当ePWMA计数器计数到CMPA时输出高电平;当ePWMB计数器计数到0时输出低电平,当ePWMB计数器计数到CMPA时输出高电平。0 {% a8 u5 T0 I* Z
. T# P* X' H% O8 T% T8 E// Set actions
) @) t6 K4 I6 a4 G$ X% O$ q$ a EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Set PWM1A on Zero! i! e! h* G. _( x4 O* m. A* M
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // Clear PWM1A on event A, up count: {4 g G3 v" z5 z/ W" p
EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Set PWM1B on Zero$ L! Q M7 v" k
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET; // Clear PWM1B on event B, up count6 h, Y* Q$ `- O" H2 z. i) G) x
2 }4 i k' ?& u, D9 L' c
$ m3 @0 Q5 D, f: `8 j! |5 H
(6)初始化事件触发模块,即配置ET相关寄存器值6 ^4 x v2 e2 G$ P- S" c8 R
当需要事件触发输出控制,就需要对ET相关寄存器配置。这里选择计数器计数到0时,同时使能事件触发中断,每发生一次触发事件就输出PWM。
9 K1 C' ]# s/ O% z. i
, `) w& V2 o- x EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event/ L/ U& B; r# t$ p4 H
EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT3 G/ H, O$ ]$ S. C" L. U/ A' I
EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event每发生一次事件产生中断信号EPWM6_INT
% D! C2 T: ?# }% N% j/ j2 j- g! i/ r D
(7)初始化死区模块、斩波模块,即配置DB、PC相关寄存器值5 h2 b( {% P4 {
一般不对死区和斩波模块进行配置。) j" E3 z5 A1 q, K$ U
(8)使能时基计数器时钟
- Q' v9 w" G2 d+ K% L各模块寄存器配置好后,最后开启时基计数器时钟,完成这一步,对应IO口便可以输出PWM波9 [% b* a# ~0 b0 R
, u c W9 X$ Y) c% eEALLOW;
) d* i5 E9 i% s6 d- w' h& O; V SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced
7 h, F2 F5 D5 Q" u1 Q EDIS;
0 G; U6 W$ f4 }* Q+ r6 t' k4 x" h7 F# a0 x) m
2.通过ePWM6A和ePWM6B两个管脚输出PWM波,分别控制D6和D7指示灯亮度
" @/ i T# B1 t0 t. i! t主函数代码如下所示- i; `2 ?- J* @& ~3 j) }
1 _5 _. E8 n- n7 S7 O0 `
#include "DSP2833x_Device.h" // DSP2833x HeadeRFile Include File
, R9 k7 p `+ e+ Q#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
7 C- k% c( c a2 d' t
9 |0 w m) y$ M* ]7 i) U- R#include "leds.h") O6 V" F# v' Y) W
#include "time.h"//在定时器中控制灯的闪烁+ u2 T6 u" `' a
#include "epwm.h"//存放PWM的驱动程序7 d; ^2 P d; X% p9 a2 W
void main()7 l% F; g# U, }. z
{/ C+ V) b9 ]. t6 W2 L& c
int i=0;: w/ v+ G1 o$ ^' a
unsigned char fx=0;//fx指示了一个方向0 m% T: l- i$ B' E% d
F& W$ H* K9 h' p# ~- ]# @# r+ G' D' L InitSysCtrl();
8 O( @4 Q% A7 B9 K8 v( g9 B1 \
1 I; _) @* F- C5 C% x- ` InitPieCtrl();
: L1 J+ [0 s2 ~! u; S2 q8 e+ r IER = 0x0000;) c2 H- t6 d+ U$ O1 N2 P' E3 \
IFR = 0x0000;; }9 F! ^ F/ } Y* s7 D* B( m
InitPieVectTable();5 q) p$ B' m1 A- {
# J ^& I9 d) S: M7 k+ v// LED_Init();
6 u, p' y2 f0 p8 V EPWM6_Init(500);//EPWM管脚也即控制了LED,也就是说周期值是500个系统时钟! {4 n! R j& O
# ?$ ]5 M8 j/ C6 L" g while(1)
9 z9 ^) ~2 R" I {
( Z3 V( Q# B7 T! R9 K2 ] if(fx==0)7 h% m# C) v$ K u& U, u7 Y
{
& d" ^3 f" m% j' {4 I; r i++;6 G; m) q' b; `, \2 N; i' F4 [
if(i==300)
6 I( H- w. r) R9 ]6 P! a/ B {
* H2 Q& m; V( z' g: G5 h$ Q fx=1;5 q8 i& p! ?4 p: O% T: v8 ]
}
( u/ A: W) Y; g8 H3 H6 }0 \ }
. g. s q4 ]9 G6 S6 K: } else9 B5 E: Y6 I1 a9 T+ e$ m, o4 c) F
{
7 c$ v6 T5 [# L# x4 e5 @; w i--;
q- B, k* s0 p if(i==0)
$ ]7 p4 k) W' w6 x9 } {$ n# o' c8 R1 ?% ?; H" c& K; z
fx=0;
+ y; L) T/ H# j- S- ~1 X }8 ~' k1 n) ]2 z/ D) f
}% r4 ~& {" @- a" ]0 Y5 `3 K6 p
EPwm6A_SetCompare(i); //i值最大可以取499,因为ARR最大值是499. ?: d9 ?' ^1 y
EPwm6B_SetCompare(300-i); //i值最大可以取499,因为ARR最大值是499.; j0 v0 W6 K9 c( [
DELAY_US(10*1000);
5 b. [ B) a- [ }
% @& u% W9 c% B/ f, i}
$ U5 X" H+ A5 l! ]
; h! S! r. L; }) a
! G' W3 [/ k! ~# ? |
|