和系统滴答定时器相关的寄存器:
STK_CTRL:控制寄存器:
COUNTFLAG:控制标志位;
CLKSOURCE:时钟源:
置零:八分频的高速度系统总线
置1:AHB原始系统时钟72HZ;
TICKINT:中断使能位:
0:关闭
1:打开,计时完毕产生中断;
ENABLE:使能位;
STK_LOAD:计数重装载值,在下图中我们可以看到load是[23:0],说明只有24位可以配,即装载值的最大值为2^{24}-1;
RELOAD:重装载值;
STK_VAL:SystemTick current value register
CURRENT:只能读,写入则会清零;
STK_CALIB:calibration校准寄存器(和出厂设置挂钩)只能读;
我们学习的目标是利用系统定时器的中断,我以用系统定时器记时,每1s灯翻转1次
寄存器实现方式
void Systick_Init(){
//配置内核时钟源,74MHz
SysTick->CTRL |=SysTick_CTRL_CLKSOURECE;
//中断使能
SysTick->CTRL |=SysTick_CTRL_CLKINT;
//系统时钟使能
SysTick->CTRL |=SysTick_CTRL_ENABLE;
//计数器重装载,例如1S亮灯1次,系统周期:每(x/72M)秒中断溢出1次,当x为72时即1us溢出1次,x允许的最大值为2^{24}-1,所以给x=72000-1,达到1ms溢出一次
SysTick->LOAD=71999;//0~71999,即计数72000次,所以要减一
}
//定义变量用来累计值
uint16_t count=0;
//中断服务程序是STM32文件stm32f1xx_it.c中自带的要自己重写的函数
void SysTick_Handler(void){
count++;
//如果达到1s
if(count==1000){
HAL_GPIO_Write(GPIOA,GPIO_Pin_4);
count=0;
}
}
HAL库的实现方式:
系统定时器本身就是系统的核心功能,点开SYS可以看到Timebase Source 默认就是SysTick
点开NVIC可以看到系统滴答定时器默认就是开启的,注意优先级是数值越小优先级越高,目前我们不用更改优先级,如果你还有其他中断需求就要考虑优先级的问题了
生成KEIL5工程文件,这里我用VSCode打开做演示:
可以看到CubeMX的默认配置是1ms中断溢出一次
用CubeMX默认系统时钟配置和我们用寄存器方式是一致的
我们的核心操作就是重写中断服务程序或者中断回调函数:
其中我们可以再在hal.c文件中找到uwTick的底层逻辑就是中断溢出的次数(每1ms中断溢出一次),所以我们不需要寄存器例子里的count来帮助累计了
重写中断服务程序的代码:注意既可以在stm32f1xx_it.c文件中添加补充,也可以在main.c中重写
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
if(uwTick%1000==0){
HAL_GPIO_Write(GPIOA,GPIO_PIN_0);
}
}
以重写中断回调函数的方式,该函数是弱函数,只能重写,这里我选择在main.c文件中重写
void HAL_IncTick(void){
uwTick+=uwTickFreq;
if(uwTick%1000==0){
HAL_GPIO_Write(GPIOA,GPIO_PIN_0);
}
}