|
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的中断;
' h4 n3 V0 D6 C U) ] ^ 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计数器; 1 k. q$ P i* s( O' q
- /*Include---------------------------*/2 C1 ]- `+ I/ K/ [* ~0 c& M+ P
- #include"stm32f10x_lib.h" //包含所有的头文件+ N! s. z5 ^) D+ p7 u+ x
- #include<stdio.h>
4 I; M% U* Y( ]5 c X b - % Q0 \: v& f8 Z4 ~) O
- //----------------函数声明--------------------1 h9 z5 `7 N, }# Z% p
- void Delay_MS(u16 dly);
% x: v o9 N- e( G/ D" Y# n$ } - void RCC_Configuration(void);
Q, p/ l6 L7 `. G1 s - void GPIO_Configuration(void);! q) l2 l: C/ W6 j6 r( M& M
- void USART3_Configuration(void);
2 I S& a# `6 ^) k - ' J9 `9 x$ n7 P9 m5 }6 x+ l
$ a1 @/ z& y" R' ~5 b- u8 tab[] = "hello welcome to class !";
, c, p7 o( X9 H; U5 w
; p& H/ c( f# z1 [! m4 Y! s- void SYSTICK_Configuration(void)( s+ {0 i6 N9 w7 t; g# ^
- {! R' _$ }) p# `( A
- SysTick_CounterCmd(SysTick_Counter_Disable);
& v. I1 q+ p+ a0 Q/ w* Y3 f; g - SysTick_ITConfig(DISABLE);
+ x! Z6 Z$ ^9 R+ G6 n7 ~( n - SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);5 S5 B- H/ r$ w% B. g" P
- SysTick_SetReload(9000*1000);
2 {8 P- t7 m& ^; u, I - SysTick_CounterCmd(SysTick_Counter_Enable);
7 A& l: n0 A$ W ?
; O4 ]$ |/ K( ]& j7 m- //*************打开systick时钟,但是由于systick时钟是默认开启的;- Z. l( b! _% M9 g4 l
- . d! u2 E" |. o. O9 B, A
- } % p2 Y/ k9 @3 U% O, Q0 k, K; M) ]
& ~) R3 G( n; F5 X. K; A- 9 t! Z: g9 A/ `% g
- /*******************************************************************************
( z/ e& Z% n$ {2 E% |& T - * Function Name : main8 F( l1 G6 o6 [5 U V
- * Description : Main program.
8 W9 T% ^6 M+ I, a - * Input : None4 `& J$ p6 E; U8 h
- * Output : None- |' ]% F* n W' \
- * Return : None9 I% y3 b; V7 w/ R! W: L( |( Q) b8 }3 R
- *******************************************************************************/ + v7 B' E" Q7 x4 ?
- int main(void)$ Y7 D+ t3 u3 i z
- {1 A# r2 `+ b/ L. @0 y5 h
- u8 min, sec;
4 R; N) X2 p# w/ F+ A, G0 V - #ifdef DEBUG5 {' ^" }5 j/ w0 I& H
- debug(); s0 R- a: W6 F- ~, b
- #endif, J* X! R8 D) v! {
- //------------初始化------------
5 B1 X6 ~$ D5 r2 W - RCC_Configuration();8 X3 Z6 T( }& T
- GPIO_Configuration();
" H: h8 R* {3 m2 H' f; } - USART3_Configuration();
" g9 N" H5 Q( I$ M7 S' W - SYSTICK_Configuration();
( z/ ^& N5 p9 L* i$ H6 j
1 r! E. P b) O3 o- V- // id_num[0] = *((u8*)(0x1FFFF7E9)); //stm32芯片id的放置地址,96位id;12字节
8 f' ]3 t1 v$ d: Y* S- x - printf("hello world\n");' _' w. _# G. B; D2 B) V" s, F2 Z0 f
- //------------将数据上传给上位机-----------
6 _. [4 a; X& E5 z6 H. v/ J2 Y' q - min = 1;/ f5 z# ]0 b2 a+ D- }9 J* |
- sec = 30;
# C/ \) R* P* o4 K1 c - : H, j+ Z* v: D" [
- while(1)
9 ], {+ h/ x4 {: s" B - {
0 m8 F- p! Z) F7 e; Z - FlagStatus Status;
, Y+ L, U9 l* O - Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
7 e5 |6 T# E3 Q9 G - if(Status == RESET)6 ~, w+ Z5 e, l' r* X2 f! i" Y
- {% S' r" b" N9 `2 e
- ;- w, b" x, _. D" f `
- }
0 V3 u' l' Q8 P! n7 H - else
) [9 ?, Q, p* n! q0 B" \, @/ ^: z - {- b, Z3 }2 i3 k. \
- sec++;- ^ h. Y6 y" P- ~/ I) ]
- if(sec == 60)
; Y& m! W1 q6 |3 f2 {, A$ m - {
c. u. ]+ j- r$ Y9 H - sec=0;# B5 f8 a' u5 C) u5 ?
- min++;! x* M9 V4 A1 D# f
- }, C" F8 i0 F. z7 I1 m% C$ f
- printf("\t\t%d:%d", min, sec);- h( U2 z6 ]7 c$ n0 I+ D0 _
- }6 _) x3 Z. f* x9 c) Y$ q1 ^
- }
* p- H/ `! }% a4 o+ ]( {. o -
: S' a5 l! ]+ u+ l" N' o+ W - }+ d) Q$ b% ^' Q$ J9 w" \
- 5 X, U5 p4 i# F! t
- /*******************************************************************************4 {1 @0 A O' S! I3 ]
- * Function Name : Delay_Ms
- ]9 A$ g: `2 h6 R% t - * Description : delay 1 ms.
8 Q3 X3 X7 R6 K - * Input : dly (ms)
' q' B b; G4 v# \0 N - * Output : None' `) Q# y( Q; g
- * Return : None
6 j6 P3 N4 ?& c5 x: s: t; b - *******************************************************************************/
5 R1 R5 h, R/ J4 u - void Delay_MS(u16 dly)9 {1 S3 E- l% v5 A
- {
" a; o' g d3 b( `6 c2 y V# ^ - u16 i,j;( p, |3 X2 _, Q) a7 x; X
- for(i=0;i<dly;i++)
* u+ Z) Q5 B& s" L - for(j=1000;j>0;j--);9 Y: p2 J+ p; h% L
- }: Y0 {. m: V6 u \
( j7 i- R5 v8 X- /*******************************************************************************& ?- O% t3 C8 }: h. V
- * Function Name : RCC_Configuration6 c, }! Z% {6 T( t" `4 @0 P
- * Description : Configures the different system clocks.
' s5 n% V A7 S2 c3 [+ `" P - * Input : None& A4 k d' s8 n' {1 |: ?' `9 W
- * Output : None H' g h$ @+ L3 d
- * Return : None7 v7 l! Z8 Z! D |2 b
- *******************************************************************************/+ B0 {3 {1 M) a: D" |
- void RCC_Configuration(void)
" W# |) h+ G$ l' W - {2 [0 O7 ?: k2 d; ?! ~* w, E5 m' Q
- //----------使用外部RC晶振-----------
2 {" k2 W) T: X; t - RCC_DeInit(); //初始化为缺省值
! S) B6 |) Z" H* e4 O - RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
, h* c8 Y6 \7 d7 e( v9 y/ ` - while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪
% C/ ^9 x U! K0 x. ~1 X6 ] - ! U- @- J7 ~% q) @1 l
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
- ^% Y( w0 j! }/ A9 u) W1 i5 g - FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait state
9 n/ l& i' W" Q, S: I7 W' t* _ c -
& q6 |" i, Z) Z4 v" ~3 Z - RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK9 X7 n2 c+ I9 |, v/ D9 O8 m) R
- RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK
; `+ _+ |4 o$ `* A( b( q0 p - RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/21 Z- P" }7 G8 Z! o @, Y# {' V
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
9 |. P. y4 A8 B2 ^" h5 y - RCC_PLLCmd(ENABLE); //Enable PLLCLK
( v' n" m' K+ [! c - ! O3 n" N' g; K! X5 J
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
9 N9 G2 D Y5 I+ I$ I1 j - RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock
0 h+ O* a" N# q, A4 u - while(RCC_GetSYSCLKSource()!=0x08); //Wait till PLL is used as system clock source
# s: B q6 C( O3 k -
8 R$ R" Q6 y6 k ? ^+ l - //---------打开相应外设时钟--------------------/ `: j1 }6 M5 a* d3 s
- RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //使能APB2外设的GPIOC的时钟( |8 h% P0 p8 f3 y t& [
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //复用功能时钟开启
6 t6 r+ T- \4 O% O* a# ~# r2 R+ F2 w s# Y - } ]5 G% B# N8 q& A/ w
* ?# A; |' q( O3 r% [1 U: C' h- /*******************************************************************************
- f0 _' Q5 J. c a Q - * Function Name : GPIO_Configuration- n4 C; b1 O2 o* j f2 H+ e3 I% [
- * Description : 初始化GPIO外设0 S. X- w/ Z7 F Z' Z
- * Input : None9 }! w8 k% ^, S D) G
- * Output : None3 D$ M; I) N! |
- * Return : None
& d9 W. E9 K" t! v - *******************************************************************************/, d5 U7 {8 q' F7 r' r" t
- //由电路图可知;配置PC10,PC11引脚
. U0 P" D: u6 q6 \0 J% u r0 l) ^ - void GPIO_Configuration(void)$ g' S# Q" o$ C/ V! q \
- {
4 M7 _9 P& ?# {) G5 F5 A - //CLK:PB5 CLR:PE11 DATA:PE10* u, _0 ]& j% Z. D
- GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量
" z5 E" U1 c: e+ L K! z - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PB.1-' s1 O! m& S' x4 f' q8 b& m9 f
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ' Q* k7 r2 v: ]: i: P- V$ W
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为 "复用推挽输出"
' ^9 n8 S9 f0 x - GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOB寄存器
, N" G/ N" K9 g# ]( W. X% H9 m9 k3 D - + B$ p( C5 L& l. M( j. W
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ; //选择PE.10 PE.11- p: S' P7 E- n: O* d. r
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
( ^) k% L: L4 u* U0 C - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输出模式为 "浮空输入"
0 o# M/ U1 C. n - GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOE寄存器
" e; N7 ~+ v4 Z% F: L) Z: e- D -
% r) `8 o' C0 G; y2 x+ ?, T - //开启时钟 必须在RCC_Configuration中设置
; e# g- e' V$ i; ~" H0 X - * I: {; j; L6 k- j! G$ I# X
-
+ `; c( B+ [# z. y6 p( B - //端口重映射:PC10/PC11
& u. {1 w6 h1 V3 r' o; ]) o* m) |4 K - GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
. Y! g) l, w' ~6 [3 b - }
& L. z# U: ^+ K1 ?$ \
$ Q/ u& u4 L) j! l- void USART3_Configuration(void): r) b8 `& f) _1 x; ~% p
- {
0 J1 r! a3 f( P3 j2 A0 w - USART_InitTypeDef USART_InitStructure;
5 m( M- U9 ~( i# I. | - USART_InitStructure.USART_BaudRate = 9600;4 _6 H) u4 h1 @8 n$ ]" b
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
r: `" F9 j) o. w' N - USART_InitStructure.USART_StopBits = USART_StopBits_1;
6 d! \: t. U' v& V" r2 U - USART_InitStructure.USART_Parity = USART_Parity_No;
+ u, i# c6 u( U+ N( Y) P1 t - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;6 [4 _: {; P6 y9 T1 R& \1 z
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
. G2 L9 x( h- G( l! _) b - ( l: P0 p6 Z1 J; }9 _0 v8 ^& E/ ]6 x
- USART_Init(USART3, &USART_InitStructure);4 x3 A- @! b9 c% Q
4 x8 H5 L, p) |( M- USART_Cmd(USART3, ENABLE); //开启使能
9 b# N. M* E& R5 |! [3 \0 Y C - }" p! w6 Y3 D+ G' c5 K
- 7 M ^% C" v/ ?: s) j( ?$ ~
- /***********************************************************
& r/ S8 w6 g! l3 b- C - name: fputc *
# v& L5 j1 F" ~) L: z - Description:重定向这个c库printf函数,文件流--->串口USART *
; U9 ~* j0 ? Z! N4 B - *
( u; D, x* ~6 b* l/ C - ************************************************************/
. A( m# t' _, A+ v - int fputc(int ch,FILE *f)# D+ M7 l1 j: z: f) s
- {
$ i% G9 \& q3 o3 x! G |: ] - //ch发送给USART1
; Z F/ s$ ?% g" C! b# @ - USART_SendData(USART3, ch);
# l0 s" Y; e$ ~# C Z - //等待发送完毕8 @( {- I" x0 q+ j' ~; t! m
- while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)
) b/ a4 e$ a6 Z# q+ Q - ;
# P9 G# X, ?' k, _' J+ J! H - return ch;6 z9 k ]" e# J- j/ d8 g# q
- }
复制代码
* ~5 s3 o3 {: d5 Q |