和往常一样,先建立SysTick定时器练习文件夹,并在里面建立SysTick_test和SysTick两个子文件夹。
STM32的通用定时器是通过一个可编程预分频器(Prescaler)驱动的16位自动重装主计数器(Counter Period)构成。可以对内部时钟或触发源以及外部时钟或触发源进行计数。
定时器发生中断时间的计算方法:
查找资料可知:定时时间 = (Prescaler + 1)x (Counter Period + 1) x 1/定时器时钟频率
比如时钟信号1KHz,Prescaler为9,Counter Period为999,定时时间为10s。
蓝桥杯嵌入式比赛一般要把时钟信号设置为80MHz,下面我们就此频率实现三个功能:
1.利用TIM2实现间隔定时,每隔0.3秒将LED1的状态进行翻转。
2.利用TIM3实现间隔定时,每隔1秒将LED4的状态进行翻转。
3.修改TIM3的初始化代码,修改为每隔0.5秒将LED4的状态进行翻转。
下面打开STM32CubeMX进行配置,我们需要初始化的LED1和LED4,对应的IO口为PC8和PC11,以及LE对应的PD2。
首先将两个时钟都打开。
再去配置对应的GPIO口,将PC8、PC11和PD2设置为推挽输出,PC8、PC11初始化为高电平,这样上电LED不会亮,PD2初始化为低电平,这样上电不会对LED有任何的控制。
下面开始配置时钟树,按照下图中的数据进行修改,配置成80MHz。
下面开始配置TIM2和TIM3,根据给定的要求结合计算公式,TIM2的Prescaler需要设置为(8000-1)即7999, Counter Period需要设置为(3000-1)即2999。
TIM3的Prescaler需要设置为(8000-1)即7999, Counter Period需要设置为(10000-1)即9999。
下面在左侧Timers下拉,对TIM2和TIM3按照计算数据进行配置。
配置完成后不要忘记使能中断。
下面依旧是到了对工程的配置阶段,按照下图进行对应修改即可。
完成后即可生成代码。打开工程,首先把启动文件添加进工程,然后进行编译。
打开stm32g4xx_it.c找到下图框中的函数并按F12进入查看函数内部。
会跳转到stm32g4xx_hal_tim.c中void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)函数,继续向下翻找到第二张图①号框对应的回调函数HAL_TIM_PeriodElapsedCallback(htim);并按F12进入到函数内部,此函数是需要我们自行编写内部内容的(即需要完成的功能)。
跳转的内容如下,此函数是一个虚函数,如果检测到在别的地方用户定义了此函数则会执行用户定义的函数而不会执行下图中的虚函数,所以我将此函数复制到主函数进行编写 ,方便后面的代码编写。
编写代码的位置及内容如下:其中HAL_GPIO_TogglePin()函数的功能就是实现GPIO端口电平的翻转。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
if(htim->Instance == TIM3)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_11);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
}
下面需要在main函数中打开定时器,需要找到如下的函数:
在stmg4xx_hal_tim.h中找到 HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
并在主函数的如下位置处打开TIM2和TIM3。
编译好代码,设置好下载器,将代码下载进入开发板即可实现现象。
下面继续打开tim.c,找到 void MX_TIM3_Init(void)函数,将里面的htim3.Init.Period值修改为4999即可实现0.5秒的LED4状态改变。