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

发布者:芳华逝水最新更新时间:2019-05-29 来源: eefocus关键字:STM32项目  SysTick  延时 手机看文章 扫描二维码
随时随地手机看文章

一、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  延时 引用地址:在STM32项目中使用SysTick实现延时(STM32_06)

上一篇:使用STM32GPIO读取按键实现按键操作(STM32_08)
下一篇:通过位带地址操作GPIO在数码管显示数字(STM32_05)

推荐阅读最新更新时间:2024-11-01 11:10

STM32设置内核定时器延时us
记录 1.查找系统嘀嗒定时器,根据 《STM32F4xx-Cortex_-M4内核参考手册.pdf》来查看寄存器, 并结合core_cm4.h。 系统定时器的时钟源=21Hz,完成21000000次计数的时候,就代表说1秒时间的到达。 21000000/1000000=21,也代表说只要完成21次计数就是1微秒的时间。SysTick- LOAD决定了延时的时间。 STTM32F407为例,用寄存器写延时函数: 需要注意的是把STM32f4xx.h文件中的HSE修改为8000000,参数因子PLL_M修改为8 时钟源来源于21 Hz 最大延时时间= 2*24 1 -21000000= 798.91ms. 时钟源来源于16
[单片机]
<font color='red'>STM32</font>设置内核定时器<font color='red'>延时</font>us
基于单片机AT89C51的时间/位移换向控制器设计
引言 在实际生产过程中,常常要用到具有自动换向功能的控制部件,如机械加工中的往返运行(位移),直流电源的正反向输出,电动机的正反转运行等现象,都是当正向(或反向)运行到一定时间或一定位置时,自动换为反向(或正向)运行,周而复始的过程。实现这一过程的自动化,就是设计一套控制电路,再配以位移传感器或时间继电器。目前市场现有的时间继电器虽然可以用多个组合来满足一些使用场合的要求,但仍存在着重复计时误差大,稳定可靠运行性不高,使用不方便灵活等问题。为此,笔者研发了以单片机为核心组成的时间/位移换向控制器SWHX-1,该系统具有成本低等特点,可完全且克服以上不足。 电路组成及工作原理 SWHX-1的内部电路如图1所示。该系统分为输入输
[单片机]
如何正确计算多重循环延时程序的延时时间
题目:MCS-51单片机,使用 6MHz 晶振,一个机器周期为 2us,计算出下列程序的延时时间。 DEL: MOV R5, #100 DEL0: MOV R6, #200 DEL1: MOV R7, #248 DEL2: DJNZ R7, DEL2 DJNZ R6, DEL1 DJNZ R5, DEL0 RET 最佳答案: 题目中的答案是错的。应该是:19 960 606 us。 本题目的程序,共有三重循环,耗时的正确计算方法,可见下图。 后记: 能够精确计算程序的执行时间,是汇编语言的长处。而用C语言编写程序,执行的时间只能进行估算和测试。 但是有很多网友,都把这两者弄混了:   在用C语言编程的时候,
[单片机]
如何正确计算多重循环<font color='red'>延时</font>程序的<font color='red'>延时</font>时间
最高效率使用单片机,放弃程序中的延时函数
我是PC机底层编程转过来的,以前从来没接触过单片机,五个月前学习AVR,在这里学到很多东西。但也意识到电子工程师们的硬件编程思想与PC机底层编程思想上的很多不同,引发了一些思考。我说一说,供大家参考,只为学习,无意争论。 我第一次看到教程里Delay()函数的代码时我吓了一跳,竟然让单片机空转以实现和外界同步,这怎么可能? 试想,如果PC机CPU空转一秒,那么音乐会断一秒、画面会停顿一秒、下载文件会断一秒,这怎么可行? 我看到很多单片机程序,它们的单片机99.9%的工作时间都在打空转,99.9%大家可能感到有些危言耸听,那就让我们算一算: 已内部8M频的AVR单片机来说,单指令周期仅为1/8 = 0.125us,那一毫秒
[单片机]
51单片机教程:按键的定时器消抖(有延时的程序不是好程序
按键消抖原理 一、首先来回顾一下按键延时消抖 按键由于是机械结构,按下的时候难免产生抖动,一般抖动会在按下的时候与松开的时候产生,抖动时间大概是10ms 于是针对按键抖动就有了延时消抖的一种简单的解决方法: 二、按键消抖代码 方法一: 按下按键损耗的时间取决于按下按键到松开的时间,至少10ms,按下按键后CPU不再执行其他指令,直到按键松开,应用能力弱 代码作用:按下按键led状态取反,按下按键需要等待松开 #include reg51.h sbit key=P1^0; //定义key为P1.0 sbit led=P2^0; //定义LED为P2.0 void delay_ms(unsigned int t)
[单片机]
51单片机教程:按键的定时器消抖(有<font color='red'>延时</font>的程序不是好程序
MSP430F5438内部延时函数的用法
今天看示例程序中出现了__delay_cycles()这个函数,在查找msp430x54x.h这个头文件的时候,发现这个头文件中没有该函数的声明,原来这个函数已经在IAR这个编译器中集成,这里总结一下__delay_cycles();这个函数的具体用法 第一步,复制代码: #define CPU_F ((double)8000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((lo
[单片机]
STM32学习笔记——系统定时器SysTick的使用
//Cortex系统定时器SysTick提供1个24位、降序、零约束、写清除的计数器,具有灵活的控制机制 #include stm32f10x_lib.h GPIO_InitTypeDef GPIO_InitStructure; //定义用于初始化配置GPIO的结构体变量 static vu32 TimingDelay; //定义为volatile类型 ErrorStatus HSEStartUpStatus; //定义枚举类型的错误状态 void TimingDelay_Decrement(void); void RCC_Configuration(void); void
[单片机]
STM32的三种延时方法的代码实现_纯软件延时, 系统定时器延时, 定时器延时
/* 外部调用: delay_init(72); //系统主频, 单位为MHZ, 仅对 SYSTICK_DELAY 有效 delay_ms(1000); */ #include stm32f10x.h //#define SOFT_DELAY //纯软件延时 //#define SYSTICK_DELAY //系统定时器延时 #define TIMER_DELAY //定时器延时 #ifdef TIMER_DELAY #define TIMER_DELAY TIM4 #define TIMER_DELAY_PERIOD 1000 #de
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved