Systick的两大作用: 1、可以产生精确延时; 2、可以提供给操作系统一个单独的心跳(时钟)节拍; 通常实现Delay(N)函数的方法为: for(i=0;i<x;i++) ; 对于STM32系统微处理器来说,执行一条指令只有几十ns(纳秒),进入for循环,要实现N毫秒的x值非常大;而由于系统频率的宽广,很难计算出延时N毫秒的精确值;针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N); cortex的内核中包含一个SysTick时钟,SysTick为一个24位递减计数器;SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1;计数到0,SysTick计数器自动装载初值并继续计数,同时内部的COUNTFLAG标志会置位;触发中断(前提是中断使能); 如果外部晶振(即外接的晶振)位8Mhz,经过内部9分频;系统时钟则为72Mhz(cpu的时钟);SysTick的最高频率为9Mhz(cpu时钟的8分频);在这个条件下;如果设置SysTick值为9000;而SysTick是9Mhz;则能产生1ms的时间基;即SysTick产生1ms的中断;
! y5 T* K' q- j- x& ]1 ]3 w SysTick相关的寄存器: CTRL: SysTick控制和状态寄存器; LOAD: SysTick重装载值寄存器; VAL: SysTick当前寄存器;(重新写入的时候;会把状态寄存器的FLAG清零) CALIB: SysTick校准值寄存器; SysTick设置步骤:(使用ST的函数库使用Systick的方法) 1、调用SysTick_CounterCmd()失能SysTick计数器; 2、调用SysTick_ITConfig()失能SysTick中断; 3、调用SysTick_CLKSourceConfig()设置SysTick时钟源; 4、调用SysTick_SetReload() 设置SysTick重装载值; 5、调用SysTick_ITConfig() 使能SysTick中断; 6、调用SysTick_CounterCmd() 开启SysTick计数器; 6 Y: d5 N/ ~8 N$ U' F% U6 E Y
- /*Include---------------------------*/
) i: ?5 z: B0 F# D- f; K - #include"stm32f10x_lib.h" //包含所有的头文件/ d) v$ y/ g" A3 ?- ^ ^
- #include<stdio.h>
, C3 c; Z' L& m9 j1 a
( U- V* C: w5 J( \) y5 b' \+ u- //----------------函数声明--------------------
- y/ A- E1 e6 C8 w/ u - void Delay_MS(u16 dly);
2 n Y5 R- [" Q" f - void RCC_Configuration(void);. {* ^$ j# y$ l0 Q/ T
- void GPIO_Configuration(void);
- i& W- |) z5 P- N7 [3 M2 ? - void USART3_Configuration(void);; ?: G1 W1 G1 ~$ E! O
- ' Q* E& [4 f0 C5 P/ g( g! i
- . z' j" B# j! }9 `8 H
- u8 tab[] = "hello welcome to class !";6 [( `$ B5 ~+ z/ Y2 Z
- 3 z6 l% q) g/ G4 v! |
- void SYSTICK_Configuration(void)0 a, o5 V: }3 E) w+ z9 |, i7 M
- {
* r7 u0 z/ ]+ L0 _! c7 T - SysTick_CounterCmd(SysTick_Counter_Disable);
|+ f8 c# p% ~ - SysTick_ITConfig(DISABLE);. p+ K' G( a. D( C! C
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);/ ]: n4 C, [: u9 m
- SysTick_SetReload(9000*1000);+ i4 n3 n9 I9 `6 I
- SysTick_CounterCmd(SysTick_Counter_Enable);
3 B+ h" y8 y0 j; b4 W ~4 k - 8 _- V: s% T( Y0 t( }
- //*************打开systick时钟,但是由于systick时钟是默认开启的;
! I; a. _' d" k, K4 r - 2 }, K1 q& [0 x- n1 N( c
- }
+ y1 I2 P$ R- A; j2 Q( L- J - 1 p3 t4 F; T# ^2 B* `1 n5 S! W! N
- 4 _) D g% Y. g$ n5 t
- /*******************************************************************************
M2 P" O% A" B0 z0 Q. R - * Function Name : main
, |7 j4 l+ {: E9 p$ T5 x7 {5 ^" O: ^ - * Description : Main program." N" H. W$ i/ D
- * Input : None4 b( j9 S& B$ }3 y
- * Output : None
6 Q, `3 F& k- D m2 M8 _! }- S- N - * Return : None9 c8 F, y# G/ ~( j2 H' P! A
- *******************************************************************************/ # c( A1 g, p- h* t k
- int main(void)
% a: ]& y- \ Z- v: O3 W - {* {# e/ c, g$ [: ^% F
- u8 min, sec;
7 ]' W/ M2 q& c8 g; m- K0 C# | - #ifdef DEBUG
( i$ {3 p: t5 t( J4 O* i- P) c! b; n - debug(); x l8 t* }- i
- #endif/ o6 ^" Q% D5 w5 d+ {
- //------------初始化------------- a+ N! ~& X( X- }) U
- RCC_Configuration();1 Z$ N" }6 c9 }) _# o
- GPIO_Configuration();
' S" Y" B5 H5 k; E+ ? - USART3_Configuration();5 m. m: [" [) ]- E5 W- Z
- SYSTICK_Configuration(); + l/ c. Q: K; p6 h
- ' @3 D3 @( [3 K5 V' E: e' Z
- // id_num[0] = *((u8*)(0x1FFFF7E9)); //stm32芯片id的放置地址,96位id;12字节* O$ z |' k! ?. l
- printf("hello world\n");* i# F1 p& i- I: ]4 D: R
- //------------将数据上传给上位机-----------
+ E/ I$ {7 V# ?+ v - min = 1;6 K3 f% p2 J. L! \* m; J1 Z; G3 D
- sec = 30;
6 J0 U5 f9 ^0 R7 d - 3 A- S7 g! J/ X8 b% ], z( m: J; Y
- while(1)
, \% O' o7 g A0 e2 r - {
5 ?2 `. W: H. o- E" a3 I7 k: } - FlagStatus Status;
8 S. Z n5 S8 V9 g5 }7 e - Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);3 q1 {: q) r. V. o& P5 ]. M
- if(Status == RESET)! d' ^, g9 O Z; }) U0 `8 b p& l
- {
$ H A3 c" L" d. C - ;
) A7 ?! n+ a6 f/ q) p) B; A" G - }% u$ E- y9 v$ H5 K( m4 W
- else8 ]' n5 C8 g; h' i3 [' D0 o, }: Q
- {. K. Q4 d' E# ~
- sec++;
9 F- P+ x0 }" U# }9 G4 ~& k - if(sec == 60)
1 ^) }' J( `" R9 O" } - {
+ z$ f) K* ~( R2 q: k4 O- a' U - sec=0;
: }& m/ T! ?+ C( w4 c - min++;
$ K* g4 I6 p' v- o7 x - }
) }, S8 [; \6 i& i |4 h/ M - printf("\t\t%d:%d", min, sec);
$ h4 A, h! m2 S1 q - }
, ^: y4 l& s% {9 e( a - }! t G" T2 }4 B: v$ o
-
% n6 ]" m$ a+ m' w, }$ | - }7 Y+ J7 c9 t9 e& z" J) N
- $ ^( v' D7 Q' n+ W4 a3 F& ~4 Q
- /*******************************************************************************
6 H2 v6 e0 R/ @. X \0 i - * Function Name : Delay_Ms( j r/ h1 v* n( E# |; p. o `
- * Description : delay 1 ms.
! J2 M5 @) S& h o - * Input : dly (ms)
/ }' @: s& x5 D# M. w - * Output : None
! \4 I9 w2 A) r4 Z7 L - * Return : None
+ c6 X) W+ V% `& b% `: { - *******************************************************************************/- f8 r/ Q2 A1 B! _/ W
- void Delay_MS(u16 dly)% H) W- I# ^, w1 `- B O" H
- {- S0 A2 X D# L/ a
- u16 i,j;8 W- X/ G; @/ A* H( w7 S1 \. w( B
- for(i=0;i<dly;i++)
; Q, B5 R: i' }" z& F3 s8 r# C2 \3 F% w - for(j=1000;j>0;j--);7 {0 H5 f, W4 E0 n4 I+ l8 W4 A/ G6 G: J
- }. B6 o J% j$ m- v( l& C. m
- N+ r: B) C" F7 D& n, i) Q! y- /*******************************************************************************( ]4 W% J2 m2 a5 C
- * Function Name : RCC_Configuration3 l- W( ?% ?' q
- * Description : Configures the different system clocks.* h% R' r# o& B) \5 x$ @
- * Input : None
6 P9 E! |7 ]7 M - * Output : None3 E& U1 V2 P1 i4 A
- * Return : None
# Z4 T' S) k( o! N4 i( [ - *******************************************************************************/' }, u2 I0 J/ W9 w% t2 I& q! @
- void RCC_Configuration(void)
* W8 P% b, d$ Z8 | - {6 R1 I8 s# J" g% p" }: H: Q
- //----------使用外部RC晶振-----------) S7 s5 c2 |) q0 s$ O5 f
- RCC_DeInit(); //初始化为缺省值
( ]$ h! t6 Q) [, j9 @1 e- N0 z U- ` - RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
- W; r. S0 w) d - while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪
; K" |% S: C$ H. `. I" _ - $ T3 [3 e0 H8 P9 R
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
( }: N7 Z( {8 G! U& y2 T, g5 j( H - FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait state
' J! z H4 Y6 E% U! y -
/ \& k5 F {4 z. ?" A) I9 ? - RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK
7 k% j$ e3 R1 [. p" F3 { - RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK- Y* y% i* }- U/ ^- v. Y4 T
- RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2
% z- I+ P2 V+ O" ?) j J; w- A - RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
5 d9 D; a! j8 r - RCC_PLLCmd(ENABLE); //Enable PLLCLK6 J+ R2 c& N. g. }, M4 W- j1 V4 a4 H
- % j0 C, l; {# q0 A, h) f% j b
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready" d- m- v. d! k0 E# |
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock. M, o: s& y, B
- while(RCC_GetSYSCLKSource()!=0x08); //Wait till PLL is used as system clock source3 d% `) l4 Y4 R0 |4 Z6 A, X
-
& `$ k' d, E6 t( W - //---------打开相应外设时钟--------------------
# Z4 o% P. b7 g+ U4 @' Z, J6 k - RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //使能APB2外设的GPIOC的时钟
2 t7 _9 {' f( N - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //复用功能时钟开启
! t5 O b! t1 p1 b9 V - }( e' w4 L; L5 O+ D
: u$ Y5 Y9 C; y0 |) U8 K- /*******************************************************************************
5 L; M* o) x0 Y+ q/ y - * Function Name : GPIO_Configuration4 t; M- X) X( i; |
- * Description : 初始化GPIO外设
1 W: H3 U+ w5 x2 q1 J+ N - * Input : None3 Q! }/ M& f9 C- g; [- _1 Q
- * Output : None
* y3 l" a- Q9 a" o# v! j - * Return : None
- J) ^: G* Y: a - *******************************************************************************/
/ O) X& H0 u% M2 ~ x - //由电路图可知;配置PC10,PC11引脚
$ i1 w$ B: R/ a! M) w1 P1 N0 u - void GPIO_Configuration(void)
1 B! h% M: m) g% n: l - {
) o. P- \0 g- l, ^9 L# ~" f& E. O - //CLK:PB5 CLR:PE11 DATA:PE10, I( S9 O! U, r( F" h+ [5 O
- GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量
. j" Z* w+ h( E+ } - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PB.1-
. _0 I+ v4 I: c; S - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ+ i# e/ G% Z" Y# s7 `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为 "复用推挽输出"
- p5 i0 R% a/ \! F6 o D - GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOB寄存器
* j/ ^- {3 B% W2 t$ R -
- A) A( ]% C" K( S8 a& }! ~& b - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ; //选择PE.10 PE.11- }% u! i7 U- A) f# ]
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ; T' Y* t" n. s* }* J$ h& l9 l
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输出模式为 "浮空输入"
2 N0 W [( ?! m - GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOE寄存器
0 A# x2 J+ }) H0 T4 d - 6 Z X: I, ]$ Z/ c
- //开启时钟 必须在RCC_Configuration中设置 % t" n3 U; G* C2 F) g
- ! [" I- ]; s# h9 \# Z3 @, Y4 Z
- 5 T, C7 ?" A e) i8 I( z+ f# y
- //端口重映射:PC10/PC11
- u) \4 D3 p' Z3 R6 l K @ - GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE); ; ]+ o2 I' [6 d0 |8 K
- }
) @& Q# Z5 I( y3 V" }9 q& Z; R
: y" E; l3 e/ c6 \% A" P+ a- void USART3_Configuration(void)4 n3 `- |: W* Q5 i' ^
- {9 N6 }. M! u0 k' n! U
- USART_InitTypeDef USART_InitStructure;0 [! ]# q: E/ |2 s3 s2 y+ `
- USART_InitStructure.USART_BaudRate = 9600;9 J/ F8 V5 [& }+ I: u
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
u1 O- z5 q; {" B. u - USART_InitStructure.USART_StopBits = USART_StopBits_1;1 U2 ?8 `4 n, O7 M' w! k
- USART_InitStructure.USART_Parity = USART_Parity_No;5 R" I4 Z7 D4 A/ i7 S: f, P) C
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;( u- b/ e7 b4 f2 J+ B b4 R
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
/ a0 O4 g; F- u, F2 o- U# B - 7 P6 T. s9 B5 F- A1 E
- USART_Init(USART3, &USART_InitStructure);0 |6 S3 W2 t- y& D! M& U
- ' Y1 v/ P$ ^: X
- USART_Cmd(USART3, ENABLE); //开启使能
0 o. z: H# f, |8 F% L- |. h - }
& T& `4 n+ K" I: V7 E7 I, b. s
6 X0 i4 i9 \0 Z/ P6 G) q. E/ ~# ?- /***********************************************************/ r& z% F" J! O/ p8 v
- name: fputc *
7 f+ y5 V2 E7 r% }3 v - Description:重定向这个c库printf函数,文件流--->串口USART *. C" x& R d' v6 v8 H: W9 b6 v6 F, C
- *6 G1 b$ O1 A' p+ Z
- ************************************************************/
( D+ t# }2 `) N - int fputc(int ch,FILE *f)2 _$ S2 [$ p& k7 h" W% _
- {
) n: P) a. K# W' |4 J7 W7 P - //ch发送给USART16 z* S4 h0 g3 c9 X
- USART_SendData(USART3, ch);: N7 A9 [; k' c' F( j! u
- //等待发送完毕
5 ^! o# A1 E7 n' _/ o# L; W, `2 J - while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)
- q: E3 e; C9 l% z% O) e# |: p, Y0 H, k - ;
! l( h! b8 H# v! |5 F' B: [. F - return ch;/ L# S! w- r; V8 |! t
- }
复制代码 . A! v9 Y& J/ q4 ^3 ~/ _: L2 A
|