你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32——SysTick 时钟 实验

[复制链接]
feixiang20 发布时间:2018-1-15 20:43
上次实验,我们学习了 STM32 的 IO 口作为输出的使用,通过管脚模拟pwm控制蜂鸣器,使用到的延时函数都是通过 软件产生的延时,延时是不精确的。这一章,我们将通过另外这次实验讲述 STM32 内部系统滴答定时器。在本次实验中,我们将利用 SysTick 产生的延时函数,实现 LED 流水灯。通过本次实验的学习,你将了解 STM32 SysTick 定时器的用。 本章分为以下学习目标:
8 M5 y0 H6 D' F+ g2 q- I1、明白系统滴答定时器。  b- ]2 z) T6 b$ @! i
2、学会配置系统滴答定时器延时。( F7 v: R  k  W- Q; P6 u

( @9 @# W0 E- ~) ~: r4 M* asystic k  定时器简述
6 N# n; H% X/ M  k: }  Y' m( rsystick 定时器是包含在 Cortex-M3 内核里面,它是捆绑在 NVIC 中。它是 24 位倒计数的定时器,当定时器计数到 0 的时候,将从 RELOAD 寄存器中自动重 装定时器初值,如果开启中断的话,同时它还是产生异常中断信号。 我们知道,定时器还必须要有一个时钟来驱动,而 systick 定时器的时钟来源 是来自系统时钟,不过它的时钟可以选择成直接取自系统时钟,还可以将系统时 钟8 分频之后再赋给 systick 定时器。
# s& D  K! A3 f+ C
; K' }3 n: G0 a2 w) _( usystick  定时器的配置步骤 systick 定时器的操作可以分为 4 步:
. d+ ~' I4 r" `( }8 b1)配置 systick 定时器的时钟源。3 Q' K  y7 M7 @
2) 配置systick 定时器的重装初始值。 & X3 J3 I$ G7 s9 S6 D& N# P2 r
3) 清零 systick 定时器计数器的值。  ]% ^% F2 y  v" A, z1 y
4) 打开 systick 定时器。
" g  v! z! r9 B: V+ H& N: l% U4 B6 ~! s. j. n' |, i
systick  定时器的寄存器介绍$ a: z8 {/ ~1 \7 r& r
在 STM32 的  库函数中没有给 systick 定时器配置有相应的函数库,我们要操作这个定时器的话,我们首先要了解一下这个定时器的寄存器。其实systick 定时器的寄存器很简单,它只有四个寄存器:1.CTRL 寄存器! B1 S/ C! L  S8 n% h4 A
2.LOAD  寄存器
6 O, b! I/ u, Z8 R8 K3.VAL  寄存器
# a# U4 K- L; r( K+ _; T+ k- F4.CALIB 寄存器* H% U: B6 ~$ a

+ [; E! ~7 q( K1 }
' B5 z7 R* ?$ i在 core_cm3.h 定义了一个 Systick_Config()的初始化函数:- X% o! m5 t% l9 g; N6 B
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
3 z4 `* @& i/ T$ J, t$ ^/ m{' I* u7 e8 w! ^8 k% j
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload
4 L8 M- `; H( ?! }; a! l1 s2 Yvalue impossible 如果重装初始值大于最大值返回错误 */
& G0 X/ O% f. S# h, M0 `8 V  RSysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set
) h5 n% c, e6 j" ^reload register 设置重装初始值 */
5 ^! e0 |- `5 Z3 j7 ?) SNVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set
( x: Z' l2 G' F! i/ L2 q, |Priority for Cortex-M0 System Interrupts 设置中断优先级 */
0 w( o3 ?+ N" [, \' Z: _- [SysTick->VAL = 0; /* Load
) H% g5 P8 C- s1 o! ethe SysTick Counter Value 清零计数器 */
& A: J0 N+ l% c# a6 nSysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
$ x* M" z; A& `0 b- o- ESysTick_CTRL_TICKINT_Msk |/ k9 w- d: L; j$ k6 f
SysTick_CTRL_ENABLE_Msk;! g& L3 ]! ]6 r! N, k0 ]
/* Enable SysTick IRQ and SysTick Timer 选择系统时钟做时钟来源、打开中
, T6 F4 T) d0 _" Y4 k: L断使 能、打开计数器 */
- {6 P% @! X- l% R/ Hreturn (0); /* 返回成功信息 Function successful */) e( N3 }; @: Y0 B2 ]
}
! M, Q3 A5 B  M7 o% [2 A' d这个初始化函数,输入一个重装初始值。然后帮你将定时器时钟设置为系统 时钟,然后打开计数器并同时打开中断使能。 在库中,这个 systick 定时器的中断函数它也帮你写好了,只是定义了 一个空的中断函数,它的中断函数在 stm32f10x_it.c中。$ M9 Z) _+ \$ f9 B
9 Z' }  e0 l1 _+ R0 ]
systick  定时器的定时微秒函数3 o3 I5 ]. z. n
void delay_us(u32 i)
& y' c. H% D# C{# J2 r: m0 J$ k1 J' U. _& p, X
u32 temp;# H9 e  L5 |; H- V3 i8 @. C
SysTick->LOAD=9*i;  //设置重装数值, 72MHZ 时% N, J* ?  W* A* c4 F
SysTick->CTRL=0X01; //使能,减到零是无动作,采用外部时钟源# [( Z8 }: {% s
SysTick->VAL=0; //清零计数器
1 e/ ?- G" V8 z  |& a- P* E+ g6 n/ Qdo) m+ g* {+ h8 ]$ I; Z2 o+ c
{& N  a: z; v4 s3 N3 T0 V8 L% b. n
temp=SysTick->CTRL; //读取当前倒计数值
% B; y) J6 k: ?}
* t; R. @0 X# H' [. Wwhile((temp&0x01)&&(!(temp&(1<<16)))); //等待时间到达
( j1 S3 d, b+ u* q6 |2 k0 cSysTick->CTRL=0; //关闭计数器! f, D4 x& l% {6 U. l
SysTick->VAL=0; //清空计数器' |. g, ?4 A# @; m+ M! F; v6 f
}+ W7 l( _$ X* t$ j
8 d' o/ I5 t  T- D/ }
systick  定时器的定时毫秒函数. x  T- _  k; g, Q+ i
void delay_ms(u32 i)
+ {5 s( C0 x% k6 B: y5 n1 A{
' e9 f8 ]/ r0 b  V* l8 g8 Mu32 temp;
4 z  Y% m; e+ {2 u! {' TSysTick->LOAD=9000*i;  //设置重装数值, 72MHZ 时
! J( q+ t3 Y9 H3 ISysTick->CTRL=0X01; //使能,减到零是无动作,采用外部时钟源" f0 z& M9 B- A
SysTick->VAL=0; //清零计数器
* R! m7 E% W4 h! ?do
: w9 a* Q$ w% D; F6 l4 n{3 g( o. e6 }! _1 |, M" z
temp=SysTick->CTRL; //读取当前倒计数值
( e8 D8 V- E1 F% y}6 O2 t2 I' C) a3 w
while((temp&0x01)&&(!(temp&(1<<16)))); //等待时间到达
) U% B- Y5 M; Y& H+ i# YSysTick->CTRL=0; //关闭计数器) n( ?/ I' |( r7 p1 S8 A
SysTick->VAL=0; //清空计数器  ]7 ^+ c- M# J: ~: V& j
}
( e: g% U8 I! B% S" k% e! W% W: ?, x" C& D( W1 J
上面两个延时函数会在以后程序中经常调用我们可以把这两个函数放到delay.c中,通过调用delay.h便可使用延时函数。7 O9 R7 g  e' Y9 u
" ]: C, m4 o+ S3 h* a% f/ |
最后就是主程序了,利用延时函数做个简单的流水。8 [& z& C& ^0 j3 h- B5 L
int main()" |4 |! K/ u' Y8 k" ]2 q7 h, W
{
+ m7 K9 l; t/ ]u8 i;
! j) O. M! u( j0 Wled_Init();  //LED 端口初始化
: N, y% v" q" l( S8 C1 R; Rwhile(1)
$ z  D. \' Q/ g3 |1 ^8 Y5 q{- Q9 `" q% T( G/ M
for(i=0;i<8;i++) //从左到右
3 }1 d3 O2 O" @. `5 v; `; w{
' d6 ]+ V1 ?+ |* m( a- m/ EGPIO_Write(GPIOB,(u16)~(0x01<<i));, F2 C: I  A! U1 Z3 u4 {
delay_ms(1000); //精确延时 1 秒
) ]+ i' h# Z" R% p) @1 t- |}
. X3 l, b. c" ?2 Q5 m; w; `}
; A  X! z. r$ i  T1 I}
3 ^+ E- W* ^4 c/ W9 j9 D$ N8 ], K# S# \( ?1 u0 a& S
好了本次的systick延时函数就到了,欢迎大家的指正。
: _$ |$ U) {3 N  G) F6 a. u3 b' \7 R. C+ S: y! h  v4 J( q9 u" g7 L
赞 收藏 评论3 发布时间:2018-1-15 20:43

举报

3个回答
anywill 回答时间:2018-1-15 21:43:09
占楼
zhjb1 回答时间:2018-1-16 08:10:38
思路明确,学习了。如能加点如何利用SysTick这段加入自己的小代码就更好了。
大陶 回答时间:2018-1-16 11:29:03
是不是要 把这个.h文件加入#include "core_cm3.h"?
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版