本文通过CubeMX配置F103RCT6的定时器中断和串口。


文章目录

  • 1 引入
  • 2 配置过程
  • 2.1 配置时钟过程
  • 2.2 配置串口过程
  • 2.3 定时器中断配置
  • 3 生成工程代码
  • 4 测试串口及定时器中断周期
  • 5 总结


1 引入

拿到一个STM32控制器,在啥也没有的情况下从零开始写软件,博主习惯于先配置定时器中断和串口打印。本文就以博主在网上买的小车控制板为例,对其进行最基本的时钟及串口打印配置,并且写一些代码测试一下串口。

定时器中断配置为20ms触发一次中断,并且在中断服务函数中执行应用层相关代码。

2 配置过程

2.1 配置时钟过程

1)首先,新建一个工程,选择MCU型号;

cubemx定时器时间配置 cube定时器中断_串口


2)在弹出的型号面板中选择自己购买的开发板上的主芯片型号,这里博主是F103RCT6;

cubemx定时器时间配置 cube定时器中断_串口_02


3)开发板上的PD0和PD1接了8MHz的晶振,所以选择Crystal/Ceramic Resonator,即使用外部晶振作为HSE的时钟源。

cubemx定时器时间配置 cube定时器中断_串口_03


cubemx定时器时间配置 cube定时器中断_单片机_04


4)时钟树配置如下图;

cubemx定时器时间配置 cube定时器中断_嵌入式硬件_05


后续的外设会参考到这里的总线时钟。

2.2 配置串口过程

将串口配置为如下所示;

cubemx定时器时间配置 cube定时器中断_嵌入式硬件_06

2.3 定时器中断配置

配置定时器中断时需要考虑避开电机、舵机、编码器等使用过的定时器,所以这里选用TIM5。在STM32手册中可以查询到TIM5的内部时钟来源是APB1总线上。因此,它的基准频率是72Mhz。

cubemx定时器时间配置 cube定时器中断_stm32_07


这里的目标是产生20ms的中断,所以博主把预分频系数设置为7200-1,自动重载值设置为200-1。这样就能得到中断频率为72000000/7200/200=50Hz。在CubeMX中的配置如下:

cubemx定时器时间配置 cube定时器中断_stm32_08


最后还需要开启中断:

cubemx定时器时间配置 cube定时器中断_嵌入式硬件_09

3 生成工程代码

1)配置生成代码的IDE为STM32CubeIDE;

cubemx定时器时间配置 cube定时器中断_嵌入式硬件_10


2)生成代码配置;

cubemx定时器时间配置 cube定时器中断_cubemx定时器时间配置_11


这里博主勾选了只拷贝必要的库文件,以及生成独立的.c/.h文件,看个人习惯。

4 测试串口及定时器中断周期

1)点击右上角的Generate Code,并Open Projectp;先新建一个user.c和user.h文件,里面存放用户手写的代码;

cubemx定时器时间配置 cube定时器中断_单片机_12

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调度一次定时器中断的;

cubemx定时器时间配置 cube定时器中断_串口_13

5 总结

本文记录了CubeMX配置定时器中断及串口打印的过程,这是玩转开发板的第一步。