目录
一、简介
二、原理及代码
1、原理
这个一个基本定时器的框图。我们稍加修改。将PSC-->stk_clk(时钟)。一个能大概表示systick的框图就诞生了。
首先,我们选择时钟。比如我们最后确定为72MHZ的八分频为所用时钟。那1us就是72MHZ / 8000000;我们的向计数器写值时并不能直接赋值,需要先向重装载寄存器中写入值,在开始时加载进计数器。
在设置控制和状态寄存器的第0位使能该计数器后,当前值寄存器在每个处理器时钟周期或参考时钟的上升沿都会减小。若计数减至0。就是1us。而计数器它会从重加载寄存器中加载数值并继续运行。
2、时钟
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//在misc.c中,选择外部时钟源 HCLK/8
fac_us = SystemCoreClock / 8000000;
fac_ms = (u16)fac_us*1000;
}
3、计时
我们将目光放到表8.10和8.11的位段上:23:0。翻译一下就是只能接受0-2的24次方之间的数。0-16777216.
我们往重装载寄存器放入我们要定时的值。例如1us.72MHZ / 8000000.
计时器里面如果有初始值,那必然会影响定时,所以我们先清空计时器。然后再让它倒数。
我们直接判断控制状态寄存器第16位是否为1,就可以知道是否计时结束。
所以我们得到代码。
我们为了可读性将这几个寄存器整合起来。
我们得到代码:
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;
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
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; //清空计数器
}
补充:
我们根据资料得知这个定时器也是可以产生中断的。需要注意的是:中断的时钟选择函数和普通的是不一样的。
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
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 */
}