Systick系统定时器是内核的24位定时器,只能够递减,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器,系统嘀嗒校准值固定为9000,当系统嘀嗒时钟设定为9MHz(HCLK/8的大值),产生1ms时间基准
功能框图如下:
下面是SysTick 控制和状态寄存器,只有0,1,2,16这四个位有效
Systick的时钟源可以选择AHB/8或者AHB
Systick寄存器操作如下
SysTick定时时间计算,最好设置成毫秒级别,防止中断的频繁切换
在core_cm3.h里面查看SysTick_Type的定义,因为SysTick属于内核的外设,
/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
memory mapped structure for SysTick
@{
*/
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;
下面是SysTick的配置库函数,对于systick中断优先级配置的是scb->shprx寄存器,而外设的中断优先级配置的是nvic->iprx,有优先级分组,有抢占优先级和子优先级的说法
/**
* @brief Initialize and start the SysTick counter and its interrupt.
*
* @param ticks number of ticks between two interrupts
* @return 1 = failed, 0 = successful
*
* Initialise the system tick timer and its interrupt and start the
* system tick timer / counter in free running mode to generate
* periodical interrupts.
*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* 如果ticks大于2的24次方则返回1 */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* 初始化reload重装载寄存器的值 */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* 配置中断优先级为15,默认的最大优先级*/
SysTick->VAL = 0; /* Sys当前计数器的值赋值为0 */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* 使能systick中断和systick时间值 */
return (0); /* Function successful */
}
补充:
对systick进行配置
#include "bsp_systick.h"
void systick_config_us(uint32_t us)
{
SysTick_Config(72);
uint32_t i;
for(i=0;i<us;i++)
{
while(!((SysTick->CTRL)&(1<<16)));
}
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}
void systick_config_ms(uint32_t ms)
{
SysTick_Config(72000);
uint32_t i;
for(i=0;i<ms;i++)
{
while(!((SysTick->CTRL)&(1<<16)));
}
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}
int main(void)
{
HseConfig(9);
lcd_init();
while(1)
{
//systick_config_ms(5000);
GPIO_ResetBits(LED_PORT,GPIO_Pin_2);
systick_config_ms(500);
GPIO_SetBits(LED_PORT,GPIO_Pin_2);
systick_config_ms(500);
}
return 0;
}
实现灯500毫秒亮灭