|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
近日工作中又涉及到了DSP28335的应用,看来TI的芯片还是得到了公司领导的认可,也直接丢了一份DSP28335的FOC程序给我理解。以前读书阶段较为简单的接触过一段时间,对DSP28335的基础功能部分有了一些浅显的了解,现在工作中要实际开始用了,开始发现之前学习的程度还是不够,因此要更加深入的探究一遍。可能非常基础,希望大家也不要见笑,人真是年龄越大忘东西越快。5 A% K* n e+ y4 {2 J( p ?0 E
Y1 e* M/ x6 g
系统初始化
" G3 M' X" [3 W# D) T. S首先从系统的初始化开始,系统初始化主要是系统时钟、看门狗等功能模块的基础配置,TI官方配置的系统初始化函数如下:4 N3 }6 o3 o( U# ?
3 C' A. u/ I B& C2 m8 p
void InitSysCtrl(void)
' t- L& x6 }' }; b: |+ E{7 k3 w, e9 P. q7 p9 p) l5 u) T; K
# g, |' J& {! h7 G% I // Disable the watchdog
! C' ^/ R2 _+ R# L. V& C/ | DisableDog();
# A( V% ^* K5 U' H : Z1 H7 p8 R0 v' g& u, Q. I
// Initialize the PLL control: PLLCR and DIVSEL
, O# F& c8 y2 t3 \. f // DSP28_PLLCR and DSP28_DIVSEL are defined in DSP2833x_Examples.h
" l' x, |! S! I/ p* U InitPll(DSP28_PLLCR,DSP28_DIVSEL);* s9 Q" X; b7 V
5 K. F9 {" O0 w& [" D5 z // Initialize the peripheral clocks$ H: k% i, e* n5 ?
InitPeripheralClocks();0 R s7 y, G% E
}2 [: S5 F9 K' k
上面代码主要由3个子函数构成,分别为 DisableDog();、InitPll(DSP28_PLLCR,DSP28_DIVSEL);、 InitPeripheralClocks();这三个子函数的功能我们也来一一分析。
, O! y& A/ F/ C4 [5 f( `& g; L2 }( C- Q( G. ?5 {0 T- P$ J
看门狗配置函数DisableDog(), Q" G' o2 K. U X" B$ C
首先是开门狗初始化函数DisableDog(),函数代码如下:4 d/ u6 l+ E7 [
# U/ U9 d! T1 v- c9 B
void DisableDog(void)
/ x1 y; p( a0 _6 F1 @{
% W) z/ O% Q) E1 g EALLOW;3 B, J4 k6 v* t- O1 p1 |( W% K4 K
SysCtrlRegs.WDCR= 0x0068;2 ^# h0 J5 |5 h' C
EDIS;, m% O/ ]1 R @7 |9 m! f: q8 O9 c9 a
}
$ n9 K ~# | f. g) c8 |# U/ ]代码解释:
* T" l& {, Y6 `4 S- C5 P# x
5 l3 t$ s2 o j( j, E: Q1、EALLOW /EDIS 打开/关闭状态寄存器保护。EALLOW/EDIS 是DSP为了防止杂散代码或指针破坏关键寄存器的状态宏定义指令,关键寄存器包括ePWM、Flash、器件仿真寄存器、FLASH寄存器、CSM寄存器、PIE矢量表、系统控制寄存器、GPIOMux寄存器等,这些寄存器的状态决定DSP是否稳定运行,因此需要修改之前应用EALLOW打开保护,修改完后必须用EDIS关闭。6 e* w$ m) E* q! \8 Y
8 E# B2 o1 E- t2、配置SysCtrlRegs.WDCR寄存器为0x0068。关闭看门狗,也可以戏称为把狗杀了,好残忍,看门狗的实际作用就是防止CPU跑飞或者其他故障导致系统出现不可挽回的故障,如果一段时间收不到CPU稳定运行的信号就会复位CPU,从而保证CPU的稳定性。打开WDCR寄存器表可知,寄存器后8位起到实际作用,0x0068 = 0110 1000 ,第7位置0看门狗不满足复位条件,第6位置1禁止看门狗模块,第5~3位写101强制写,第2~0位写000配置看门狗时钟。关键为第6位置1禁止看门狗模块。' X7 R* Y/ V" P
. l$ G! N+ q+ G6 D5 S! y9 V5 o/ u
9 `0 I9 }1 ?. @, e6 t. m! [7 }0 O1 Q1 l
锁相环初始化函数 InitPll(DSP28_PLLCR,DSP28_DIVSEL)! L/ R" x! m: N0 t5 I
其次是锁相环初始化函数,在DSP中锁相环函数主要是用在时钟的分频上,将晶振产生的震荡进行分频和倍频操作,是整个芯片心脏——时钟能够起作用的关键之处,因此必须在程序开头对其进行配置。其代码如下:4 L2 ^6 k; l, m( |
% f; |" e/ a L. t+ Q
void InitPll(Uint16 val, Uint16 divsel)" O6 Q& i) s5 q- n# B3 q
{
: v3 s g0 H9 V. V) o: B8 r
1 c- S/ ?6 f' {: s5 _$ A/ h. B& V // Make sure the PLL is not running in limp mode 确保PLL没有运行在故障状态
0 @: p4 L0 B0 k. C( {4 j( L' D if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
7 d5 o8 D! d/ j: c2 H& a4 e {
$ o$ t0 Z/ ?( a // Missing external clock has been detected
- h1 H; @- h% o: w // Replace this line with a call to an appropriate
3 _ v$ X `3 h4 h' J( a# j, g // SystemShutdown(); function.
; @8 S5 x `$ b3 z4 s$ j2 f u // 若检测到系统失去外部时钟,则关闭系统
' H2 z6 U4 q, C; s/ s7 K asm(" ESTOP0");- C7 ]0 P* ]1 U5 N
}
' J/ I5 p: r0 B0 d* n* I" T0 o . K: y9 M- h! J1 A p4 i
// DIVSEL MUST be 0 before PLLCR can be changed from 在PLLCR可以从更改前,DIVSEL必须为0
% v" G5 B) d3 T k // 0x0000. It is set to 0 by an external reset XRSn 通过外部重置XRSn将其设置为0
2 w: P! {* l' u1 W // This puts us in 1/4
5 E1 c7 C/ }. y( e* t4 O3 k) H9 Q if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)# ?7 X' ?2 S+ O9 y' K8 r3 X9 i
{
- d6 o( n8 P( j$ v: D" \ EALLOW;$ T+ h) S. J' }0 ?1 c9 m
SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
4 w g$ ^- s5 Y5 N6 N) h EDIS;
" A3 r( n: w- p: r! s* D }4 _ X1 |/ Q1 y- l9 i
S! Z1 o; t( }; O6 Q, W* I; h // Change the PLLCR 更改PLLCR
' B* I# ^, r" Z if (SysCtrlRegs.PLLCR.bit.DIV != val); E/ i5 Q2 L, w$ I
{7 u0 x) @4 s/ t! ]: d
0 Q. W! h3 O+ C9 G! ?* d4 U1 H1 A2 S
EALLOW;
4 Q; l* W; I, Y: R4 m8 j // Before setting PLLCR turn off missing clock detect logic 在设置PLLCR之前,关闭缺失时钟检测逻辑+ Y* h/ i9 T1 Y% s
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
! Z- d7 t, |' G' p, [ SysCtrlRegs.PLLCR.bit.DIV = val;
0 F3 c- a+ H& p2 V9 m EDIS;) ^. I" q! ^) M* i) g: }; L* i4 f
5 |% v. M( D7 F, ^; {. T DisableDog();
4 ]: j1 g1 M: q/ W" ]" u 7 R; ~; T" i4 a9 w8 h5 ?
while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1). C0 G: D/ g6 L" I
{0 W4 V# w( m5 G8 E5 q# U
// Uncomment to service the watchdog
! Z! b; j" K7 T6 L2 K2 d' W // ServiceDog();% h) q; ^4 @/ [9 ] o
}0 g3 _: i9 {" C$ m0 z+ d0 G
1 {8 {0 _/ {5 P$ D5 h) s" r EALLOW;
# t7 z- ?6 A/ A) p SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;4 W: m) \1 v9 S: c9 G/ w8 o7 @9 w
EDIS;
5 i9 R4 d1 M( {8 \' T }
$ r0 b% @% N' h, d5 B5 h
+ }5 W% u! u; ?7 K( H // If switching to 1/2 如果切换至1/2
" l& K3 f* B1 o1 F if((divsel == 1)||(divsel == 2))" j. L) W) [: q, b6 g& k
{
9 h# S- b8 Q7 q- D EALLOW;0 ~, }' K8 b5 ~: ~$ i; K
SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
5 ?( E& k3 D6 o* r; ~# I* w, p EDIS;5 A* r! {3 }; Q2 h4 d$ c
}1 d/ l! O6 A/ J9 _
# u. V! O# H$ m+ ^/ [, t; ?$ _
// NOTE: ONLY USE THIS SETTING IF PLL IS BYPASSED (I.E. PLLCR = 0) OR OFF
8 {+ S9 Y+ l3 ]! M2 f8 E* m2 j9 _ // If switching to 1/1 如果切换至 1/1
|5 r2 v7 u6 U( d9 j7 c1 _4 I // * First go to 1/2 and let the power settle$ U" ], a1 P( a0 p i8 A
// The time required will depend on the system, this is only an example( ?6 C# ?9 M$ ~8 B s
// * Then switch to 1/12 a7 ^9 m4 _6 C, l& t- h) y0 U
if(divsel == 3)5 }) w! n* ]1 W0 [1 b+ B
{4 M* @5 P9 z5 z; v$ c+ s5 e
EALLOW;
2 {* x+ k, E; ^" @: Y J SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;& O# k% z6 l8 @$ i/ s
DELAY_US(50L);: w/ j4 t5 k8 Z, R5 c" p3 H
SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
- R1 S% L3 q/ z9 K7 B8 n: @ EDIS;# J6 M% a' k6 c0 z" l/ x' F
}
2 I8 x# u7 {1 w% R* N* d( `}% E5 s* N0 g. Z/ j, n! n0 O
) _' h; T3 e: m; |$ k! Svoid InitPll(Uint16 val, Uint16 divsel)8 O/ x P! ?, |, ?
{
3 q3 M) O8 [/ ~1 c 2 X ~8 C4 u4 q/ c
// Make sure the PLL is not running in limp mode
5 K$ Z: ~6 G6 R' m/ B _) T if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)" I6 D+ [0 t1 W5 E
{
! ~: F3 Y3 r2 F // Missing external clock has been detected |9 G1 G7 L) P( k
// Replace this line with a call to an appropriate+ Y& ^, y8 g5 ]$ J; C
// SystemShutdown(); function.
0 c Y5 y1 G& y: N$ o$ b2 _' t0 Q asm(" ESTOP0");
: K8 ~, s3 w! e! [ }- h( ^: f! V+ S/ r* C
- z& N. o. p: b( U! t
// DIVSEL MUST be 0 before PLLCR can be changed from/ d9 d4 D: m2 w* S& q7 U
// 0x0000. It is set to 0 by an external reset XRSn
3 r) n/ s9 I$ V" B9 n // This puts us in 1/4/ X- D* H) k; B+ S
if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
5 T9 ^' K- K' Z, p' R {/ r# m5 N4 v) O7 N3 E. a B; x
EALLOW;
% l& H8 H+ }1 M SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;% h" e( p: I8 }1 `4 n5 @
EDIS;+ t4 ~. b6 h. J
}& p' z. ]/ d! [! y% b7 m, B# S
: n* ~; C, Q4 w) Z( K
// Change the PLLCR- X7 F' r) D3 L2 P3 x3 y
if (SysCtrlRegs.PLLCR.bit.DIV != val)
6 o" _: s" x8 j7 q. U+ F$ l# |2 c {
) n3 E6 x, r: m! D V# E+ J
7 \$ j5 B' K9 ~6 p7 z EALLOW;$ F# Z$ ?0 `+ `4 T2 t' [, `8 R
// Before setting PLLCR turn off missing clock detect logic7 j* S4 N7 |% ]" e" Q
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
6 p5 {! E1 \. j) Q4 M, v SysCtrlRegs.PLLCR.bit.DIV = val;
7 i3 S$ }' G, ~# a5 L$ X/ S EDIS;
* g& x. J9 r# q( q1 T& x 9 P3 m3 e6 c" X3 |2 @: D
DisableDog();3 Z& e% J) C g3 C( v3 i9 q3 u7 w
) K y1 o; J- G1 a3 ~2 a while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
4 V( s" E8 f" N" _% P) ~& x {
' m: k9 Q5 ], Z5 t // Uncomment to service the watchdog
2 Z2 J$ m9 Y1 n: O& W) Y // ServiceDog();- ~; Q* @ B- z: `6 M$ K0 j
} Q! B* X7 R2 z" y; U
5 N* h4 O$ M4 C5 p EALLOW; ]+ I% Y% f4 ^- C5 W
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;9 l: a- ?- u) ^; i( z
EDIS;9 i6 F( K- E' P) q2 ?& ~9 R+ Q
}
' | U/ C6 z+ ^8 g3 J7 {
( \3 Y5 m7 l* c- o ?9 h0 u; C- f // If switching to 1/2
0 ?! g& _( e9 j( l$ N1 ` if((divsel == 1)||(divsel == 2))
/ [$ k7 x: b- K2 a! w {
9 z' w" P/ ?- E! g2 v0 R1 e* W EALLOW;
, a ?% l9 B: R SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
. S; c6 c+ ?( z3 Q4 x: _4 ~/ j9 p) D6 P EDIS;
& e) ^5 F* M; W8 M' C6 K }' X4 m- |5 e! B! O* S
2 C! w f b7 n5 C // NOTE: ONLY USE THIS SETTING IF PLL IS BYPASSED (I.E. PLLCR = 0) OR OFF0 M) U9 X( M! N% R. S
// If switching to 1/13 y) V# w ?, h* ^& e# }" {/ p
// * First go to 1/2 and let the power settle; P2 ?* M! t3 C% X
// The time required will depend on the system, this is only an example- j, K6 Q0 F7 ~: W- G8 M! M
// * Then switch to 1/1
% @, t7 J/ R, \/ [4 W: C if(divsel == 3)4 J- v! h. O* h |, X/ @
{
6 l7 c8 e q8 a# F6 h( Y! v1 ^ EALLOW;9 z5 V0 _$ E% Y( z: O( W
SysCtrlRegs.PLLSTS.bit.DIVSEL = 2; e! f* X# ^( Q r: N) |
DELAY_US(50L);) ~) A- |% R3 H
SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
7 h4 `7 f8 J' d# a" Y EDIS;
! w' V/ b* Y" Z K! P" C }1 E8 d" W% L! P
代码解释:
$ z& \6 M3 C# T# g* e$ K/ X( t( r
1、if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0),检测外部时钟是否存在,保证在外部时钟正常的情况下运行系统。
3 D, a9 X* E8 b+ e# H* W5 X3 I6 s1 O: C+ A% k+ k
2、 if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0),如果8~7位不等于0,则强制置为0。; `' D) j7 H- A
! m8 ? _8 m3 ^3 |, m5 C6 ?: I; l5 T4 F6 r
, ^6 x2 V* p8 f8 C8 q3、if (SysCtrlRegs.PLLCR.bit.DIV != val),如果锁相环控制寄存器PLLCR的3~0位不等于10实现10倍频,则使得锁相环状态寄存器MCLKOFF标志位为1,并强制置锁相环控制寄存器PLLCR的3~0位等于10。并且锁定锁相环,然后打开时钟丢失检测功能。- q9 {& A2 O' P
/ V3 l2 e: B7 I$ I I3 `
4、if((divsel == 1)||(divsel == 2)) 与 if(divsel == 3) ,配置锁相环的分频。通过查询头文件可以看到这两个值。证明系统默认的倍频数位10倍频,系统默认的分频数为2分频。
) A/ d4 V% A; o1 ?. h
+ {" n( W! U7 w& W
! ^" a, P8 [5 z, y. o2 ~7 @
- h8 L& e! E- X7 s& x' H2 V由于目前的生产工艺,晶振频率为30Mhz的晶振性能更优,配置外部晶振为30Mhz成为主流,因此选择的倍频数为10,分频数为2,30*10/2 = 150 Mhz ,这也是DSP28335主频为150M的由来。
" v* s! y3 f" o6 m- ^' }6 t5 h) Y1 e2 C C8 V) z3 D. g
3、初始化外设时钟函数InitPeripheralClocks();# }% T& m: A4 N
在进行了外部晶振的倍频和分频后,芯片就要将自己的动力分配给各个外设,驱动各个外设进行工作,这个动力的分配就是初始化外设时钟函数的作用,函数代码如下:6 E# [7 v" f; D+ k6 C* B1 ]
5 M5 x7 ]* p: s1 }6 i: Kvoid InitPeripheralClocks(void)
0 ?9 |) d1 S m# J+ U2 u{
$ M) ?4 P( [( K$ a% f EALLOW;/ P8 [; A2 L9 e5 z5 @' E
5 S' f+ T; R( T
// HISPCP/LOSPCP prescale register settings, normally it will be set to default values
! D3 j; v( N2 C4 O# t SysCtrlRegs.HISPCP.all = 0x0001;; N+ T# T3 v# G( D
SysCtrlRegs.LOSPCP.all = 0x0002;' V! n8 r; \( ?& M. f- H# o% F
" l4 E8 K: q! z$ y3 U5 g4 e// XCLKOUT to SYSCLKOUT ratio. By default XCLKOUT = 1/4 SYSCLKOUT6 {& l! F9 S" m/ {
// XTIMCLK = SYSCLKOUT/2
; k1 c+ x8 {1 W2 ]" O% D XintfRegs.XINTCNF2.bit.XTIMCLK = 1;" ^: H$ Z- a3 F; i2 Q
// XCLKOUT = XTIMCLK/29 F4 P- s3 x! z! U% u
XintfRegs.XINTCNF2.bit.CLKMODE = 1;
- T+ F! }- ^4 k5 i // Enable XCLKOUT
9 g" _% z3 O9 y l T" Y' E XintfRegs.XINTCNF2.bit.CLKOFF = 0;/ A( L( Q( m$ A6 d) t! S
, z0 R/ {% l- e% O// Peripheral clock enables set for the selected peripherals.
, y4 G/ Y6 \: `// If you are not using a peripheral leave the clock off% F* c3 ?* @; T' f9 X- i
// to save on power.
5 @7 x8 m1 W# s1 c+ }- l- q1 L//
& a9 b: p2 P2 h" X3 h; u// Note: not all peripherals are available on all 2833x derivates.
6 {5 X* ^* T7 ~, V% {3 E$ F// Refer to the datasheet for your particular device.& X( \: c7 F, X" T9 R
//
7 k! `0 b( J) k9 s, n& E// This function is not written to be an example of efficient code.) z* ~2 C4 |2 Q& h. r
1 b! K6 L/ p) w* E" g) g* t SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC
/ m, _( A& R5 B' U/ C, d7 T
" c* N* U$ L0 F: l! o // *IMPORTANT*
4 j5 \( @- n" c4 c- r# E // The ADC_cal function, which copies the ADC calibration values from TI reserved9 z8 W6 a0 i6 j7 _
// OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the) m# N" C' B/ e4 e
// Boot ROM. If the boot ROM code is bypassed during the debug process, the
- V6 X: X* m3 T; v3 z) l$ E5 h // following function MUST be called for the ADC to function according8 O: w8 x5 H( a
// to specification. The clocks to the ADC MUST be enabled before calling this J. X% j- \- t
// function.
$ w3 q0 ?1 G4 X // See the device data manual and/or the ADC Reference5 l8 P2 e+ d7 [7 }: V+ p
// Manual for more information.% _$ e, F" y* I* o
$ c4 R# b4 j$ |8 C; ^ ADC_cal();8 l1 c: }/ |+ o1 @7 ]- Z7 _$ e; U+ Q
4 ]) W! G% h3 Y0 o& F5 L" M
0 p# o2 A/ D1 d
SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1; // I2C X; \! B3 c# k9 v% j/ S% I
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // SCI-A1 e0 W' ~4 J3 w: f: v* B
SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1; // SCI-B
8 W, k% @) n# f B SysCtrlRegs.PCLKCR0.bit.SCICENCLK = 1; // SCI-C
' Q7 J3 P* D9 q: J; m4 F" y7 A6 B. y SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; // SPI-A
$ s! j: w q/ g5 J& U7 u SysCtrlRegs.PCLKCR0.bit.MCBSPAENCLK = 1; // McBSP-A, }. ]6 D& w4 [% {' D
SysCtrlRegs.PCLKCR0.bit.MCBSPBENCLK = 1; // McBSP-B
- l6 u) m+ w* r L9 P. N# @ SysCtrlRegs.PCLKCR0.bit.ECANAENCLK=1; // eCAN-A4 |. `2 l& s/ r2 ~
SysCtrlRegs.PCLKCR0.bit.ECANBENCLK=1; // eCAN-B- r5 {( P6 J2 e& U/ l
& \$ w5 J- S# ~( k: a4 q SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM0 E& @& Q$ `9 s) A
SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // ePWM1) s/ d g% l# N5 S; N
SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 1; // ePWM2. }- w: R9 C2 T# H) K( ^- c% b: O& R1 o
SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK = 1; // ePWM3! R0 }/ |' Z5 L0 I
SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK = 1; // ePWM4
$ b( [9 A* I; h! j7 s6 ] SysCtrlRegs.PCLKCR1.bit.EPWM5ENCLK = 1; // ePWM57 N% {: {1 q3 Q- j7 c( u- K$ `3 B
SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1; // ePWM6
8 R, v- G: ]+ w* h+ }+ g; r // SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable TBCLK within the ePWM* H8 B9 \# o( i* r6 q4 i" j
! B0 [$ F7 ^( z1 v$ j SysCtrlRegs.PCLKCR1.bit.ECAP3ENCLK = 1; // eCAP3# E4 E+ k U- T9 L
SysCtrlRegs.PCLKCR1.bit.ECAP4ENCLK = 1; // eCAP4
% Q# a; \) \. t2 Y# J4 F& ? SysCtrlRegs.PCLKCR1.bit.ECAP5ENCLK = 1; // eCAP5
3 A3 u) x4 B- h) F t/ I: j SysCtrlRegs.PCLKCR1.bit.ECAP6ENCLK = 1; // eCAP6% ]7 j: A' U' }$ u
SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 1; // eCAP1* J5 e; J3 N7 G& z/ `
SysCtrlRegs.PCLKCR1.bit.ECAP2ENCLK = 1; // eCAP2) x* y, ~' i3 s$ W8 ~! t2 ]
SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK = 1; // eQEP1
, }; z9 c# b* D! H& x. G1 r+ g: P SysCtrlRegs.PCLKCR1.bit.EQEP2ENCLK = 1; // eQEP2
. T4 J- Z4 M2 C7 X0 c# M $ o1 S8 u* b. x/ F1 P) I
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0' n8 j# p- K0 O3 `; g) s8 F( Y
SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK = 1; // CPU Timer 1, n4 j$ T3 ~# h3 q: S& x+ x& z
SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK = 1; // CPU Timer 2% U% d5 V& X; u) D" U; r: R
8 z% ~; ]' u" \: v% z SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock
8 J- |4 p2 E* }( ^+ `. {! o SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1; // XTIMCLK) T5 R! I2 o$ |. X1 P; d# k
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO input clock
. r/ x2 d) d: l" Z& H ; l: z7 o0 |. Q% |6 _
EDIS;. J" T* [. `$ Z: R5 r0 K" g
}
' P) n$ u$ v# I$ {! r7 r* I 代码解释:' @( q" d& O3 b0 q% |" P
1 Z' _" |' C1 P9 S; A& M$ ^; z1、SysCtrlRegs.HISPCP.all = 0x0001; 设置高速外设时钟分频 = sysclk / 2。& L, I4 e% j5 u) ~
) R* k6 t% a, C! [) t& O
& d8 }. b, l6 ~/ e0 I 2、SysCtrlRegs.LOSPCP.all = 0x0002;设置低速外设时钟低速外设时钟分频 = sysclk / 2,这里命名稍微有点出入,但是查询头文件后确实是这个功能。只不过换了一种方式表示。本来我以为我很细,但是发现是我很粗,错过前一句的命名风格,实际就是这么命名的。1 m8 m$ p3 E" {8 H+ N
/ K' j( R0 D l- w
& P0 h& H/ [: ~7 v! o6 X" X1 h) n
8 j* r k8 ]( G: e4 T/ o
7 ]! E# E$ F! X M+ m5 O' ~; B; @
3、XintfRegs.XINTCNF2.bit.XTIMCLK = 1;配置外部存储器的时钟为默认状态。5 m: {# X( N/ E# r5 a7 I
' k7 Q% A% ~3 {0 G& e& j3 `: B& N ?
/ m/ T. t6 H# ?+ T. U. W; t1 D b \! `9 I
4、XintfRegs.XINTCNF2.bit.CLKMODE = 1;外设时钟频率控制位,并配置为默认。; n1 l ]8 P4 H+ X/ V. B) t
' J$ [- F% i; ?& ?6 w
% L( h3 p+ j/ m0 k+ u$ {
1 z! h& a$ B# h8 ]; g) ]9 z1 o5、SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1等; 外设时钟使能,这里的外设时钟控制寄存器PCLKCR0控制片上各种外设时钟的工作状态,使能或者禁止,也就是说这里控制着外设的各个时钟的关闭和开通。9 H6 N' O, ~: |' r
, K2 N/ y; o# m2 d
小结:% W4 e* ?% z) h0 [4 O8 n
通过这个系统初始化函数,我们能够得到几个关键的信息:$ x( }& w. [" \+ B2 |
1 J- p# [7 `$ F6 y1 g1、外部晶振为30Mhz,经过锁相环PLL的倍频和分频操作可以得到DSP28335的主频150Mhz。
" o& M1 F6 r6 O
6 V" f* {: b8 M9 v% u$ o' R+ o+ [5 E2、在初始化函数中,能够选择打开或者关闭各个外设时钟,并且可以配置频率大小。
4 x' e% B1 X4 o1 t# x. D% J
6 k; C) v) d+ M) T* U说实话,在梳理这个初始化程序的过程中,其实好多次想撤退,心里想着反正这些都是固定好的,也不会更改其中的参数,我为什么要花这么多时间去看这个呢,但是咬着牙看下来了。看完之后其实我觉得收获还是挺大的,特别是DSP的主频150Mhz是怎么来的这个点。说来惭愧,用了DSP好久,只知道主频是150Mhz,还真不知道是经过PLL分频又倍频来的,有不有用?我感觉其实还是有用的,我们对需要从事的工作有了更一份的了解,这就有用,也希望自己在日后的学习过程中,刨根究底,不偷懒不粗略,细不细?不够细啊!忍不忍得住,那必须忍得住啊。
5 t3 L v$ Z0 {* g2 }. ]. h—
$ q& B M7 ]) y% X |
|