基于cubemx的stm32开发之路(使用正点原子战舰V3开发板)——基本定时器的应用

实验目的

学习利用CubeMX创建HAL库的工程
掌握定时器的基本原理

实验现象

使用stm32F1的TIM6定时器实现LED灯1hz的闪烁

实验设备

正点原子新战舰V3 STM32F103ZET6开发板学习板
st-link烧录器

定时器原理

F103定时器组成

STM32F103ZET6总共有8个定时器:

计数器类型预分配系数产生DMA捕获/比较通道互补输出计数器分辨率
高级定时器TIM1向上/向下1-65535可以416位(2^16)
TIM8向上/向下1-65535可以416位
通用定时器TIM2向上/向下1-65535可以416位
TIM3向上/向下1-65535可以416位
TIM4向上/向下1-65535可以416位
TIM5向上/向下1-65535可以416位
基本定时器TIM6向上1-65535可以016位
TIM7向上1-65535可以016位

总结:
TIM1和TIM8定时器特殊在有互补输出。高级定时器可以定时、输出比较、输入捕捉、还可以输出三相电机互补信号,每个高等定时器有8个外部IO口。
TIM6和TIM7基本定时器特殊在:基本定时器没有外部IO口,只能向上计数定时产生中断/DMA请求,没有捕获/比较通道
通用定时器(TIM2-TIM5)可以定时、输出比较、输入捕捉,每个通用定时器具有4个外部IO口。

定时器时间计算

基本定时器的计数次数由自动重装载寄存器决定的,基本定时器的计数器从0开始向上计数(计数模式为向上计数时),当计数器的值与自动重装载寄存器相等时,产生溢出。所以基本定时器的溢出时间计算公式如下:
T i m e = ( P S C + 1 ) ∗ ( A R R ) / T I M x C L K ( u s ) Time = (PSC+1)*(ARR)/ TIMxCLK(us) Time=PSC+1ARR/TIMxCLKus
PSC是定时器的分频系数,TIMxCLK是内部时钟。
  ARR是自动重装载寄存器的值(既计数多少产生一次溢出)。
  假设基本定时器TIMxCLK = 72MHZ,PSC = 72-1,ARR = 1000,那么定时器的溢出时间为:
T i m e = 72 ∗ 1000 / 72 = 1000 ( u s ) = 1 ( m s ) Time = 72*1000/72 = 1000(us) = 1(ms) Time=721000/72=1000us=1ms

具体步骤

1.RCC时钟源配置

RCC_allocation

2.时钟树配置

Clock_Configuration

3.GPIO配置,LED0对应PB5引脚

GPIO_Configuration

4.TIM6配置与中断使能

对应的时间为
T i m e = 7200 ∗ 5000 / 72 = 500 ( m s ) = 0.5 ( s ) ; 周 期 T = 1 s ; 频 率 f = 1 h z . Time = 7200*5000/72 = 500(ms)=0.5(s); 周期T=1s ; 频率f=1hz. Time=72005000/72=500ms=0.5(s)T=1sf=1hz.

NVIC_settings

5.项目配置

Project_Setings
code_setings

代码编写

1.CubeMX 生成的main.c
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();			//GPIO初始化,,函数definition在gpio.c
  MX_TIM6_Init();			//Tim6定时器初始化,函数definition在tim.c
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
2.CubeMX 生成的tim.c
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim6;

/* TIM6 init function */
void MX_TIM6_Init(void)			//定时器初始化函数
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 7200-1;				//定时器预分频系数
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;	//向上计数模式
  htim6.Init.Period = 5000-1;					//自动重装载值
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;		//自动重装功能使能
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)  //中断设置
{

  if(tim_baseHandle->Instance==TIM6)
  {
  /* USER CODE BEGIN TIM6_MspInit 0 */

  /* USER CODE END TIM6_MspInit 0 */
    /* TIM6 clock enable */
    __HAL_RCC_TIM6_CLK_ENABLE();

    /* TIM6 interrupt Init */
    HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);		//中断NVIC优先级设置为0,0
    HAL_NVIC_EnableIRQ(TIM6_IRQn);				//使能定时器6的中断服务
  /* USER CODE BEGIN TIM6_MspInit 1 */

  /* USER CODE END TIM6_MspInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)	//中断挂起函数
{

  if(tim_baseHandle->Instance==TIM6)
  {
  /* USER CODE BEGIN TIM6_MspDeInit 0 */

  /* USER CODE END TIM6_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM6_CLK_DISABLE();

    /* TIM6 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM6_IRQn);
  /* USER CODE BEGIN TIM6_MspDeInit 1 */

  /* USER CODE END TIM6_MspDeInit 1 */
  }
}
3.查看stm32f1xx_it.c文件,找到中断服务函数
void TIM6_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_IRQn 0 */

  /* USER CODE END TIM6_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_IRQn 1 */

  /* USER CODE END TIM6_IRQn 1 */
}

这个函数调用了下面这个函数

HAL_TIM_IRQHandler(&htim6) ;

4.找到中断回调服务函数

进入HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)函数,这里面的代码很长,其实就是不同的中断类型,进入不同的中断回调函数,都属于虚函数,所以我们只要在 main.c 或者 tim.c 文件中使能中断并重写中断服务函数即可

void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
  /* Capture compare 1 event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
    {
      {
        __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;

        /* Input capture event */
        if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
        {
       ..............................................
5.使能定时器中断并编写中断回调服务函数
使能定时器中断
  MX_GPIO_Init();
MX_TIM6_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);  //放在初始化之后
编写中断回调服务函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM6)
	{
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
	}
}

对应的源程序压缩包可以前往https://download.csdn.net/download/weixin_46074226/20533195 下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值