zoukankan      html  css  js  c++  java
  • 基于Systick系统时钟延时的LED闪烁灯

    1、回顾我们的51 单片机编程,当我们需要做系统延迟的时候,最常采用的一
    种方式就是使用for 循环的空语句等待来实现。

    当然,在STM32 里面也可以这么实现。但是在STM32 的Cortex 内核里面,有个比其更加精准的定时器专业用于

    系统定时,我们称之为Cortex 系统定时器(SysTick,系统滴答)。

    Systick 就是一个定时器而已,只是它放在了NVIC(中断事件)中,

    主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。

    这样,只要设置好其中断的时间,就可以每隔一定时间跳入其处理程序,

    通过这种方式,我们可以做一些分时的任务处理。

    然而,由于我们刚刚接触STM32,因此我们本课程内容,仅仅是

    用其做一些延迟函数的处理。可能有些同学有疑问,微控制器的定时器资源一般

    比较丰富,比如STM32 存在8 个定时器,为啥还要再提供一个SYSTICK?原因就
    是所有基于ARM Cortex_M3 内核的控制器都带有SysTick 定时器,这样就方便了
    程序在不同的器件之间的移植。而使用RTOS 的第一项工作往往就是将其移植到
    开发人员的硬件平台上,由于SYSTICK 的存在无疑降低了移植的难度。具体
    Systick 的概述,请参考《Cortex-M3 权威指南》179 页。

    关于SysTick 的编程
    流程如下:
     配置系统时钟;
     配置SysTick;
     写SysTick 中断处理函数;
     编写delay 延迟函数;

    第一步:

    先让我们来设置系统时钟。关于系统时钟的配置,我们可以直接使
    用默认的固件库函数“void SystemInit(void);”,这个函数在固件库手册上面
    是没有的,一旦使用默认配置之后,整个STM32 的系统时钟就会被配置成:
    SYSCLK(系统时钟) = 72MHZ(系统最高允许时钟);
    AHB 总线时钟= 72MHZ(AHB 最高允许时钟);
    APB1 总线时钟= 36MHZ(APB1 最高允许时钟);
    APB2 总线时钟= 72MHZ(APB2 最高允许时钟);

    第二步:

    配置SysTick。我们在设置SysTick 的时候,只用到“core_cm3.h”
    文件的函数“__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)”。
    这个函数在固件库里面是没有介绍的,因为这个函数是在“core_m3.h”里面定
    义的,所以不属于STM32 固件库的范畴。参考《STM32F10xxx 参考手册》第80
    页的STM32 系统时钟框图,我们可以知道,系统时钟(AHB,此时为72MHz)经8
    分频或者不分频之后产生的时钟给Systick 作为时钟震荡源,因此此时的
    Systick 默认为频率为72MHz,如果需要使用8 分频之后的频率,可以使用函数
    “SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);”,因此我们只
    需要把Systick 设置成72000 时(计算方式:(1/72000000Hz)*72000 次=1ms),
    就能产生1ms 时间基准,说白了就是一个中断信号。

    见函数void Systick_Init(void)配置

    第三步:

    编写Systick 的中断处理函数。对于STM32 所有的中断处理函数,
    我们都可以在对应的“startup_stm32f10x_xx.s”里面找到其入口。比如,在做
    Systick 中断处理的时候,我们选择的入口地址就是“SysTick_Handler”。因
    此,我们可以写如下的代码,如程序片段6 所示。同时,需要把“stm32f10x_it.c”
    里面的“SysTick_Handler”入口屏蔽,不然会报错。

     1 __IO uint32_t TimingDelay;
     2 void TimingDelay_Decrement(void)
     3 {
     4 if (TimingDelay != 0x00)
     5 {
     6 TimingDelay--;
     7 }
     8 }
     9 void SysTick_Handler(void)
    10 {
    11 TimingDelay_Decrement();
    12 }

    第四步,写delay_ms函数

    1 void delay_ms(__IO uint32_t nTime)//延迟函数,设置为US
    2 {
    3 TimingDelay = nTime;//时钟滴答数
    4 while(TimingDelay != 0);
    5 }

    以上只是Systick的配置,下面是一个完整实现LED灯闪烁的代码

    下面包含四个文件:分别是mian.c文件、timer.c文件、timer.h文件、led.c文件、led.h文件

    mian.c文件、

     1 #include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>
     2 #include "timer.h"
     3 #include "led.h"
     4 int main(void)
     5 {
     6     SystemInit();//初始化系统,使得系统频率为72MHZ
     7     systick_init();//配置Systick,使得1ms产生
     8     led_gpio_init();//LED灯的配置,要用到LED灯就要配置
     9     while(1)
    10     {
    11         GPIO_SetBits(GPIOB,GPIO_Pin_5);
    12         delay_ms(1000);//延时1s
    13         GPIO_ResetBits(GPIOB,GPIO_Pin_5);
    14         delay_ms(1000);
    15     }
    16 }

    timer.c文件、

     1 #include "timer.h"
     2 #include "stm32f10x.h"
     3 __IO uint32_t TimingDelay;//相当于宏定义一个TimingDelay
     4 void systick_init()
     5 {
     6     //配置Systick重载值,系统时钟为72MHZ
     7     //设置72000,中断时间:72000*(1/72000000)=1ms
     8     //有返回值,返回0则装在成功
     9     if(SysTick_Config(72000)==1)
    10     {
    11         while(1);
    12             
    13     }
    14 }
    15 
    16 
    17 
    18 void TimingDelay_Decrement(void)
    19 {
    20     if(TimingDelay !=0x00)
    21     {
    22         TimingDelay--;
    23     }
    24 }
    25 /*中断处理函数,中断一次减1ms*/
    26 void SysTick_Handler(void)
    27 {
    28     TimingDelay_Decrement();//调用上面的函数
    29 }
    30 
    31 
    32 
    33 void delay_ms(__IO uint32_t nTime)
    34 {
    35     TimingDelay = nTime;//时钟滴答数
    36     while(TimingDelay !=0);
    37 }
    38     

    注意:这里需要做一个细节!!

    在stm32f10x_it.c文件里面的void SysTick_Handler(void)这个函数注释掉。

    看截图:

    timer.h文件、

     1 #ifndef _TIMER_H_
     2 #define _TIMER_H_
     3 
     4 #include "stm32f10x_tim.h"
     5 #include "stm32f10x_rcc.h"
     6 #include "stm32f10x_it.h"
     7 #include "misc.h"
     8 
     9 extern __IO uint32_t TimingDelay;
    10 
    11 void systick_init();
    12 void delay_ms(__IO uint32_t nTime);
    13 #endif

    led.c文件、

     1 #include "led.h"
     2 #include "stm32f10x_gpio.h"
     3 //GPIO初始化
     4 void led_gpio_init()
     5 {
     6     GPIO_InitTypeDef gpio;
     7     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
     8     gpio.GPIO_Mode=GPIO_Mode_Out_PP;
     9     gpio.GPIO_Pin=GPIO_Pin_5;
    10     gpio.GPIO_Speed=GPIO_Speed_50MHz;
    11     GPIO_Init(GPIOB,&gpio);
    12 }

    led.h文件

    1 #ifndef _LED_H_
    2 #define _LED_H_
    3 
    4 
    5 void led_gpio_init();
    6 
    7 #endif
  • 相关阅读:
    QuickSort
    Java细节
    Java
    Prime
    apache和tomcat有什么不同,为什么要整合apache 和tomcat?
    java线程面试题及答案
    Struts2中的ModelDriven机制及其运用
    Java中instanceof关键字的用法总结
    spring特点与好处
    spring与struts有什么区别?
  • 原文地址:https://www.cnblogs.com/kinson/p/7967332.html
Copyright © 2011-2022 走看看