STM32系列中m3内核中包含了一个简单的系统定时器Systick,计时方式采取向下计数,计数容量为24位。
关于Systick主要有四个32位寄存器:
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
CTRL 控制状态寄存器 第16位:计时标志位,如果在上次读取本寄存器后,Systick已经数到了0,则该位为1。 如果读取该位,自动清零。
第2位:时钟源选择位,0=外部时钟源 1=内部时钟源
第1位:中断允许位,0=Systicck倒数到0时无动作 1=倒数到0时产生中断请求
第0位:Systick定时器的使能位,1=开始使能 0=不使能
LOAD重载寄存器 前24位[23:0]: 记录着当倒数至零时,将被重载的值
VAL 当前值寄存器 前24位[23:0]:读取时返回当前倒计时的值,写时则清零,同时还会使CTRL中的计时标志位置零
CAILB 校准寄存器 用于计数校准
Systick的时钟为单片机的核心频率为 to Cretx System timer的时钟线,如下图所示,在该时钟线前面可根据实际需要来进行设计
在写Systick延时函数首先要在程序中对其进行初始化,可以直接使用SysTick_Config(uint32_t ticks) 函数进行配置,ticks代表着systick重装定时器的值。意思就是我要多少个1/fosc 时间后中断一下,SysTick_Config函数被定义在 core_cm3.h文件中
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* 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 (0UL); /* Function successful */
}
如果时钟频率fosc=72Mhz,计数一次需要1/72000000 s ,要定时1us,那就要把使 ticks 设置为72,然后再使能定时器
延时初始化代码
void SysTick_Init()
{ if(SysTick_Config(72)// 设置重载值 1us,可根据具体单片机的频率进行更改
{ while(1);
}
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;//使能定时器
}
void Delay_us( unsigned int nTime)
{ SysTick->LOAD = nTime*72;//设置延时
SysTick->VAL=0;//计数器清零
while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_MSK));//等待计数终止
}
//延时约断,误差越大,延时1us时,调试延时6us
//延时10us时,调试延时12.3us