- 认识一下systick
Cortex-M3在内核部分 包含了一个简单的定时器——SysTick timer.在STM32中SysTick 以 HCLK(AHB时钟)或HCLK/8 作为运行时钟。SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在中断向量表中有它的一席之地。SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
- systick工作分析
SysTick 是一个24位的定时器,即一次最多可以计数2^24 个时钟脉冲,这个脉冲计数值被保存到 当前计数值寄存器STK_VAL (SysTick current valueregister) 中,只能向下计数,每接收到一个时钟脉冲STK_VAL的值就向下减1,直至0,当STK_VAL的值被减至0时,由硬件自动把重载寄存器STK_LOAD(SysTick reload value register)中保存的数据加载到STK_VAL,重新向下计数。当STK_VAL的值被计数至0时,触发异常,就可以在中断服务函数中处理定时事件了。
当然,要使SysTick进行以上工作必须要进行SysTick进行配置。它的控制配置很简单,只有三个控制位和一个标志位,都位于寄存器STK_CTRL(SysTick control and status register )中。
Bit0: ENABLE
为SysTick timer 的使能位,此位为1的时候使能SysTick timer,此位为0的时候关闭SysTick timer。
Bit1:TICKINT
为异常触发使能位,此位为1的时候并且STK_VAL计数至0时会触发SysTick异常,此位被配置为0的时候不触发异常
Bit2:CLKSOURCE
为SysTick的时钟选择位,此位为1的时候SysTick的时钟为AHB时钟,此位为0的时候SysTick时钟为AHB/8(AHB的八分频)。
Bit16:COUNTFLAG
为计数为0标志位,若STK_VAL计数至0,此标志位会被置1。 与SysTick控制相关的所有寄存器如图 0-2,其中上面没有介绍的STK_CALIB寄存器是用于校准的,不常用。
- 实例
实验要求:使开发板上的3个LED等循环亮灭,周期是0.5秒。使用SYSTICK控制定时。
硬件图:
led.h程序
led.c程序#ifndef __LED_H #define __LED_H #include "stm32f10x.h" #define LED1_ON GPIO_SetBits(GPIOB, GPIO_Pin_5); #define LED1_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_5); #define LED2_ON GPIO_SetBits(GPIOD, GPIO_Pin_6); #define LED2_OFF GPIO_ResetBits(GPIOD, GPIO_Pin_6); #define LED3_ON GPIO_SetBits(GPIOD, GPIO_Pin_3); #define LED3_OFF GPIO_ResetBits(GPIOD, GPIO_Pin_3); void LED_GPIO_Concig(void); #endif
#include"led.h" void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO初始化结构体GPIO_InitStructure RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD ,ENABLE);//开启RCC时钟 /*对LED的IO口进行设置*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_3 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB ,&GPIO_InitStructure); GPIO_Init(GPIOD ,&GPIO_InitStructure); /*是LED灭*/ GPIO_ResetBits(GPIOB,GPIO_Pin_5); GPIO_ResetBits(GPIOD,GPIO_Pin_3); GPIO_ResetBits(GPIOD,GPIO_Pin_6); }
SysTick.h程序
#ifndef __SYSTICK_H #define __SYSTICK_H #include "stm32f10x.h" void SysTick_Init(void); void Delay(__IO u32 nTime); #endif /* __SYSTICK_H */
SysTick.c程序
#include "SysTick.h" static __IO u32 TimingDelay; void SysTick_Init(void) { if (SysTick_Config(SystemCoreClock / 100000)) //10us中断一次 { /* Capture error */ while (1); } SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; } void Delay(__IO u32 nTime) { TimingDelay = nTime; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; while(TimingDelay != 0); } /*中断程序*/ void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } }
SysTick_Config()第1行代码是检查输入参数ticks,因为ticks是脉冲计数值,要被保存到重载寄存器STK_LOAD寄存器中,再由硬件把STK_LOAD值加载到 当前计数值寄存器STK_VAL使用的,STK_LOAD和STK_VAL都是24位的,所以当输入参数ticks大于其可存储的最大值时,将由这行代码检查出错误返回。ticks的最大值为2^24。
定时器时间计算
现在回到函数SysTick_Init(),在调用SysTick_Config()函数时,向它输入的参数为:SystemCoreClock / 100000 ,SystemCoreClock 为定义了系统时钟(SYSCLK)频率的宏,即等于AHB的时钟频率,AHB都是
被配置为72MHz的,也就是这个SystemCoreClock 宏展开为数值7200 0000。
由此我们可以算出定时的时间,下面为计算公式:
T=ticks*(1/f)
T 为要定时的总时间。
ticks为SysTick_Config()的输入参数。
1/ f 即为SysTick timer使用的时钟源的时钟周期,f为该时钟源的时钟频率,当时钟源确定后为常数。
main.c#include "stm32f10x.h" #include "SysTick.h" #include "led.h" int main(void) { LED_GPIO_Config(); SysTick_Init(); while (1) { LED1_ON; Delay(50000);//0.5s LED1_OFF; LED2_ON; Delay(50000); LED2_OFF; LED3_ON; Delay(50000); LED3_OFF; } }
stm32之systick
最新推荐文章于 2024-08-27 15:16:20 发布