×
单片机 > 单片机程序设计 > 详情

在STM32项目中使用SysTick实现延时(STM32_06)

发布时间:2020-06-18 发布时间:
|

一、SysTick


Sys-系统,Tick-滴答声,系统滴答滴答很形象地表示了它是一个系统节拍器。SysTick 是一个集成在Cortex内核里的24位的倒计数定时器,当计到0时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。


SysTick的作用。


SysTick主要有以下几个作用:


1、产生操作系统的时钟节拍;


当RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。


2、便于不同处理器之间程序移植


因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。


3、作为一个闹铃测量时间


可以用作闹钟,作为启动一个特定任务的时间依据。它作为一个闹铃,用于测量时间。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。


二、项目配置


该项目以https://blog.csdn.net/fanxp66/article/details/80227611为基础,对程序中的延时替换为使用SysTick来实现精准延时。


1、将库函数库中的"misc.h"头文件复制到项目的Libinc文件夹下,将"misc.c"程序文件复制到Libsrc文件夹下;


2、将"misc.c"文件添加到项目的"Lib"组中;


3、在项目文件夹下新建一个"Public"文件夹,在项目中添加"Public"组;


4、新建"SysTick.h"文件和"SysTick.c"文件,将"SysTick.c"文件添加到项目的"Public"组中;


5、修改项目配置,将路径"Public"添加到"C/C++"的"Include Paths"中。


三、编程


在本程序中,利用SysTick进行精准1秒定时,系统时钟初始为72MHz,选择SYSCLK/8分频后得到的9MHz作为SysTick的输入计时时钟,当设置计数值为9000000时,实现1秒定时。


在使用SysTick时有查询式和中断方式两种,使用查询方式时,首先为SysTick选择时钟源和设置计数值并启动计数,然后查询计数完成状态位,状态位为1时表示计数完成;使用中断方式时要为15号异常设置中断服务程序处理。这里使用查询方式。


SysTick编程用到以下寄存器:


CTRL          SysTick 控制和状态寄存器


LOAD         SysTick 重装载值寄存器


VAL            SysTick 当前值寄存器


CALIB         SysTick 校准值寄存器


在"core_cm3.h"文件中定义了:


typedef struct


{


  __IO uint32_t CTRL;    /*地址偏移: 0x00  SysTick 控制和状态寄存器*/


  __IO uint32_t LOAD;    /*地址偏移: 0x04  SysTick 装载计数值寄存器*/


  __IO uint32_t VAL;     /*地址偏移: 0x08  SysTick当前计数值寄存器*/


  __I  uint32_t CALIB;   /*地址偏移: 0x0C  SysTick 校准值寄存器*/


} SysTick_Type;


#define SysTick   ((SysTick_Type *)SysTick_BASE)   /*SysTick 配置结构体  */


    以后就可以通过对SysTick结构体指针操作SysTick的寄存器。


1、SysTick编程步骤。


① 为SysTick设置时钟源


在STM32的库函数文件中有"misc.h"头文件和"misc.c"程序文件定义了相应的宏和库函数。


在"misc.h"头文件有定义:


#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)


#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)


在"misc.c"程序文件定义函数


void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)


{


  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));


  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)


  {


    SysTick->CTRL |= SysTick_CLKSource_HCLK; /*将CTRL寄存器的位2设为1*/


  }


  else


  {


    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; /*将CTRL寄存器的位2设为0*/


  }


}


在本程序中使用8分频的系统时钟,所以调用函数如下:


SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);


② 为SysTick 装载计数值寄存器设置计数值;


③ 对SysTick当前计数值寄存器置0;


④ 通过对SysTick的CTRL寄存器的位0置位使能SysTick定时器。


2、编程实现


在程序中,为了方便使用,定义了"SysTick.h"头文件和"SysTick.c"程序文件(这两个文件已经在前面“项目配置”部分创建)。


"SysTick.h"头文件内容如下:


#ifndef __SysTick__H


#define __SysTick__H


#include "stm32f10x.h"


void SysTick_Init(u8 SYSCLK);


void delay_us(u32 nus);


void delay_ms(u16 nms);


"SysTick.c"程序文件内容如下:


#include "SysTick.h"


#include "misc.h"


u8 fac_us = 0;


u16 fac_ms = 0;


 


void SysTick_Init(u8 SYSCLK)


{


     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);


     fac_us = SYSCLK / 8;


     fac_ms = (u16)fac_us*1000;


}


 


void delay_us(u32 nus)


{


     u32 temp;


     SysTick->LOAD = nus * fac_us;


     SysTick->VAL = 0;


     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;


     do{


         temp = SysTick->CTRL;


     }while((temp&0x01)&&(!(temp&(1<<16))));


     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;


     SysTick->VAL = 0;


}


void delay_ms(u16 nms)


{


     u32 temp;


     SysTick->LOAD = nms * fac_ms;


     SysTick->VAL = 0;


     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;


     do{


         temp = SysTick->CTRL;


     }while((temp&0x01)&&(!(temp&(1<<16))));


     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;


     SysTick->VAL = 0;


}


3、在主函数中使用定时


#include "stm32f10x.h"


#include "stm32f10x_rcc.h"


#include "led.h"


#include "SysTick.h"


 


int main()


{


     u32 i,j;


     //共阳数码管'0'-'9'显示码


     u32 LED[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};


     LED_Init();


     SysTick_Init(72);  //系统时钟72MHz


     while(1)


     {


         for(i=0;i<10;i++)


         {


              //根据LED[n]数组的值决定数码管各个段位的显示


              for(j=0; j<8; j++)


                   if( ~(LED[i]) & 0x1<


                       PCout(j) = 0;


                   else


                       PCout(j) = 1;


              delay_ms(1000);


         }


     }


}



关键字:STM32项目  SysTick  延时


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容