STM32之定时器(一)

1. 定时器介绍(这里以STM32F103C8T6为例)

• STM32F103C8T6微控制器内部集成了许多类型的定时器,这些定时器在嵌入式系统中扮演重要角色,用于计时,延时,事件触发,以及 PWM 波形成,脉冲捕获等应用。

• TIM1:这是一个高级定时器,不仅具备基本的定时中断功能 ,还拥有内外时钟选择,输入捕获,输出比较,编码器接口 以及主从触发模式等多种功能。使得TIM1能够适用于各种复杂的应用场景,为开发者提供强大的时间控制和信号处理能力。

• TIM2,TIM3和TIM4:这三个是通用定时器,同样具备定时的功能,但在功能上与高级定时器有所区别。通用定时器常用作实现一些基本的定时任务,如LED闪烁,脉冲宽度测量等。

• 每个定时器都由一个16 的计数器,预分频器和自动重装载寄存器的时基 单元组成。预分频器可以对时钟进行分频 ,计数器则对预分频后的时钟进行计数。当计数器的值达到设定值时,会触发中断,从而执行相应的定时任务。

2. 定时器的工作原理

2.1 定时器的核心是计数器,如图:

3. 三种定时器的介绍

3.1 基本定时器,一般编号为TIM6和TIM7,接入的总线是APB1,功能是拥有定时中断、主模式触发 DAC 的功能。如图:

3.2 通用定时器一般有:TIM2,TIM3,TIM4,TIM5,接入的总线是APB1,功能是拥有基本定时器全部功能 ,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能,如图:

3.3 高级定时器,一般是TIM1和TIM8,接入的总线是APB2,功能是拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能,如图:

4. 计数模式

4.1 计数模式有三种,分别位向上计数,向下计数,中心对齐计数。如图:

5. 定时器溢出时间计算

• 如图:

• Tout是定时器溢出的时间,ARR是重装载寄存器里面的值,PSC预分频寄存器里面的值,Ft是时钟源频率

• 例如,我们现在要定时500ms,则其余三个项该怎么配置

• 首先,我们这里的时钟使用的是72M,则其余两个应当配置为ARR=4999,PSC=6199,最好是往整数配置。注意:虽然是自己配置,但是ARR的值不能太小

• 计算过程是:带入数据为,(4999 + 1)*(7199 + 1)/ (72 * 10的六次方),即5000 * 7200 * 72 * 10的负6次方。

• 即:5*10的3次方 * 7.2 * 10的3次方 * 72 * 10的负6次方。月份之后就是等于0.5s,即500ms。

6. 定时器中断实验配置步骤

• 时基工作参数配置 HAL_TIM_Base_Init()

• msp初始化(GPIO,NVIC,CLOCK等)

• HAL_TIM_Base_MspInit()

• __HAL_RCC_TIMx_CLK_ENABLE()

• HAL_NVIC_SetPriority

• HAL_NVIC_EnableIRQ()

• 使能更新中断

• 启动定时器

• 上述这两步在HAL_TIM_Base_Start_IT()中配置

• 中断服务函数编写,TIMx_IRQHandler()

• 更新中断回调函数编写,HAL_TIM_PeriodElapsedCallback()

6.1 实操 定时器中断点灯 使用定时器 2 进行中断点灯,500ms LED 灯翻转一次。

• timer.c

cpp 复制代码
#include "timer.h"
#include "led.h"

TIM_HandleTypeDef timer_handle = {0};//定时器的句柄

void timer_init(uint16_t arr,uint16_t psc){//定时器初始化,arr是自动重装载值寄存器,psc是预分频器
    timer_handle.Instance = TIM2;//使用的是定时器2
    
    timer_handle.Init.Prescaler = psc;
    timer_handle.Init.Period = arr;
    timer_handle.Init.CounterMode = TIM_COUNTERMODE_UP;//计算模式,选择向上计数
    timer_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;//不使用自动重装预加载功能
   
//    timer_handle.Init.ClockDivision //这个与死区生成有关的
//    timer_handle.Init.RepetitionCounter 这个是重复计数  这两个选项与高级定时器有关
    
    HAL_TIM_Base_Init(&timer_handle);//初始化时基
    HAL_TIM_Base_Start_IT(&timer_handle);//使能中断更新和打开定时器
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim){//初始化msp函数,该函HAL_TIM_Base_Init函数里面被调用
    if(htim ->Instance == TIM2){
        __HAL_RCC_TIM2_CLK_ENABLE();
        HAL_NVIC_SetPriority(TIM2_IRQn,2,2);
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
    }
}

void TIM2_IRQHandler(){//中断服务函数
    HAL_TIM_IRQHandler(&timer_handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){//更新中断回调函数
    if(htim ->Instance == TIM2){
        led_toggle();//翻转
    }
   
}

• main.c

cpp 复制代码
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "led.h"
#include "timer.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
    timer_init(5000 - 1,7200 - 1);
    while(1) 
    { 
       
    }
}

7. 输出比较

• 输出比较可以通过比较 计数器的值 CNT 与设定的比较值 CCR,可以控制输出引脚的电平状态(置高或置低),从而实现生成一定频率和占空比的 PWM 波形。如图:

• PWM模式有两种,TIM_OCMODE_PWM1和TIM_OCMODE_PWM2,区别就是一个正向一个反向。

• 有效电平可以选择低电平或者高电平,根据需要来选择

• 所以一共有4种选择 图:

8. PWM介绍

• PWM波形(Pulse Width Modulation,脉冲宽度调制波形)是一种占空比可调的脉冲信号波形 。这种调制方式是通过改变脉冲宽度 来控制电路中的信号强度和频率。具体来说,PWM波形中的高电平持续时间和低电平持续时间可以根据需要进行调整,从而实现对模拟信号电平的数字编码。

• PWM波形在各种领域都有广泛的应用,包括电源管理、电机控制、LED 亮度调节等。此外,生成PWM波形的方法有多种,例如使用波形发生器、单片机或可编程逻辑器件等。

• 占空比的定义是脉冲信号在一个周期内处于高电平(或有效电平)的时间占比 。

8.1 定时器输出PWM波形配置步骤

• 时基工作参数配置 HAL_TIM_PWM_Init()。

• msp初始化(GPIO,NVIC,CLOCK等):

• HAL_TIM_Base_MspInit()。

• __HAL_RCC_TIMx_CLK_ENABLE()。

• 配置相应的GPIO的PWM模式,CCR寄存器设置。

• 使能输出,并启动计数器,HAL_TIM_PWM_Start()。

• 修改CCR寄存器的值,__HAL_TIM_SET_COMPARE()

8.2 实操,呼吸灯实验

• pwm.c

cpp 复制代码
#include "pwm.h"

TIM_HandleTypeDef tim_handle = {0};//定时器句柄

//pwm初始化
void pwm_init(uint16_t arr,uint16_t psc){
    TIM_OC_InitTypeDef pwm_handle = {0};
    tim_handle.Instance = TIM4;
    
    tim_handle.Init.Period = arr;
    tim_handle.Init.Prescaler = psc;
    tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    tim_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_PWM_Init(&tim_handle);
    
    pwm_handle.OCMode = TIM_OCMODE_PWM1;//选择pwm1模式
    pwm_handle.Pulse = arr / 2;//给CCR寄存器一个初值
    pwm_handle.OCPolarity = TIM_OCPOLARITY_LOW;//有效电平是低电平
//    tim_oc_handle.OCFastMode 这个是快速模式,用于优化PWM信号输出的性能
//    tim_oc_handle.OCIdleState 这个是空闲状态输出的电平,设置定时器通道在空闲状态(BDTR_MOE位为0)时的输出电平
//    tim_oc_handle.OCNIdleState 这个是空闲状态互补输出的电平,设置定时器互补通道在空闲状态时的输出电平
//    tim_oc_handle.OCNPolarity 这个是互补输出极性,设置互补输出信号(OCxN)的有效极性
    //上述这四个参数都与高级定时器有关
    HAL_TIM_PWM_ConfigChannel(&tim_handle,&pwm_handle,TIM_CHANNEL_3);//设置pwm模式,CCR寄存器,选择通道
    HAL_TIM_PWM_Start(&tim_handle,TIM_CHANNEL_3);//开启计数器,使能输出
}

//msp函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim){
    if(htim->Instance == TIM4){
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_TIM4_CLK_ENABLE();
        GPIO_InitTypeDef gpio_init = {0};
        gpio_init.Mode = GPIO_MODE_AF_PP;//参考手册的外设gpio,输出比较选择推挽复用输出
        gpio_init.Pin = GPIO_PIN_8;//推挽输出
        gpio_init.Pull = GPIO_PULLUP;//默认上拉
        gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB,&gpio_init);    
    }
    
}
//修改CCR寄存器的值
void pwm_compare_set(uint16_t crr){
    __HAL_TIM_SET_COMPARE(&tim_handle,TIM_CHANNEL_3,crr);
}

• main.c

cpp 复制代码
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "led.h"
#include "pwm.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
    pwm_init(500 - 1,72 - 1);
    uint16_t i = 0;
    while(1)//呼吸灯实验
    { 
       for(i = 0; i < 300; i++){//这里CCR寄存器值最大为300,这里不断修改CCR寄存器的值
            pwm_compare_set(i);
            delay_ms(10);//延时一下,每修改一次
       }
       
       for(i = 0; i < 300; i++){//这里CCR寄存器值最大为300,这里不断修改CCR寄存器的值
            pwm_compare_set(300 - i);
            delay_ms(10);//延时一下,每修改一次
       }
    }
}
相关推荐
Y1rong2 小时前
STM32之SysTick
stm32·单片机·嵌入式硬件
广药门徒2 小时前
WINDOWS 10如何在PCB 等软件自由使用快捷键
嵌入式硬件
代码游侠2 小时前
学习笔记——GPIO按键与中断系统
c语言·开发语言·arm开发·笔记·嵌入式硬件·学习·重构
__万波__3 小时前
STM32L475按键中断实验
stm32·单片机·嵌入式硬件
破晓单片机3 小时前
STM32单片机分享:智能恒温箱系统
stm32·单片机·嵌入式硬件·智能家居
小痞同学3 小时前
【铁头山羊STM32】HAL库 6.中断部分
stm32·单片机·嵌入式硬件
你爱写程序吗(新H)3 小时前
基于单片机的洗衣机控制系统设计 单片机洗衣机控制(设计+文档)
c语言·汇编·单片机·嵌入式硬件·matlab
淘晶驰AK3 小时前
新手学单片机,主要是玩,学什么好?
单片机·嵌入式硬件
恶魔泡泡糖3 小时前
51单片机I-O扩展1
c语言·嵌入式硬件·51单片机