第27章 通用定时器-定时

第二十七章 通用定时器-定时

1. 硬件设计

TIM输入stm32内部资源无需硬件设计,led电路我们也已经分析过了

2. 软件设计

  • TIM相关参数宏定义
#define GENERAL_TIM                TIM2                   // 选择使用的定时器--TIM2
#define GENERAL_TIM_APBxClock_FUN  RCC_APB1PeriphClockCmd // 选择挂载的定时器时钟--RCC_APB1Periph_TIM2
#define GENERAL_TIM_CLK            RCC_APB1Periph_TIM2    // 选择使用的定时器时钟--RCC_APB1Periph_TIM2
#define GENERAL_TIM_Period         (1000-1)               // 定时器周期--1000-1
#define GENERAL_TIM_Prescaler      71                     // 定时器分频系数--71
#define GENERAL_TIM_IRQ            TIM2_IRQn              // 选择使用的定时器中断--TIM2_IRQn
#define GENERAL_TIM_IRQHandler     TIM2_IRQHandler        // 选择使用的定时器中断处理函数--TIM2_IRQHandler
  • 配置中断
// NVIC中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{
    // 1.定义NVIC_InitTypeDef结构体
    NVIC_InitTypeDef NVIC_InitStructure; 
    // 2.设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);        
    // 3.设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;    
    // 4.设置主优先级为 0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     
    // 5.设置抢占优先级为3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    // 6.使能中断    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    // 7.初始化NVIC
    NVIC_Init(&NVIC_InitStructure);
}

中断配置,我们已经见到很多了,不必解释

  • 配置定时器模式
// 定时器模式配置
static void GENERAL_TIM_Mode_Config(void)
{
    // 1.定义TIM_TimeBaseInitTypeDef结构体
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;        
    // 2.开启定时器时钟,即内部时钟CK_INT=72M
    GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK, ENABLE);    
    // 3.自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = GENERAL_TIM_Period;
    // 4.时钟预分频数
    TIM_TimeBaseStructure.TIM_Prescaler = GENERAL_TIM_Prescaler;    
    // 5.时钟分频因子 ,没用到不用管
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        
    // 6.计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;         
    // 7.重复计数器的值,没用到不用管
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;    
    // 8.初始化定时器
    TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
    // 9.清除计数器中断标志位
    TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update);
    // 10.开启计数器中断
    TIM_ITConfig(GENERAL_TIM, TIM_IT_Update, ENABLE);
    // 11.使能计数器
    TIM_Cmd(GENERAL_TIM, ENABLE);
}

对定时器的配置简要说明如下:

  1. 定义结构体:定义用于定时器基础配置的结构体 TIM_TimeBaseInitTypeDef
  2. 开启时钟:启用定时器的时钟。这里假设 GENERAL_TIM_APBxClock_FUN 是一个宏或函数,用于使能定时器时钟。
  3. 自动重装载寄存器:设置定时器的自动重装载寄存器的值,这决定了定时器的溢出周期。
  4. 时钟预分频:设置时钟预分频数,影响定时器的计数频率。
  5. 时钟分频因子:设置时钟分频因子(未用到可以保持默认值)。
  6. 计数模式:设置计数模式为向上计数。
  7. 重复计数器:设置重复计数器的值(未用到可以保持默认值)。
  8. 初始化定时器:根据配置初始化定时器。
  9. 清除中断标志:清除定时器更新中断标志位,确保中断不会立即触发。
  10. 开启中断:启用定时器更新中断。
  11. 使能计数器:启动计数器,使定时器开始计数。
  • 定时器初始化
void GENERAL_TIM_Init(void)
{
    GENERAL_TIM_NVIC_Config();
    GENERAL_TIM_Mode_Config();        
}

定时器初始化即中断配置和定时器配置

  • 主函数
// 通用定时器TIMx,x[2,3,4,5]定时应用
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_GENERALTim.h" 

uint32_t time = 0; // ms 计时变量 

int main(void)
{
  // led 端口配置
  LED_GPIO_Config();
  // TIM初始化    
  GENERAL_TIM_Init();

  while(1)
  {
    if(time == 1000) // 1000 * 1 ms = 1s 时间到
    {
      time = 0; // 计数器清零
      // LED1 取反       
      LED1_TOGGLE; 
    }        
  }
}

这个程序应该比较简单了,就是利用定时器进行定时,到达一秒后,定时器更新,LED状态取反

3. 小结

照例,我们还是来回顾一下基本流程,尽管这个实验很简单:

1. 配置系统时钟

首先确保系统时钟配置正确。通常,这在启动文件或者系统初始化代码中已经完成。

2. 启用定时器时钟

启用TIM2时钟。这里假设你正在使用STM32标准外设库,RCC_APB1PeriphClockCmd函数用于启用外设时钟。

3. 配置定时器基础设置

配置定时器的基础参数,包括自动重装载寄存器值、预分频器等。

4. 使能定时器中断(如果需要)

配置定时器中断并设置优先级。

5. 启动定时器

使能定时器,开始计数。

6. 示范代码

#include "stm32f0xx.h"  // 包含STM32F0系列的头文件

void TIM2_IRQHandler(void);  // 定义定时器中断处理函数原型

void TIM2_Config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 1. 启用TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 2. 配置TIM2的基础设置
    TIM_TimeBaseStructure.TIM_Period = 7999;  // 定时器周期
    TIM_TimeBaseStructure.TIM_Prescaler = 999; // 时钟预分频
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    // 初始化定时器
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    // 3. 清除TIM2更新中断标志
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    // 4. 使能TIM2更新中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    // 5. 配置定时器中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 6. 启动TIM2
    TIM_Cmd(TIM2, ENABLE);
}

// 定时器中断处理函数
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        // 处理定时器中断
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        // 在这里执行你的定时任务
    }
}

int main(void)
{
    // 系统初始化代码
    SystemInit();

    // 配置TIM2
    TIM2_Config();

    while (1)
    {
        // 主循环中可以执行其他任务
    }
}

2024.9.12 第一次修订,后期不再维护

posted @ 2024-09-12 16:16  hazy1k  阅读(5)  评论(0编辑  收藏  举报