|
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的中断;
/ [+ N/ J- H; {4 s" w1 G# s 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计数器;
( }, n! t$ ]& ` r/ z8 \' `5 t+ X: y- /*Include---------------------------*/
& Y) }* W( S* e& T' a - #include"stm32f10x_lib.h" //包含所有的头文件0 {6 a" [0 g9 h& d" v
- #include<stdio.h>) F: t+ v) R- r, d4 A# e! J. t
- ' P+ w6 N3 A' P/ G/ I( `1 h
- //----------------函数声明--------------------
7 i: k2 H! O5 V2 K% | - void Delay_MS(u16 dly);
" _% G/ L. V4 q - void RCC_Configuration(void);1 \4 w+ |: O1 R/ q! X
- void GPIO_Configuration(void);
( N1 ~6 `& o' p, Y* p3 a - void USART3_Configuration(void);
) A/ Y1 H, Y& h, g5 E9 q$ } - 0 ^1 E! M+ }" r3 b! t* l
6 Y) w$ n# H3 |8 a! L- u8 tab[] = "hello welcome to class !";
- A4 }. _4 C8 F - $ K3 \" E) k3 Y
- void SYSTICK_Configuration(void)
7 c* u! _! b, V/ Y: i5 d - {
" g" T) B" \" P - SysTick_CounterCmd(SysTick_Counter_Disable);8 {$ n9 ^/ N* z. N7 B* c# m
- SysTick_ITConfig(DISABLE);
5 o) i8 T6 a3 G6 V, T. \/ a! O - SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);6 p( ?! j: v7 h4 u z- c
- SysTick_SetReload(9000*1000);, x- _. A: C) L2 b* i
- SysTick_CounterCmd(SysTick_Counter_Enable);
" A, X( D a7 @: R$ e5 t( |
* Q" u; ?0 Q3 q+ I2 _+ I) |- //*************打开systick时钟,但是由于systick时钟是默认开启的;/ U. ?8 v( w8 [1 {, ?/ `
-
- U3 `( a, }- [& j - } % g! G$ {3 X u t P' ~0 {
& G* y8 D' ~5 ^, g" [ [
4 G; Q; q) ]- h- /*******************************************************************************& A; q3 M, y7 P6 H7 H
- * Function Name : main& o$ l' x1 A) B0 m
- * Description : Main program.
3 R' @8 z2 f) v. k - * Input : None
7 v7 z Q$ ^- j1 r% a4 C G* i - * Output : None
9 H- d) a, J: [1 S0 s - * Return : None% e) g# l7 Z% x( E) a2 Z
- *******************************************************************************/
1 Z! j9 N1 y' {! T9 S7 ] - int main(void)
0 S# ^) O4 G- p/ m6 @5 ] - {8 k- k3 [ l9 Y) l
- u8 min, sec;
0 t. \/ R7 b' r$ {# u7 M4 C" ~) ` - #ifdef DEBUG
" x5 y0 |5 a4 G& k- G+ k9 x - debug();
5 H& `; M/ z0 B) D- _, m - #endif2 G9 n& n4 m5 F" d0 r! C. j
- //------------初始化------------
4 W( ]2 f; H0 I& p - RCC_Configuration();9 ]" x& c4 M5 V* M4 `- ^" P, A1 L$ u; D
- GPIO_Configuration();
$ D# i2 f' u6 a6 C. M% n - USART3_Configuration();/ a' K" f- O$ M6 T4 w% H8 H
- SYSTICK_Configuration();
5 P; L# S& r. V) D - & a/ N8 N; O v7 }7 _
- // id_num[0] = *((u8*)(0x1FFFF7E9)); //stm32芯片id的放置地址,96位id;12字节7 \9 }) c/ c9 a8 R6 a
- printf("hello world\n");7 A8 `) P5 ^6 ?2 [. \5 L) r
- //------------将数据上传给上位机-----------
, @$ ^4 v9 g7 e6 @6 w1 ]6 |( a - min = 1;; _- [0 W4 L& W/ K5 b1 w4 m
- sec = 30;
+ k8 V& x3 T6 e+ @9 ?3 N7 \, m6 \
$ b( }; d" T1 O$ y% i- while(1)
+ U" V" [4 w! K7 r- E - { ^8 ^; f* {/ I" E2 B7 Z1 S
- FlagStatus Status;! X3 S1 |9 A. N2 c6 h, ]+ f
- Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
, ?5 ?, e5 `2 z# B& w% c& D6 `% Y - if(Status == RESET)
$ G# y, x4 \- E% _% A+ M* l; `1 a1 ^ - {
& P( ~" N/ u- U6 Z - ;
* ^/ d: k. \7 w+ G; U( z. h - }# }" {; k8 n* ]) M- R5 s) i5 {5 R
- else
* F# Z. p- I3 x$ `! c6 K - {
% G* S, K5 p5 `: F2 b+ k - sec++;
) i* ]2 r0 N7 C) ^0 g l4 f9 a% p - if(sec == 60)
+ J2 q: |9 G- H$ a, d$ ^2 } - {
7 P9 |4 e7 H, D& q) ~3 K - sec=0;
7 H% Z5 l" @. M! e$ C - min++;
0 b7 H8 ]; v- ~7 w4 l+ q - }
% V1 ?7 N" ^- @9 t# C1 a+ a( I/ } - printf("\t\t%d:%d", min, sec);" a6 U2 N# s D# \6 G
- }
* Q. g2 C7 F1 @ - }2 a3 u( V' O8 h
- - p: F# M% ~& W; y& Y* f( h% [
- }
. M2 N* S$ @/ S0 m+ l2 e+ M
1 ~0 X* B) p0 d- /******************************************************************************** G/ U W4 n" U2 K( [- U
- * Function Name : Delay_Ms J1 D2 r$ Q3 ^/ f
- * Description : delay 1 ms.1 H$ R1 I3 d: T3 ?1 O' z0 a# r0 L
- * Input : dly (ms)
9 o3 a& i6 U1 h/ W( P - * Output : None" {# K0 J5 M9 B6 c. T2 i5 [. Z \
- * Return : None
7 r" ], ~+ u9 n - *******************************************************************************/9 C$ h( ^/ a) q8 T
- void Delay_MS(u16 dly)
7 b4 f9 [& h" O+ b6 m! p6 g5 _ - {
' n8 \; s w' s0 r2 D/ u/ _ - u16 i,j;1 t* G8 y7 f! K+ l2 `
- for(i=0;i<dly;i++)/ _# f; r8 _3 ^; W8 t
- for(j=1000;j>0;j--);- W9 G4 k7 ?2 v* i% v T9 N
- }7 b; {$ v) k4 Y' T1 P3 y) K3 @
- ( K- A5 A! C e! z
- /*******************************************************************************
7 i- u3 \" g& i' Q, ? I - * Function Name : RCC_Configuration
0 C: b6 S! }" U- E9 j0 e& t8 h - * Description : Configures the different system clocks.
9 E6 u( e( Z1 `2 n+ f - * Input : None5 T2 i5 x4 X% G7 q8 S
- * Output : None
' c" t. p! _- n( K/ B) F - * Return : None
1 o# \' a4 l& J; E3 u4 b! @ - *******************************************************************************/
2 w$ w4 ^) M+ [% }) h. ` - void RCC_Configuration(void)
- q$ W8 l9 K% Y3 Y6 k - {
/ K! ?9 m. s9 \/ K3 } - //----------使用外部RC晶振-----------7 ~+ g2 v9 @. [; `
- RCC_DeInit(); //初始化为缺省值
& k2 l2 [" @( Y8 O - RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
9 {1 ?/ T+ H$ t. W* U W% ?) J7 B - while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪/ J1 S/ j2 l( ]/ p4 i0 A' L
-
) Z9 ~! i f' m; K3 m - FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
3 M8 Z, p) D2 L9 Z - FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait state
; G+ z6 l, n" u( a - 6 ?/ q, V& M9 n8 X J! L9 i4 @$ ^
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK
& R/ O/ ?# L5 ?' W$ ^3 L - RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK# K& V! x8 T' g* H# E, {* H
- RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2
6 a4 q3 z u* l" U1 u0 R - RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
# E% w0 O7 B. q5 I - RCC_PLLCmd(ENABLE); //Enable PLLCLK
9 B; a; y3 a) {% m+ F$ L
" Z& I. c3 f/ s$ D) s: _$ `: X- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
# A) L( p7 m/ S8 J% `! ] - RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock+ W/ H6 R( n1 ]: i7 E% ]7 ]
- while(RCC_GetSYSCLKSource()!=0x08); //Wait till PLL is used as system clock source
; s6 G* R( e% y, F5 v9 N) ~0 i2 u' a -
$ x G) O$ F ]% y! d1 r0 x - //---------打开相应外设时钟--------------------
. i% ~% M5 Q) n% ]) y; L - RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //使能APB2外设的GPIOC的时钟- G. n5 m8 _' w% b; D5 l/ V
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //复用功能时钟开启 3 B6 P0 n/ E% U
- }2 D+ _1 i% O* ~0 X# P0 M# U) r
- 1 h$ w; A. [8 d$ o
- /*******************************************************************************6 I- E% Q' w6 O- @
- * Function Name : GPIO_Configuration& ^6 t# l6 `( ?2 e7 \3 H
- * Description : 初始化GPIO外设
* q8 R$ Q# K2 k; Z; ]# q5 \ - * Input : None/ Q; Q! v* H& a
- * Output : None @: \4 ^4 m: M5 Q
- * Return : None
; e4 \9 t4 G* b: v4 V" O# z) w - *******************************************************************************/
! Q( \! x3 P! r- u! f# v - //由电路图可知;配置PC10,PC11引脚4 N6 M* c! _' Y; V. R* x! A$ f! d
- void GPIO_Configuration(void)
6 _, u4 d1 r2 E( ^ - {: m0 p6 e4 q' |+ |' v# s
- //CLK:PB5 CLR:PE11 DATA:PE10
/ D" C/ ?$ e" l! e - GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量
: E& H8 S* X) t7 n3 |, R - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PB.1-7 p$ e; ]) V5 a" l5 ~
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
3 b$ c+ q3 B+ M1 n. A8 S - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为 "复用推挽输出"
2 t( P" m+ Q: c! y& R - GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOB寄存器
; [ @+ q3 y' o$ S. L& ` -
6 `$ x6 `9 X3 V& `8 d - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ; //选择PE.10 PE.11
( V$ k5 |( |* h3 M - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
, n# t; _8 \7 ?. s" Z" ~ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输出模式为 "浮空输入") `& a- G( c3 V
- GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOE寄存器
6 N( t9 G/ x$ Y- q v5 L/ D* W - ; d }( \* M! V8 u# R
- //开启时钟 必须在RCC_Configuration中设置
, p8 n- L4 D; K" I -
% N+ f, c/ b, \ F7 C, ^ -
$ Q: L/ x: R7 i" w: Y5 R - //端口重映射:PC10/PC115 n9 `& J5 `/ H9 [% j$ |" D
- GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
, j! m$ t- _4 m e& L9 A6 M6 x - }
- K( u/ ?& X! l' _
) S8 _* W4 ~1 Z0 s0 A- void USART3_Configuration(void) O* H, Y' G* Z& r
- {) U* x) l1 V7 _9 C4 d4 x( J
- USART_InitTypeDef USART_InitStructure;. {1 k2 G" c s! R& h% ]2 |6 f
- USART_InitStructure.USART_BaudRate = 9600;+ K% N+ b! _) G* J0 ?
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
7 I; \* S, Y, R' O9 p0 q- l' X - USART_InitStructure.USART_StopBits = USART_StopBits_1;6 b$ o/ `" R) G4 f+ Z2 F
- USART_InitStructure.USART_Parity = USART_Parity_No;
( D/ Q9 C4 Z$ y* ]: z - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;* ~' K% i- }0 f
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;3 v6 X: }8 }# M
. G9 L/ v5 D, Y7 k6 t( q) Q% s- USART_Init(USART3, &USART_InitStructure);& B2 N2 p6 W( {
- t- |* J3 c! ~1 {# y+ n2 T
- USART_Cmd(USART3, ENABLE); //开启使能* O8 @4 w3 a9 n
- }
7 T3 O6 a7 k5 n - / P5 f+ _; w5 o( Z% }. h
- /***********************************************************
: l4 w& v6 s! W# J8 Q - name: fputc *
6 |3 w3 O3 T* _5 ? - Description:重定向这个c库printf函数,文件流--->串口USART *
" ~8 Q2 G( g( l' {3 m - *) t" P6 ~1 c2 l7 W; v, F, I& m3 f
- ************************************************************/
8 s, |# X* |* x' h" o u4 Y6 ] - int fputc(int ch,FILE *f)1 r" s1 }0 U X% P r) `4 B# l
- {
- G# m8 r% _; k9 Y2 ] - //ch发送给USART1
9 `3 B) a# N8 L1 Q) z t6 V - USART_SendData(USART3, ch);
0 `1 n1 ^* V$ F; L% T( H- i1 f - //等待发送完毕
; c* ^( c: F/ W- r% ^3 r; I - while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)2 z, j. O2 V) F" z
- ;
$ z, k) k# E/ K, J( |: M4 Z- \ - return ch;
; l" r) ]4 L" y; M1 m3 F I - }
复制代码
0 m2 [# e6 L. H2 g u& v2 D; w |