|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
#include "DSP28x_Project.h"
' |: U! C: B$ a: ]* k// Configure the period for each timer
% i# n$ B2 p4 Z6 t" `8 h2 u- O#define EPWM1_TIMER_TBPRD 3750 // Period register 系统始终为150MHZ,下面的程序进行了4分频,即为37.5MHZ,这样得到的是10KHZ8 I, n7 x' j! \! j0 Y
#define EPWM1_START_CMPA 1900//设置PWM通道A初始占空比
$ c) \8 ]# V8 }1 D# U#define EPWM1_START_CMPB 1900//设置PWM通道B初始占空比
& i; H; Q- v9 Q/ R' s* z6 ~$ evoid ChangeDuty(Uint16 Duty)//改变占空比函数
J5 y0 R. V5 A( x) T{
5 y: _4 M& q# I2 U if(Duty > EPWM1_TIMER_TBPRD) Duty = EPWM1_TIMER_TBPRD;, L) M) K% e5 e: E
if(Duty < 0) Duty = 0;
4 o: t/ o2 K# {4 J8 G' a EPwm1Regs.CMPA.half.CMPA = Duty; // Set compare A value
% O ^1 T/ [ `' F1 P* Q$ F EPwm1Regs.CMPB = Duty; // Set Compare B value& h4 z! c- T- J1 Z4 W9 I
} n1 r- f# i' F' S% j
void PWM1_Init()//初始化PWM
& o% c6 k3 h" ]" G: y% U{4 n+ M2 r# X- `5 h, f
/*首先进行的是PWM1引脚的初始化,因为PWM1的引脚为GPIO0和GPIO1,这两个引脚可以是普通的IO口,也可以复用输出PWM,这里选用复用功能*/
/ ]4 N# h0 y9 z9 V0 w EALLOW;
& Y8 l# |" y4 L4 k3 \" i GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // Enable pull-up on GPIO0 (EPWM1A)1 i- q! _ p9 Y* ?: X( {
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // Enable pull-up on GPIO1 (EPWM1B)
% |5 f0 E9 R1 v- j# F GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A复用功能设置,为0代表是普通IO口
/ V* g+ c d- X+ {3 d6 g GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B' _ r0 I1 b; E) Q+ |/ A, t
EDIS; L/ F- ]1 h3 x/ Q
EALLOW;
' w- c9 Y8 ]" ]2 U SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks7 ]: H6 ~7 x3 b. e" ?
EDIS;3 m/ d4 t7 m9 J! E- \
// Setup TBCLK! l0 S7 `4 m: n( V+ n
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD - 1; // 设置周期
( a5 L3 _! V! R* N8 ?: z" I EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // 这个代表的是相位,不明白什么东西; ?1 `# G* h, _0 N" M
EPwm1Regs.TBCTR = 0x0000; // Clear counter! B8 g6 R) }4 Y0 |8 b. \/ A
// Set Compare values
! Y; ~* e8 v5 b# r: P- } EPwm1Regs.CMPA.half.CMPA = EPWM1_START_CMPA; // Set compare A value" U' G( h+ E: i
EPwm1Regs.CMPB = EPWM1_START_CMPB; // Set Compare B value/ m/ `" w6 Z' r+ ?
// Setup counter mode; u4 L _% y$ `% m' E
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; //计数模式* X* L; F. V+ G+ h, B& e
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
( `2 j" t, A% O X9 k EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2; // 这里是进行2分频
6 s3 R/ X0 J- I. ~" f% } EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2; //这里也是2分频
: h9 ?; A# p4 z8 O% R8 ] // Setup shadowing3 ^, ]% P; N# h7 y) ]5 C! u
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //采用影子寄存器跟新0 }7 U3 [7 \# w
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
! J; @ g8 L3 H x; j/ K! Y EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
' U4 o& ^6 N* E" v EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
% \0 x/ B( f$ ~: L! ` // Set actions
3 K' O0 L% j6 x! y3 X EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM1A on event A, up count4 d0 P8 T* q; N( O
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // Clear PWM1A on event A, down count
e( w# k# q2 C8 i% {3 x EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up count
2 n1 K! y) n+ O+ x EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // Clear PWM1B on event B, down count. a9 c0 O% k( N0 r% n
EALLOW;. t3 R' t; T& J* s# s7 D
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced" s4 H2 V! n& R
EDIS;/ R, L- C+ [- G, _; k- p
}
( R ~/ J$ x4 ~- I- f% Gvoid All_Init()3 [: ]& O! `1 t( S* \8 V/ @6 ^
{* n* s0 H- v) S3 @
InitSysCtrl();
% \8 ~: L3 S. o DINT;0 B& @3 |+ [8 I# p5 F2 Q2 [, M
InitPieCtrl();* o. |, S! W1 l
IER = 0x0000;
; A; W$ A) Y# H2 ~ IFR = 0x0000;
& s( k' |8 }6 p/ _6 l7 Q InitPieVectTable();
" k. y- [3 g. d* U( x7 ], ^ PWM1_Init();
) n4 l. f3 I; n7 J1 p EINT; // Enable Global interrupt INTM' c" [1 ?( l& R$ x
ERTM; // Enable Global realtime interrupt DBGM+ T/ N/ v. E9 {$ K: K4 d b$ [& x- t
}
! i, I3 X( s. @6 I" z0 `1 Q( BUint16 Duty = 1900;
* l* ]& S+ H0 b. `1 Z, C2 lvoid main(void)
) d0 b* k% a; C5 z. F{7 @, ] O9 @( q/ ]6 G, r
All_Init();. Y7 s7 A/ E h6 X% \: ~6 w8 [
while(1)
# n* T) t# F- ?3 [; s+ p( ~0 g( R {
! j, a4 T; m' ~/ A9 F1 I ChangeDuty(Duty);" y8 ~3 ~4 p/ ]; \- i; Y3 z
}5 r9 x3 h2 p) I. z
}0 c! A( a5 X: u7 E1 Q+ B0 O* Q
7 _ o# M7 c/ \! S( U( f& N* l产生PWM主要需要三个部件,
1 J4 I/ z* |0 m* v! ^# D第一个是周期PRD,通过设定EPwm1Regs.TBPRD的值,来得到周期,我的代码中设定的是3750,系统时钟是150 M hz,经过四分频得到的是37.5Mhz,即1/(37.5M)秒,计数器每个时间间隔加一,加到3750需要的时间是3750 * 1 / (37.5M) = (1 / 10K)秒,即为计数周期,可知频率为10K。
* j6 D7 z4 G# H# L6 F第二个是计数器CTR,计数器根据设定的时钟频率不断累加,我设定计数时钟频率是10K,即每过0.00001s,计数器自动加一。我这里设定的计数模式是增减模式,即计数器加到EPwm1Regs.TBPRD时再自动开始减小,当减到0时,又开始增加。# g q$ C$ Z+ @8 l, Q% H
第三个是比较器COMPA,COMPA是我们自己设定的比较值,当这里设定的初始值1900,当计数器计数到1900的时候会产生事件,比如讲输出引脚置为1或者清为0。
: v6 t; J& a# z! a- f4 o) J这里采用了影子(映射)寄存器(EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;),映射提供了一个保持寄存器与硬件同步更新的方法,当使用映射模式时,只能在特定的事件处更新当前工作的寄存器,这就防止了由于软件异步修改寄存器内容而引发的错误。
+ f6 \7 e7 N, H* `计算器不断的累加,当计数器的值等于比较值时,就输出为1,当计数器的值等于周期值时,就输出为0.从图中也很容易看出方波的周期和占空比。) k: M V) P8 I. I6 G
) V5 P M' x3 s6 p) P
- j) H. n& w% ?. Y1 q
|
|