系统定时器SysTick
SysTick是CM3内核中的外设,是一个24位递减的计数器,每1/SYSCLC递减一次,其中,SYSCLC是SysTick的时钟,在stm32f1系列单片机中,可以设置为72M(时钟源位HCLK)、9M(HCLC的8分频)。
SysTick寄存器介绍:
这里只列举几个重要寄存器,图片摘自野火stm32库开发实战指南:
SysTick定时时间的计算
前面说到SysTick每1/SYSCLC递减一次是指:SysTick从重装载寄存器的RELOAD值开始每次递减1,假设SYSCLC设置位9MHZ,则SysTick每1/9M递减一次,基于此,SysTick从RELOAD递减到0所需的时间为:
如果设置RELOAD=9,带入上式得到T=1us,便可实现微秒级延时。
SysTick是否递减到0可通过读取SysTick当前数值寄存器获得当前值判断。
delay函数编写:
下面基于标准库编写delay函数:
首先,先对SysTick初始化:
static uint16_t g_fac_us = 0; /* us延时倍乘数 */
void delay_init(uint16_t sysclk)
{
SysTick->CTRL = 0;//清Systick状态
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择SysTick时钟源,这里选择HCLK8分频
g_fac_us = sysclk / 8;
}
/**
* @brief 延时nus
* @param nus: 要延时的us数.
* @note 注意: nus的值,不要大于1864135us(最大值即2^24 / g_fac_us @g_fac_us = 9)
* @retval 无
*/
void delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD = nus * g_fac_us; /* 时间加载 */
SysTick->VAL = 0x00; /* 清空计数器 */
SysTick->CTRL |= 1 << 0 ; /* 开始倒数 */
do
{
temp = SysTick->CTRL;
} while ((temp & 0x01) && !(temp & (1 << 16))); /* CTRL.ENABLE位必须为1, 并等待时间到达 */
SysTick->CTRL &= ~(1 << 0) ; /* 关闭SYSTICK */
SysTick->VAL = 0X00; /* 清空计数器 */
}