TA的每日心情 | 难过 2021-2-27 22:16 |
---|
签到天数: 1568 天 连续签到: 1 天 [LV.Master]伴坛终老
|
STM32F469 本身是带有12个定时器和两个看门狗。其中定时器1和定时器8属于高级定时器。TIM2,TIM5 ; TIM3,TIM4 ; TIM9 ; TIM10,TIM11 ; TIM12 ; TIM13,TIM14 属于通用定时器,还有TIM6,TIM7两个基本定时器。值得一提的是定时器最高时钟高达180MHz ,这使得在一些要求精度的场合,更能发挥出F469的优势,做起应用来也更方便。这是应为此所以在学习STM32定时器时,是个难点。同样也是个重点。
高级定时器:(TIM1,tim8)可以看作是三相PWM发生器。同样具有互补的脉宽调制输出,可编程插入死区时间设置。它们也可以被当做通用定时器使用。
通用定时器:STM32F46x包括4个全功能的通用定时器TIM2,TIM5,TIM3和TIM4。
TIM2和TIM5计时器是基于32位自动重载加/减计数器的一个16位的预分频器。
TIM3和TIM4计时器是基于一个16位自动重载递增/递减计数器的一个16位预分频器。他们都拥有输入捕捉/输出4个独立通道比较器,PWM或单脉冲模式输出。多达16个
输入捕捉/输出的比较 PWM通道。其中TIM2,TIM3,TIM4,TIM5通用定时器可以一起工作,或与其他通用定时器,并通过同步或事件链接定时器TIM1和TIM8。任何
这些通用定时器的可以被用于生成PWM输出。
TIM2,TIM3,TIM4,TIM5都有独立的DMA请求产生。它们能够处理正交(增量值)编码器信号和数字输出1至4个霍尔效应传感器。
TIM9, TIM10, TIM11, TIM12, TIM13, and TIM14 这些计时器是基于16位自动重载的16位的预分频器。其中 TIM0,TIM11,TIM14 TIM13,功能独立,TIM9和TIM12有输
入捕捉/输出比较两个独立通道,PWM或脉冲方式输出。他们可以用TIM2,TIM3,时间同步,TIM5功能齐全的通用定时器。它们也可以用作简单的时间基准。
基本定时器TIM6,TIM7这些定时器主要用于产生DAC触发和波形。或者也可以被用作一个通用的16位时间基准。TIM6,TIM7支持独立的DMA请求代。
看门狗:独立看门狗是基于一个12位的向下计数器和8位预分频器。它是由一个独立的32 kHz内部RC阻止,因为它独立运作的主时钟,它可以在停机和待机模式下运行。
它可以使用,也可以作为看门狗在发生问题时重置设备,或者作为一个自由运行定时器用于应用程序管理的超时。它是硬件或软件配置通过选择字节。
新建工程:新建工程的话可以用STM32CUBE来新建工程。有点类似向导的感觉。用来配置外设利器。用来配置时钟,定时器,ADC,DAC等等很方便。
直接OK,下一步就是设置要用到的资源,比如定时器,设置完成后,就可以生成工程。而且重要的引脚显示很清楚。在选择生成工程时,支持生成MDK 和EWARM 等的工程。很方便。不过我打算这么干。我打算直接keil 去新建工程。
新建一个工程。首先要找到 "stm32f4xx_hal_conf.h" 这个头文件,至于这个头文件在哪里(main.h 下 "stm32f4xx_hal.h"头文件下"stm32f4xx_hal_conf.h"文件)就能找到。首先要将文中的 /* #define HAL_TIM_MODULE_ENABLED */ 注释去掉。 意思是使用定时器
第二步:要添加头文件到Drivers/STM32F4XX_HAL_Driver 文件夹下 文件在keil安装目录下:keil5\ARM\Pack\Keil\STM32F4xx_DFP\2.6.0\Drivers\STM32F4xx_HAL_Driver\Src文件夹中。 添加stm32f4xx_hal_tim.c 文件和 stm32f4xx_hal_ex.c 两个.c文件到工程中。
文件夹下:
MAIN中声明一个结构体:TIM_HandleTypeDef TimHandle;
初始化定时器3:
view plaincopy to clipboardprint?
void TIM3_Init()
{
/* Prescaler declaration */
uint32_t uwPrescalerValue = 0;
/* Compute the prescaler value to have TIMx counter clock equal to 10000 Hz */
uwPrescalerValue = (uint32_t)((SystemCoreClock / 2) / 10000) - 1;
/* Set TIMx instance */
TimHandle.Instance = TIM3;
/* Initialize TIMx peripheral as follows:
+ Period = 10000 - 1
+ Prescaler = ((SystemCoreClock / 2)/10000) - 1
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = 10000 - 1;
TimHandle.Init.Prescaler = uwPrescalerValue;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
BSP_LED_On(LED3);
while (1);
}
/*##-2- Start the TIM Base generation in interrupt mode ####################*/
/* Start Channel1 */
if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
{
/* Starting Error */
BSP_LED_On(LED3);
while (1);
}
}
初始化GPIO口:这步官方已经写好了函数,可以直接调用。本着研究的目的,f12了函数,发现初始化函数:
view plaincopy to clipboardprint?
GPIO_InitTypeDef gpio_init_structure;
__HAL_RCC_GPIOD_CLK_ENABLE();
gpio_init_structure.Pin = GPIO_PIN_4;
gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_structure.Pull = GPIO_PULLUP;
gpio_init_structure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOD, &gpio_init_structure);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET);
view plaincopy to clipboardprint?
MAIN 函数直接调用定时器初始化函数就OK,纳尼 。。。 怎么没看到开启TIM的时钟函数,也没看到配置中断优先级呀? 进入 HAL_TIM_Base_Init 函数中看看 其实,ST官方库函数是这么做的: 在初始化定时器时,HAL_TIM_Base_Init 函数会调用HAL_TIM_Base_MspInit(htim) 函数去开启中断时钟和配置定时器的中断优先级
那么就好办了。重写个HAL_TIM_Base_MspInit 函数去初始化时钟和NVIC 设置。
view plaincopy to clipboardprint?
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
/*##-1- Enable peripheral clock #################################*/
/* TIMx Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/*##-2- Configure the NVIC for TIMx ########################################*/
/* Set the TIMx priority */
HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
/* Enable the TIMx global Interrupt*/
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
官方的中断处理函数也是写好的,只要用的时候去调相应事件的中断就OK了。
剩下的就是重写HAL_TIM_Base_MspInit(htim) 函数 这个很简单,并且重要的官方的已经很完善了
view plaincopy to clipboardprint?
/**
* @brief Period elapsed callback in non blocking mode
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
BSP_LED_Toggle(LED1);
}
完成。剩下的就是烧写,去看led 一闪一灭,本文中很多关于定时器的高级应用和关于定时器的定时值的计算并没有说,其实是也不大懂,怕说错误导大家,详情还是研究官方例程和数据手册中吧。
|
|