本文通过CubeMX配置F103RCT6的定时器中断和串口。
文章目录
- 1 引入
- 2 配置过程
- 2.1 配置时钟过程
- 2.2 配置串口过程
- 2.3 定时器中断配置
- 3 生成工程代码
- 4 测试串口及定时器中断周期
- 5 总结
1 引入
拿到一个STM32控制器,在啥也没有的情况下从零开始写软件,博主习惯于先配置定时器中断和串口打印。本文就以博主在网上买的小车控制板为例,对其进行最基本的时钟及串口打印配置,并且写一些代码测试一下串口。
定时器中断配置为20ms触发一次中断,并且在中断服务函数中执行应用层相关代码。
2 配置过程
2.1 配置时钟过程
1)首先,新建一个工程,选择MCU型号;
2)在弹出的型号面板中选择自己购买的开发板上的主芯片型号,这里博主是F103RCT6;
3)开发板上的PD0和PD1接了8MHz的晶振,所以选择Crystal/Ceramic Resonator,即使用外部晶振作为HSE的时钟源。
4)时钟树配置如下图;
后续的外设会参考到这里的总线时钟。
2.2 配置串口过程
将串口配置为如下所示;
2.3 定时器中断配置
配置定时器中断时需要考虑避开电机、舵机、编码器等使用过的定时器,所以这里选用TIM5。在STM32手册中可以查询到TIM5的内部时钟来源是APB1总线上。因此,它的基准频率是72Mhz。
这里的目标是产生20ms的中断,所以博主把预分频系数设置为7200-1,自动重载值设置为200-1。这样就能得到中断频率为72000000/7200/200=50Hz。在CubeMX中的配置如下:
最后还需要开启中断:
3 生成工程代码
1)配置生成代码的IDE为STM32CubeIDE;
2)生成代码配置;
这里博主勾选了只拷贝必要的库文件,以及生成独立的.c/.h文件,看个人习惯。
4 测试串口及定时器中断周期
1)点击右上角的Generate Code,并Open Projectp;先新建一个user.c和user.h文件,里面存放用户手写的代码;
2)参考网上其他博客,在user.c中加上重定向函数,这样就可以用printf函数打印数据;
/* USER CODE BEGIN 1 */
#include "stdio.h"
// 重定向print start
int __io_putchar(int ch)
{
//具体哪个串口可以更改USART1为其它串口
while ((UART4->SR & 0X40) == 0); //循环发送,直到发送完毕
UART4->DR = (uint8_t) ch;
return ch;
}
//_write函數在syscalls.c中, 使用__weak定義, 所以可以直接在其他文件中定義_write函數
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
// 重定向print end
/* USER CODE END 1 */
2)在main函数中启动定时器并使能中断,在while循环之前;
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim5);
/* USER CODE END 2 */
3)重定义中断回调函数,在user.c中加入如下代码;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == htim5.Instance)
{
Test20ms();
}
}
4)编写test20函数内容,将一个变量没调度一次加20;
float i_20ms = 0.0F;
void Test20ms()
{
i_20ms = i_20ms + 20.0;
}
5)最后,在主函数的while循环中每过1s通过串口打印出i_20ms的变量值;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("i_20ms:%f\r\n",i_20ms);
HAL_Delay(1000);
}
6)烧录程序,通过串口读取,每次i_20ms变量比之前增加1000,说明是按照20ms调度一次定时器中断的;
5 总结
本文记录了CubeMX配置定时器中断及串口打印的过程,这是玩转开发板的第一步。