stm32f407
+ -

STM32F407ZG Systick定时器及应用

2022-01-02 9 0

Systick是系统定时器,对于CORTEX M3和M4的内核芯片,都有一个Systick定时器。
Systick定时器可以认为是系统主频(如STM32F407ZG为168M的时钟滴答)的实时计数。

Systick定时器的用法

Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS心跳时钟。

Systick定时器的用法

  • Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息(循环进行重载计数,计数到0然后再重载计数),即使在睡眠模式下也能工作。

    Systick定时器会将从RELOAD寄存器中装置初始值后,会一直按系统时钟定时减1,直到减为0.然后重新从RELOAD寄存器中装置初始值继续计数。

  • SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)

  • Systick中断优先级也可以设置。

Systick相关寄存器

  • CTRL:SysTick控制和状态寄存器
    SysTick初始化、控制、状态寄存器
    SysTick控制和状态寄存器

  • ENABLE:SYSTICK定时器的使能位

  • TICKINT:计数到0后是否产生中断
  • CLKSOURCE:时钟源选择,使用SysTick_CLKSourceConfig();函数配置
    • 外部时钟源是 HCLK(AHB总线时钟)的1/8,即168M的1/8=21M
    • 内核时钟是 HCLK时钟,即168M.
  • COUNTFLAG:状态位,是否读取过本寄存器。
  • RELOAD: SysTick重装载数值寄存器。
    预设的重载置,即我们要设置的定时值
    SysTick 重装载数值寄存器

  • CURRENT:SysTick 当前值寄存器
    当前值寄存器

Systick相关函数

固件库中的Systick相关函数:

  • SysTick_CLKSourceConfig() //Systick时钟源选择 misc.c文件中

    void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
    {
    /* Check the parameters */
    assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
    
    if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
    {
     SysTick->CTRL |= SysTick_CLKSource_HCLK;
    }
    else
    {
     SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
    }
    }
    
  • SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断

    static __INLINE uint32_t SysTick_Config(uint32_t ticks)
    { 
    if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);         /* Reload value impossible */
    
    /* set reload register */                                                            
    SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; 
    /* set Priority for Cortex-M0 System Interrupts */
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
    SysTick->VAL   = 0;                                        /* Load the SysTick Counter Value */
    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                    SysTick_CTRL_TICKINT_Msk   | 
                    SysTick_CTRL_ENABLE_Msk;     /* Enable SysTick IRQ and SysTick Timer */
    return (0);                                                  /* Function successful */
    }
    

Systick中断服务函数:

  • void SysTick_Handler(void);

Systick使用示例

这里实现的是每隔500ms两上LED灯的交规点亮,并且扬声器每500ms发出声音

#include "stm32f4xx.h"


static u8  tick_us=0;                        
static u16 tick_ms=0;                            
void InitSysClck(u8 sysclk)
{
     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //168/8=21M

     tick_us = sysclk/8;
     tick_ms = (u16)tick_us*1000;
}


void delay_xms(u16 nms)
{                     
    u32 temp;           
    SysTick->LOAD=(u32)nms*tick_ms;            
    SysTick->VAL =0x00;                   
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;     
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;  //关闭计数器
    SysTick->VAL =0X00;                   
} 

void delay_ms(u16 nms)
{          
    u8 repeat=nms/540;                        

    u16 remain=nms%540;
    while(repeat)
    {
        delay_xms(540);
        repeat--;
    }
    if(remain)delay_xms(remain);
} 

int main(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10|GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOF, &GPIO_InitStructure);

  InitSysClck(168);

  while(1)
    {
        GPIO_SetBits(GPIOF,GPIO_Pin_9);
        GPIO_ResetBits(GPIOF,GPIO_Pin_10);
        GPIO_ResetBits(GPIOF,GPIO_Pin_8);

        //Delay(0x7FFFFF);
        delay_ms(500);
        GPIO_SetBits(GPIOF,GPIO_Pin_10);                
        GPIO_SetBits(GPIOF,GPIO_Pin_8);                
        GPIO_ResetBits(GPIOF,GPIO_Pin_9);               
        delay_ms(500);
        //Delay(0x7FFFfF);

    }

}

问题

在实际的过程中,发现延迟并不准确,变长了,发现我使用了系统默认的PLL参数配置,导致时钟配置不正确。

  • 如 system_stm32f4xx.c 文件中PLL_M原值为255,这里应改为8,因为我们使用的是8M的外频时钟,而并非25M的时钟,导致系统时钟变低引起的。
  • 另一个地方是stm32f4xx.h文件 中的HSE_VALUE也需要从25000000改为8000000。

0 篇笔记 写笔记

STM32F407ZG Systick定时器及应用
Systick是系统定时器,对于CORTEX M3和M4的内核芯片,都有一个Systick定时器Systick定时器可以认为是系统主频(如STM32F407ZG为168M的时钟滴答)的实时计数。Systick定时器的用法Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU......
作者信息
我爱开发
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!