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

一、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"头文件复制到项目的\Lib\inc文件夹下,将"misc.c"程序文件复制到\Lib\src文件夹下;

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<<j )

                       PCout(j) = 0;

                   else

                       PCout(j) = 1;

              delay_ms(1000);

         }

     }

}

猜你喜欢

转载自blog.csdn.net/fanxp66/article/details/80242212
今日推荐