|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1.PWM输出配置步骤% _% f+ Z& y" q6 i8 X8 B
EPWM相关库函数在DSP2833x_EPwm.c和DSP2833x_EPwm.h文件中。! a3 V+ e; u" p) ^# i6 a# J9 a: p
(1)开启ePWM外设时钟及失能时基模块时钟( Q( d; l" R' X) b8 I( a, N j9 x
使用ePWM外设需开启相应时钟,在对ePWM相关寄存器配置时需要先关闭时基模块时钟,待配置好后再开启,可以保证同步。9 R6 E1 M; ~& P$ [. F7 `8 Z: Z1 r" N
2 n2 w$ l( |! f0 H; C! S
EALLOW;
' A/ }$ A+ E, B3 s SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM要保证时基同步的话,首先在配置TB/CC寄存器时先把时钟关闭,即所有TBCLK停止,不产生。等全部配置后之后再打开,保证时钟同步
3 i5 N% N' \& f4 @' P" `' t SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // 开启ePWM1外设时钟8 s$ v: |7 _/ \, V' n8 L l
EDIS;- C) C9 J( l& l/ B( J, b
3 ~, T( u4 i( h8 {(2)开启ePWM对应GPIO时钟及初始化配置
# }5 s- b( l: }+ {" gPWM输出通道对应F28335的IO口,所以需要使能对应的端口时钟,并将对应的IO口配置为ePWM输出功能。这里使用GPIO10、GPIO11的ePWM6A和ePWM6B功能,即对这两个IO口初始化,使能上拉和GPIO外设复用功能。
! E- A+ N* i. T, _* f
, h& u, e' r9 p) q+ ]7 X InitEPwm6Gpio();//开启时钟,对应ePWM复用功能的开启: E' I& k- S" V& A8 _1 T
1$ l' w; e% U2 n' r: f# l7 J. o: W
(3)初始化时基模块,即配置TB相关寄存器值(确定计数方式、周期、相位)0 m, C9 w9 I) k' H) O
通过配置时基模块,可以确定计数器的计数方式,周期频率,是否同步等。这里设置ePWM6计数方式为向上计数,不使用相位同步功能,计数器计数频率为系统时钟频率,计数器初值为0。- o) E! z1 M6 ?4 n% I5 C* l& C
" q* l# C0 P( B# f0 H1 w# u: Z) V8 T
// Setup Sync
; i; ~- D( t3 T. K EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 禁止(即不使用(输出))ePWMxSYNCO信号! {6 E& X% R3 J$ l: m8 g( @
// Allow each timer to be sync'ed
2 d8 _5 Y4 u1 c7 w EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁止TBCTR加载相位寄存器TBPHS中的值
& T! y v+ X% ]* g EPwm6Regs.TBPHS.half.TBPHS = 0;//将相位寄存器中的值清零
$ a/ R% [' p8 @; H EPwm6Regs.TBCTR = 0x0000; // Clear counter时间基准计数寄存器设置为0$ C1 @3 ^* z* r' E5 S, ~
EPwm6Regs.TBPRD = tbprd;//设定周期值
0 s ]2 C1 p. J$ f' C4 ^: A0 y EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up向上计数模式
( R0 ?. B: h, s* m% B EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//采用系统时钟作为TBCLK, M/ O6 f7 J* \% ^& `1 n8 u! i
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;//同样是配置TBCLK的时钟7 {4 a( a0 u2 C9 S
1 Y% @1 h( h; W6 u; }) T
(4)初始化比较模块,配置CC相关寄存器
8 [2 j% [4 R3 t通过配置CC模块,可以确定比较寄存器值的加载方式,比较器值、占空比等。这里设置ePWM6加载方式为计数器为0加载、比较器值为0。# E: K! l( T9 G6 [. B
+ _+ o. b# i. L' V! \
// Setup shadow register load on ZERO
0 i* [9 g8 P& ^/ _& K& C EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;// 使用影子寄存器
2 T9 z1 N6 a/ v* b6 q7 D EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;// 使用影子寄存器
/ {- p _% }, J EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;//CTR等于0时加载
( _/ D, b" t, y4 [) s/ W8 U$ b, H EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
0 T0 E( Q4 V2 m4 w0 s4 j
/ M! r' ~4 ]/ H6 O+ m // Set Compare values
5 G. n1 z( N2 T" u2 Z6 V7 r EPwm6Regs.CMPA.half.CMPA = 0; // Set compare A value
$ B! d" \. M3 ?. K8 t6 v, U EPwm6Regs.CMPB = 0; // Set Compare B value3 \. `2 M- {: d* j4 x+ s& j
& z/ L0 ], g5 H
(5)初始化动作限定模块,配置AQ相关寄存器值8 `2 c( d% f" ~' J C
通过配置AQ模块可以确定PWM输出波形方式等。这里配置ePWM6输出,当ePWMA计数器计数到0时输出低电平,当ePWMA计数器计数到CMPA时输出高电平;当ePWMB计数器计数到0时输出低电平,当ePWMB计数器计数到CMPA时输出高电平。# r8 |* r ^9 M, `1 i) e& l
. T# _* o* f9 g" K+ t8 s: h
// Set actions7 q, l6 p' C4 a
EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Set PWM1A on Zero9 S9 K+ N8 ^% A: x. M# |
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // Clear PWM1A on event A, up count
; Z9 f, _3 d" {3 o EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Set PWM1B on Zero! U% P# A7 v' E" S# z
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET; // Clear PWM1B on event B, up count
7 e9 o* r4 r9 L+ z6 d6 L( s# S1 f
' J7 A/ J1 \! Z* j4 v' D" U3 D) m5 P5 [
(6)初始化事件触发模块,即配置ET相关寄存器值
8 E% D x) V6 v8 E) ^9 _% ]% @" n当需要事件触发输出控制,就需要对ET相关寄存器配置。这里选择计数器计数到0时,同时使能事件触发中断,每发生一次触发事件就输出PWM。
* ^" r( I: ?; q1 b1 v5 F
g4 T: M W& H EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event6 r; b | z7 U8 y* Y6 A
EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT' R% B6 M8 J" z. I
EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event每发生一次事件产生中断信号EPWM6_INT: M$ n! W$ U. r6 L9 w
1 l8 }% g1 \% ~- W& D" n- Q
(7)初始化死区模块、斩波模块,即配置DB、PC相关寄存器值. `1 V9 N9 e8 Q+ b r% U7 @
一般不对死区和斩波模块进行配置。4 J5 l( d- m2 S$ G7 s
(8)使能时基计数器时钟* x& w1 L/ C0 `" H+ s2 y
各模块寄存器配置好后,最后开启时基计数器时钟,完成这一步,对应IO口便可以输出PWM波
! n4 I( A1 p( \1 v# D5 {( H7 I+ f
EALLOW;3 a) V D2 m+ _0 M; {) k2 F
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced5 X- y+ D2 o1 V* f) P1 _
EDIS;% H9 G8 c; A2 `4 _6 H4 C4 D2 W
4 y0 a: b- w- s+ V1 E3 n, Z2.通过ePWM6A和ePWM6B两个管脚输出PWM波,分别控制D6和D7指示灯亮度/ H( n4 }: m4 ?* b
主函数代码如下所示
3 ?/ T4 d0 n5 Q1 F2 C
$ e7 t) _6 h2 b# ?7 T#include "DSP2833x_Device.h" // DSP2833x HeadeRFile Include File8 u) I; T* y. N1 f: B; H
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
5 B. Q0 z8 k/ u8 z4 I* q" [0 k6 d; B# O8 u0 i& p, N
#include "leds.h"
) c6 F M( [) v. Z: \9 |9 C& U h#include "time.h"//在定时器中控制灯的闪烁
0 @, ~' i g; u1 V( R. [5 d#include "epwm.h"//存放PWM的驱动程序
|) T6 {: P- {3 X$ X# [void main()
0 r% @) P" o' p# x, O{
1 h" S: }! }' R int i=0;
. G$ ^5 F S5 V unsigned char fx=0;//fx指示了一个方向
4 l t6 x! h' t# A' U A% @. ~( K: u% T
" F5 \$ T, S8 X; Z InitSysCtrl();* }& K F8 [! N1 G) d- a
/ n: Q* ^( l& z8 j4 O9 ?
InitPieCtrl();
/ u' f- |5 B' h, V9 T IER = 0x0000;
# F! X! F0 Y4 E) K IFR = 0x0000;
& G" I! P% ? V m InitPieVectTable();8 E2 h- W+ G0 @6 S, c0 Z6 M0 d
& ^/ ], z1 K/ R) Z) E0 O
// LED_Init();, k" X& ^' K3 ~) D3 c/ L% b
EPWM6_Init(500);//EPWM管脚也即控制了LED,也就是说周期值是500个系统时钟6 V& y0 u3 `3 A" R- S1 P. H
, W- I) f# p; [8 b" F while(1)! a0 h; M# _$ @# z
{
: `+ [; j+ M/ O5 ]" C% ?3 h if(fx==0)
& z& ~# U+ K4 B8 R; u {7 T4 [ ^$ k2 i
i++;
4 P5 u& }1 K! W$ w! c" E' M) M if(i==300)# ^. z5 h$ E- v- L% l# i& Q1 J
{% i, r# W. Y) k4 \4 n
fx=1;
( c k: H( E* s1 j# a1 v) P0 p }+ s7 g) U, V: l% p( q
}
( N3 R4 _/ x5 }' \4 o0 n else6 |' j5 P0 J- Y L' s; M: K
{& n& _( r# \ a/ ]" y" C3 ^
i--;
/ [! i: t6 C: R1 r, X7 k if(i==0)
/ J1 z l' v/ J% W {
+ F+ t1 X5 S# Y; \/ ^9 R5 d% N fx=0;
5 d$ p' t f% h4 K4 s' D( y }9 R; t0 s* N& ]6 L
}' n; Q. m6 ?3 _
EPwm6A_SetCompare(i); //i值最大可以取499,因为ARR最大值是499.8 s N) V3 o2 w! f9 a' X
EPwm6B_SetCompare(300-i); //i值最大可以取499,因为ARR最大值是499." e+ `& `, B2 @( k
DELAY_US(10*1000);
$ |9 W m3 n, j4 M+ a }
, m* T! g8 g5 r5 E! X% X" R}
$ t. a5 i' l% |2 L' p+ y( b. b6 B% n6 i! J/ R0 e7 J9 c
% } i8 V! G' w% D K
|
|