stm32基本定时器控制led闪烁(标准库)

定时器

stm32f1系列,一般有8个定时器,分为基本定时器,通用定时器和高级定时器

基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部IO。通用定时器TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。

基本定时器

定时器寄存器概述

CR1 (Control Register 1): 控制定时器的使能、计数模式选择等。

  •  CEN: 计数使能位,启用定时器。
  •     ARPE位的作用是使能或禁止ARR的预装载功能
  • 当ARPE = 1:

    自动重载值(ARR)在定时器的计数过程中可以随时被修改,但新设置的值将在下一个更新事件(计数器溢出)后生效。

    当ARPE = 1:

    启用预装载功能。在这种情况下,如果你修改了ARR的值,新值会在下一个更新事件前生效,而不是立即应用。这意味着新的自动重载值在当前计数周期内不会影响计数过程,只是在计数器达到当前ARR时使用新设置的值。

    PSC (Prescaler Register): 分频器寄存器,用于设置定时器的时钟频率。定时器时钟频率为系统时钟频率除以(PSC + 1)。

    CNT (Counter Register): 当前计数值寄存器,保持当前计数的值。

    DIER(DMA/Interrupt Enable Register):用于配置定时器相关的中断和DMA请求。

    SR (Status Register):状态寄存器:   用于标识定时器的状态和标志位,如溢出、更新等。

      ARR (Auto-Reload Register): 自动重载寄存器,设置计数器的最大值。当计数器达到这个值后会复位并重新开始计数。

    ARR它定义了定时器计数的上限值。当定时器的计数器(CNT)达到这个值时,会发生以下几种情况:

    1. 计数器重置

      当计数器的值达到ARR设定的值后,计数器会被重置为零(0)。

    2. 更新事件

      达到ARR值时,会产生一个更新事件,这通常用于触发中断或其他相关操作。定时器可以配置为在这种情况下产生中断。

    3. 周期性行为

      ARR的设置决定了定时器的运行周期。例如,如果将ARR设置为10000,而预分频器(PSC)设置为7200,那么计数器将在每1秒内完成一次完整的循环。这对于实现定时任务(如LED闪烁、数据采集等)非常有用。

    当给PSC赋值后,会等到CNT重新变为0后才会将值赋给影子寄存器。

    一些函数介绍

    1. 初始化和配置

    TIM_TimeBaseInit

    初始化定时器的基本设置,包括预分频、计数模式等。

    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseStruct);
    
    //TIM_TimeBaseStruct: 指向包含基本定时器设置的结构体的指针,该结构体定义如下:
    
    typedef struct { 
    
        uint16_t TIM_Prescaler; // 预分频值 
        uint32_t TIM_CounterMode; // 计数模式 (TIM_CounterMode_Up, TIM_CounterMode_Down) 
        uint32_t TIM_Period; // 自动重载值 
        uint16_t TIM_ClockDivision; // 时钟分割 (TIM_CKD_DIV1, TIM_CKD_DIV2, TIM_CKD_DIV4)
        uint32_t TIM_RepetitionCounter; // 重复计数值 (用于高级定时器)
    
     }TIM_TimeBaseInitTypeDef;

    2. 输出比较配置

    TIM_OCInit

    配置定时器的输出比较功能,用于生成 PWM 信号或其他类型的输出比较信号。

    void TIM_OCInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    
    //TIM_OCInitStruct: 指向包含输出比较设置的结构体的指针,该结构体定义如下:
    
    typedef struct { 
        uint16_t TIM_OCMode; // 输出比较模式 (如 TIM_OCMode_Timing, TIM_OCMode_PWM1) 
        uint32_t TIM_OutputState; // 输出状态 (TIM_OutputState_Enable, TIM_OutputState_Disable) 
        uint32_t TIM_Pulse; // 比较值 
        uint16_t TIM_OCPolarity; // 输出极性 (TIM_OCPolarity_High, TIM_OCPolarity_Low) 
        uint16_t TIM_OCFastMode; // 快速模式 (ENABLE/DISABLE)
     } TIM_OCInitTypeDef;

    3. 启用或禁用定时器

    TIM_Cmd
    void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

    4. 中断管理

    TIM_ITConfig

    配置定时器的中断功能

    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
    
    
    //TIM_IT: 要配置的中断类型(例如:TIM_IT_Update、TIM_IT_CC1 等)。
    
    TIM_GetITStatus

    检查特定定时器中断的状态。

    FlagStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
    TIM_ClearITPendingBit

    清除特定定时器的中断挂起位。

    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

    5. 设置计数器和预分频器

    TIM_SetCounter
    void TIM_SetCounter(TIM_TypeDef* TIMx, uint32_t Counter);
    
    //Counter: 要设置的计数器值。
    
    TIM_PrescalerConfig
    void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, 
    TIM_PSCReloadMode ReloadMode);
    
    
    
    //Prescaler: 新的预分频值。
    
    //ReloadMode: 重新加载方式(例如:TIM_PSCReloadMode_Update)。

    代码

    timer.c

    #include "timer.h"
    
    
    void Timer_NVIC_Config(void){
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    
    	  /* 嵌套向量中断控制器组选择 */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    	
    	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
    	
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	
    	NVIC_Init(&NVIC_InitStructure);
    }
    
    void Basic_Timer_Init(void){
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	
    	TIM_InternalClockConfig(TIM6);
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
    	
    	TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
    	TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
    	
    	TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
    	
    	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
    	
    	TIM_Cmd(TIM6,ENABLE);
    }

    main.c

    #include "stm32f10x.h"
    #include "systick.h"
    #include "usart.h"
    #include "timer.h"
    #include "LED.h"
    
    uint16_t time = 0;
    
    int main()
    {
    	LED_ConfigInit();
    //	USART_Init_Config();
    	SystemClock_Config();
    	Timer_NVIC_Config();
    	Basic_Timer_Init();
    	
    	while(1)
    	{
    		if(time == 1000)
    		{
    			time = 0;
    			GPIOB->ODR ^= GPIO_Pin_5;
    //			GPIO_Toggle(GPIOB,GPIO_Pin_5);
    		}
    	}
    }
    

     stm32f10x_it.c添加

    extern uint16_t time;
    
    void TIM6_IRQHandler(void){
    	if(TIM_GetITStatus(TIM6, TIM_IT_Update)!=RESET)
    	{
    		time++;	
    		TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
    	}
    }
    

     设置系统时钟

    void SystemClock_Config(void)
    {
        // 启动 HSE(外部高速晶振)
        RCC->CR |= RCC_CR_HSEON; // 开启 HSE
        while (!(RCC->CR & RCC_CR_HSERDY)); // 等待 HSE 变为就绪状态
    
        // 配置 Flash 延迟周期
        FLASH->ACR |= FLASH_ACR_LATENCY_2; // 对于 72MHz,设置延迟周期为 2 WS
    
        // 配置 PLL
        RCC->CFGR |= RCC_CFGR_PLLSRC_HSE; // 选择 HSE 作为 PLL 输入
        RCC->CFGR |= RCC_CFGR_PLLMULL9; // 设置 PLL 倍频因子为 9 (8 MHz * 9 = 72 MHz)
    
        // 启动 PLL
        RCC->CR |= RCC_CR_PLLON; // 开启 PLL
        while (!(RCC->CR & RCC_CR_PLLRDY)); // 等待 PLL 就绪
    
        // 将 PLL 作为系统时钟
        RCC->CFGR |= RCC_CFGR_SW_PLL; // 选择 PLL 作为系统时钟
        while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待 PLL 成为系统时钟
    }

    如果led的闪烁时间不对,就是时钟源不对,因为我用的正点的zet6和野火的板子不一样,也是搞了半天才解决(笑~),TIM_InternalClockConfig()作用是将定时器的时钟源设置为内部时钟。

    作者:zhi_beiyou

    物联沃分享整理
    物联沃-IOTWORD物联网 » stm32基本定时器控制led闪烁(标准库)

    发表回复