STM32 Timer (2) 定时器中断代码框架

摘要:
voidTIM3_IRQHandler{//待编写}//写什么呢,TIM的api中,有中断触发函数HAL_TIM_IRQHandler;---˃voidTIM3_IRQHandler{HAL_TIM_IRQHandler;}//继续跟踪HAL_TIM_IRQHandler;/*TIMUpdateevent*/if(__HAL_TIM_GET_FLAG(htim,TIM_FLAG_UPDATE)!
3. 代码框架

3.1 分频系数的计算

x1/x2                /N(预分频)
APB1时钟------->F(CK_PSC)--------------->CK_CNT

如果APB1的分频系数为1, CK_INT的倍频系数就是x1
如果APB1的分频系数不为1, CK_INT的倍频系数就是x2

STM32F1(MHz)

STM32F4(MHz)

STM32F7(MHz)
SYSCLK72168216
AHB72168216
APB1 (AHB/4)184254
CK_INT(x1/x2)3684108
PSC预分频
举例:实现 0.5s 的led闪烁
当前使用F7 所以 

CK_INT =108MHz
PSC预分频:Prescaler
自动重装载寄存器: Period

time =  (Period)(Prescaler)/CK_INT

0.5 = (Period)(Prescaler)/108000000
预分频 Prescaler 方便计算 设置为 108000(整除),
自动重装载 Period 设置为 500计算: 500*108000/108000000 = 0.5
但是,因为受到16位寄存器的约束, 108000超过的65535(2的16次方)
所以稍微调整:
5000 * 10800同样满足要求。 

所以配置:
Prescaler = 10800Period = 5000

根据定时需求调整
time =  (Period)(Prescaler)/CK_INT

3.2 代码细讲

intmain()
{
    
}开始了解定时器的实现
//1.使能定时器时钟
__HAL_RCC_TIM3_CLK_ENABLE();

//2. 初始话定时器,配置Prescaler,Period
HAL_TIM_Base_Init();

//3. 开启定时器/中断
HAL_TIM_Base_Start();
HAL_TIM_Base_Start_IT();

//4. 设置中断优先级
HAL_NVIC_SetPriority(); HAL_NVIC_EnableIRQ();

//5. 编写中断服务函数
TIMx_IRQHandler();    //中断服务函数
HAL_TIM_IRQHandler(); //中断处理入口函数
HAL_TIM_PeriodElapsedCallback();//定时器更新中断回调函数
//正式开始
//1. 自定义一个TIM初始化函数
voidTIM3_Init()
{
    //...
}

intmain()
{
    TIM3_Init();
}
//Tim3_Init()做些什么事?
voidTIM3_Init()
{
    //1. 定时器初始化函数
    HAL_TIM_Base_Init(); //需要一个参数
}

//函数原型: HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
//所以设置TIM句柄 
TIM_HandleTypeDef htim3;

//设置了句柄,就要对其中的参数进行初始化
htim3.Instance =TIM3;
htim3.Init.Prescaler = 10800-1;                     //预分频系数
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //计数模式
htim3.Init.Period = 5000-1;                         //自动装载值
//结果:
TIM_HandleTypeDef htim3;
voidTIM3_Init()
{
    htim3.Instance =TIM3;
    htim3.Init.Prescaler = 10800-1;                     //预分频系数
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //计数模式
    htim3.Init.Period = 5000-1;                         //自动装载值
HAL_TIM_Base_Init(htim3);
}
//2. 然后嘞就要使能时钟定时器
//在HAL_TIM_Base_Init(htim3) 函数中有:
HAL_TIM_Base_MspInit(htim);

//这个函数Msp 表示回调函数, 一般在文件stm32f4xx_hal_msp.c文件中,如果没有,自己实现也是一样
//这个函数主要实现 时钟的开启, GPIO的配置, 中断优先级的配置
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef*htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();    
    }
}

//因为HAL_TIM_Base_Init 这个函数不仅仅针对与TIM3, 所以在Msp函数中, 要进行if判断
htim_base->Instance==TIM3
//在这个函数中, 进行 TIM时钟的开启  
__HAL_RCC_TIM3_CLK_ENABLE();
//3.开启Tim3且中断
voidTIM3_Init()
{
    htim3.Instance =TIM3;
    htim3.Init.Prescaler = 10800-1;                     //预分频系数
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //计数模式
    htim3.Init.Period = 5000-1;                         //自动装载值
HAL_TIM_Base_Init(htim3);
    
    //new
    HAL_TIM_Base_Start_IT(&htim3);                         //开启定时器中断
}
//4 .开启了中断后,就要设置中断优先级
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef*htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
 
        //中断优先级
HAL_NVIC_EnableIRQ(TIM3_IRQn);
        HAL_NVIC_SetPriority(TIM3_IRQn,1,3);
    
    }
}
//5. 编写中断服务函数
//在start.s文件中,有中断触发函数列表,查找之。
void TIM3_IRQHandler(void)
{
    //待编写
}
//写什么呢,TIM的api中,有中断触发函数
HAL_TIM_IRQHandler(&htim3);

--->
void TIM3_IRQHandler(void)
{
   HAL_TIM_IRQHandler(&htim3);
} 

//继续跟踪  HAL_TIM_IRQHandler(&htim3);
 /*TIM Update event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) !=RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->PeriodElapsedCallback(htim);
#elseHAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}
  }

//有各种各样的中断,这里实现更新中断, 调用了 HAL_TIM_PeriodElapsedCallback(htim);
//所以重写回调函数HAL_TIM_PeriodElapsedCallback(htim);
//time更新回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    //LED 反转
}

3.3 全代码

其中LED的初始化基于RT-thread, 若非RTOS自行替换,跟框架无关。

main.c

#include <rtthread.h>#include <rtdevice.h>#include <board.h>


#define LED0    GET_PIN(B,0)
#define LED1    GET_PIN(B,1)

static rt_uint8_t flag = 0;
TIM_HandleTypeDef htim3;
voidTIM3_Init()
{
    htim3.Instance =TIM3;
    htim3.Init.Prescaler = 10800-1;                    //预分频系数
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //计数模式
    htim3.Init.Period = 5000-1;                         //自动装载值
HAL_TIM_Base_Init(&htim3);
    
    HAL_TIM_Base_Start_IT(&htim3);                      //开启tim3中断
    
    //因为开启了中断,所以要设置中断优先级
    //本来要自己实现中断函数HAL_TIM_Base_MspInit 的,但是在
    //stm32f7xx_hal_msp.c文件中已经写了,所以去这个文件编写中断优先级
}
//中断配置后,实现中断服务函数
//中断服务函数
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim3);
}

//time更新回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(flag == 0)
    {
        rt_pin_write(LED0,PIN_LOW);
        flag = 1;
        return;
    }
    
    if(flag == 1)
    {
        rt_pin_write(LED0,PIN_HIGH);
        flag = 0;
        return;
    }
}

void LED_Init(void)
{
    rt_pin_mode(LED0,PIN_MODE_OUTPUT);  
}

int main(void)
{
    LED_Init();
    TIM3_Init();

    return 0;
}

htm32f7xx_hal_msp.c

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef*htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
 
        //中断优先级
HAL_NVIC_EnableIRQ(TIM3_IRQn);
        HAL_NVIC_SetPriority(TIM3_IRQn,1,3);
    
    }
 }

免责声明:文章转载自《STM32 Timer (2) 定时器中断代码框架》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Mongodb总结6-数据库启动、停止、备份等命令openwrt 代码框架分析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

STM32f103之外部中断

一、背景 有个需求,IO口检测上升沿,然后做相应的动作。在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用。 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会让你看的更远,走的更快, 感谢老司机。 二、正文 STM32f103有68个可屏蔽中断。(...

STM32系统时钟RCC(基于HAL库)

基础认识 为什么要有时钟: 时钟就是单片机的心脏,其每跳动一次,整个单片机的电路就会同步动作一次。时钟的速率决定了两次动作的间隔时间。速率越快,单片机在单位时间内所执行的动作将越多。时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率。 为什么这么多个时钟源: STM32系统是复杂的,高精度、低精度、...

基于MCP2515的Linux CAN总线驱动程序设计(三)

基于MCP2515的Linux CAN总线驱动程序设计(三) 作者:李老师,华清远见嵌入式学院讲师。 1.前言 上篇文章介绍了使用SPI子系统设计的基于MCP2515的Linux CAN总线驱动程序,这篇文章主要介绍MCP2515的字符设备驱动功能函数的实现。 2.硬件设计 MCP2515与S3C2416的硬件连接图如图3所示。如硬件原理图可知MCP251...

定时器与系统时间(续)

额外问题处理: -------------------------------------------------------------------------------- 13) 定时器之外的一些处理     a) window环境下,定时器通知执行定时任务的时间点可能误差1毫秒;Linux环境也有类似情况,但是误差频率低很多(只是在指定时间点前后1...

Linux 信号signal处理机制

信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念、Linux对信号机制的大致实现方法、如何使用信号,以及有关信号的几个系统调用。 信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实质和使用很象中断。所以,信号可以说是进程控制的一部分。 一、信号的基本概念 本节先介绍信号的一...

关于STM32F103系列从大容量向中容量移植的若干问题

一、把STM32F103大容量移植到STM32F103C8T6上的步骤: 1、换启动文件 startup_stm32f10x_cl.s ——互联型的器件 包括:STM32F105xx,STM32F107xx startup_stm32f10x_hd.s ——大容量器件 包括:STM32F101xx,STM32F102xx,STM32F103xx start...