《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器

写在前面——
  《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器,本节讲述syTIK系统定时器原理,以及其使用方法
官方例程下载:https://pan.baidu.com/s/1QC5BnDgY1m1me6-ihQ_OUQ?pwd=nqb1
提取码:nqb1

目录

  • 4.2 sysTICK系统定时器
    • 4.2.1. 实验任务
    • 4.2.2. sysTICK系统定时器原理
      • 1. sysTICK功能解析
      • 2. sysTICK ---HAL_Delay函数代码解析
      • 3. 使用sysTICK,自定义计时(在中断服务函数中实现计时控制)
      • 4. 使用sysTICK,自定义计时(main.c中使用uwTick实现计时)
    • 4.2.3. 小结

4.2 sysTICK系统定时器

4.2.1. 实验任务

1. 参考官方例程HAL_03_SYSTICK,掌握延迟函数HAL_Delay,实现流水灯。
2. 功能拓展:使用全局变量uwTick,实现自定义计时。

4.2.2. sysTICK系统定时器原理

1. sysTICK功能解析

   sysTICK系统定时器在CPU核内部实现的,跟MCU外设无关,因此无需外部电路连接。只要是ARM Cortex-M系列内核的MCU都包含这个定时器。使用内核的sysTICK定时器来实现延时,可以不占用系统定时器,节约资源。
  sysTICK 一般用于 HAL 库的毫秒级延时函数HAL_Delay(),可以实现精准的延时计时。该函数已经封装好了,直接调用即可。
  但是,在按键长/短按等实例中,需要精确的计时,这就要使用到sysTICK定时器。
简单说, sysTICK就是一个24bit、倒计时(递减计数)、自动重装载定时器,倒计时结束会产生一个中断。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第1张图片
  设:VAL中的数值为 80,脉冲频率为 80MHz,则VAL由 80 减到 0 所需要的时间为 ,并且当减到 0 时会触发中断(相当于 1us 定时器),同时 LOAD 的值也会重新载入到VAL中。
  在 STM32CubeMX 中配置好时钟树后,时钟频率会输入到 Cortex System timer内核时钟 。而 sysTICK又属于内核,故给到 sysTICK的脉冲频率来自于此。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第2张图片

2. sysTICK —HAL_Delay函数代码解析

  精准的1ms定时在SysTick_Config()中,从此函数逐渐深入到 core_cm4.h 中就有详细的SysTICK配置。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第3张图片
  LOAD寄存器 和 VAL寄存器 的值都在此函数中配置好了。
  这样,执行我们编程的函数时,内核还会不断的产生1ms中断(只是我们看不见),该中断服务函数SysTick_Handler在stm32g4xx.it.c中。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第4张图片
  其中,HAL_IncTick()在stm32g4xx_hal.c中定义:
在这里插入图片描述
  其中,uwTick是一个全局变量(非常重要的变量),uwTickFreq 的值为1(可跳转深入查看)。也就是说,通过中断服务函数SysTick_Handler(),实现了uwTick每1ms加1.
  再来看HAL_Delay()函数,在stm32g4xx.hal.c中被定义(函数HAL_GetTick也在其中):
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第5张图片在这里插入图片描述
  以HAL_Delay(500)为例,调用该函数时,如上图,变量wait赋值为500,变量tickstart记录uwTick初始值。当判别((HAL_GetTick() - tickstart) < wait),也就是当前uwTick值减去初始值,得到xx差值(因为uwTick值每1ms+1,这时就相当于系统计时了xx ms)。若小于用户定义的500,则继续循环等待;若超过500,则跳出循环(即跳出HAL_Delay() ),执行下一个函数。
  HAL_Delay函数已经被封装,直接调用就行了。

3. 使用sysTICK,自定义计时(在中断服务函数中实现计时控制)

  从以上分析可知,HAL_Delay()函数利用全局变量uwTick(每1ms自动累加1),实现计时功能。中断服务函数SysTick_Handler起到关键作用,每1ms发生执行一次。
官方例程HAL_03_SYSTICK,流水灯就是利用中断服务函数SysTick_Handler(stm32g4xx_it.c文件中)来实现的。
  在中断服务函数SysTick_Handler中编程代码:

unsigned char ms_led = 0;
unsigned char i = 7;
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(++ms_led == 100){
		GPIOC->ODR = ~(0x0001 << ++i);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		ms_led = 0;
		
		if(i == 16){
			i = 7;
		}
	}
}

  起始时i=7, ++i 使i=8,0x0001 <<8(左移8位)得到0x0100 。ODR是引脚电平输出的寄存器,写1 则gpio 管脚为高电平,写0 为低电平。
  main.c无需操作,系统自动每1ms执行中断服务函数SysTick_Handler,从而实现每100ms(因为(++ms_led == 100))左移一次的流水灯。

4. 使用sysTICK,自定义计时(main.c中使用uwTick实现计时)

  参考HAL_Delay函数的原理,在main.c中利用全局变量uwTick实现精确计时:

  • 先记录uwTick初值,如,有按键按下时使ulKey_Time = uwTick; ulKey_Time为main.c中自定义的变量。uwTick直接调用,无需在main.c中再次声明。
  • 计时判断,如,if(uwTick-ulKey_Time > 800) ,当前uwTick值减去其初值(ulKey_Time),大于800,则表示按下时间超过0.8s,判断是否长按?

  具体设计方法,参考以下按键长/短按设计程序(按键长/短按函数KEY_Proc):

unsigned char ucKey_Long;
unsigned long ulTick_ms, ulKey_Time;

void KEY_Proc(void)
{
  unsigned char ucKey_Val;

  ucKey_Val = KEY_Scan();   //按键扫描,按键按下时得到按键值1/2/3/4
  if(ucKey_Val != ucKey_Long)  //防止一直进入switch判断
  {
    ucKey_Long = ucKey_Val;
    ulKey_Time = uwTick;
  }
  else
	  ucKey_Val = 0;

  if(ucKey_Val == 1)				// B1按下
  {
if(uwTick -ulKey_Time < 800) //B1长/短按判断,0.8s计时
{
/* B1短按操作程序*/
}
    else 
    {
      ulKey_Time = uwTick;
/* B1长按操作程序*/
    }
  }
  
/* B2B3B4按键操作程序,类同,省略*/
  }
 }
}

  该程序利用全局变量uwTick(每1ms自动累加1)实现精确计时判断。
  另外一种方法,不用全局变量uwTick,而是在中断服务函数SysTick_Handler(stm32g4xx_it.c里)中使用自定义的全局变量(如ulTick_ms++)或者计时函数。ulTick_ms功能作用和uwTick一样,每1ms累加1.
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.2 sysTICK系统定时器_第6张图片
  然后在main中使用它(ulTick_ms在main.c中定义,SysTick_Handler中extern声明),替换上面的uwTick,也可以实现精确计时。

4.2.3. 小结

掌握以下2个方面:

  • 全局变量uwTick
  • 延迟函数HAL_Delay

你可能感兴趣的:(stm32CubeMX,嵌入式,SYSTICK,stm32,蓝桥杯)