|
上次实验,我们学习了 STM32 的 IO 口作为输出的使用,通过管脚模拟pwm控制蜂鸣器,使用到的延时函数都是通过 软件产生的延时,延时是不精确的。这一章,我们将通过另外这次实验讲述 STM32 内部系统滴答定时器。在本次实验中,我们将利用 SysTick 产生的延时函数,实现 LED 流水灯。通过本次实验的学习,你将了解 STM32 SysTick 定时器的用。 本章分为以下学习目标: 1、明白系统滴答定时器。 b- ]2 z) T6 b$ @! i 2、学会配置系统滴答定时器延时。( F7 v: R k W- Q; P6 u systic k 定时器简述 systick 定时器是包含在 Cortex-M3 内核里面,它是捆绑在 NVIC 中。它是 24 位倒计数的定时器,当定时器计数到 0 的时候,将从 RELOAD 寄存器中自动重 装定时器初值,如果开启中断的话,同时它还是产生异常中断信号。 我们知道,定时器还必须要有一个时钟来驱动,而 systick 定时器的时钟来源 是来自系统时钟,不过它的时钟可以选择成直接取自系统时钟,还可以将系统时 钟8 分频之后再赋给 systick 定时器。 systick 定时器的配置步骤 systick 定时器的操作可以分为 4 步: 1)配置 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 定时器。 % 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 寄存器 3.VAL 寄存器 4.CALIB 寄存器* H% U: B6 ~$ a 在 core_cm3.h 定义了一个 Systick_Config()的初始化函数:- X% o! m5 t% l9 g; N6 B static __INLINE uint32_t SysTick_Config(uint32_t ticks) {' I* u7 e8 w! ^8 k% j if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible 如果重装初始值大于最大值返回错误 */ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register 设置重装初始值 */ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts 设置中断优先级 */ SysTick->VAL = 0; /* Load the SysTick Counter Value 清零计数器 */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_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 选择系统时钟做时钟来源、打开中 断使 能、打开计数器 */ return (0); /* 返回成功信息 Function successful */) e( N3 }; @: Y0 B2 ] } 这个初始化函数,输入一个重装初始值。然后帮你将定时器时钟设置为系统 时钟,然后打开计数器并同时打开中断使能。 在库中,这个 systick 定时器的中断函数它也帮你写好了,只是定义了 一个空的中断函数,它的中断函数在 stm32f10x_it.c中。$ M9 Z) _+ \$ f9 B 9 Z' } e0 l1 _+ R0 ] systick 定时器的定时微秒函数3 o3 I5 ]. z. n void delay_us(u32 i) {# 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; //清零计数器 do) m+ g* {+ h8 ]$ I; Z2 o+ c {& N a: z; v4 s3 N3 T0 V8 L% b. n temp=SysTick->CTRL; //读取当前倒计数值 } while((temp&0x01)&&(!(temp&(1<<16)))); //等待时间到达 SysTick->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) { u32 temp; SysTick->LOAD=9000*i; //设置重装数值, 72MHZ 时 SysTick->CTRL=0X01; //使能,减到零是无动作,采用外部时钟源" f0 z& M9 B- A SysTick->VAL=0; //清零计数器 do {3 g( o. e6 }! _1 |, M" z temp=SysTick->CTRL; //读取当前倒计数值 }6 O2 t2 I' C) a3 w while((temp&0x01)&&(!(temp&(1<<16)))); //等待时间到达 SysTick->CTRL=0; //关闭计数器) n( ?/ I' |( r7 p1 S8 A SysTick->VAL=0; //清空计数器 ]7 ^+ c- M# J: ~: V& j } : ?, 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 { u8 i; led_Init(); //LED 端口初始化 while(1) {- Q9 `" q% T( G/ M for(i=0;i<8;i++) //从左到右 { GPIO_Write(GPIOB,(u16)~(0x01<<i));, F2 C: I A! U1 Z3 u4 { delay_ms(1000); //精确延时 1 秒 } } } $ N8 ], K# S# \( ?1 u0 a& S 好了本次的systick延时函数就到了,欢迎大家的指正。 ' \7 R. C+ S: y! h v4 J( q9 u" g7 L |
占楼 |
| 思路明确,学习了。如能加点如何利用SysTick这段加入自己的小代码就更好了。 |
| 是不是要 把这个.h文件加入#include "core_cm3.h"? |
微信公众号
手机版