STM32--寄存器与标准库函数--通用定时器--输出比较(PWM生成)

目录

前言

通用定时器类型

向上计数、向下计数、中心对齐

输入捕获与输出比较概念

输出比较典型例子:驱动舵机旋转

通用定时器的输出比较库函数

代码

通用定时器的输出比较寄存器操作

代码

这里提供数据手册的寄存器

后言


前言

使用平台:STM32F407ZET6

使用数据手册:STM32F407数据手册.pdf

使用参考手册:STM32F4xx参考手册(中文).pdf

使用cortex-M手册:Cortex M3与M4权威指南.pdf

对于STM32F407微处理器而言,内部一共集成了14 个定时器,其中有2个基本定时器(TIM6和TIM7)、10个通用定时器(TIM2~TIM5、TIM9~TIM14)、2个高级定时器(TIM1和TIM8)。

通用定时器类型

通用定时器相对于基本定时器增加了输入捕获与输出比较功能。

可以确定,递增计数是所有定时器通用的,保险起见,整体设置为递增计数可以提高通用性。

向上计数、向下计数、中心对齐

STM32F407ZET6一共提供10个通用定时器(TIM2~TIM5、TIM9~TIM14),TIM2和TIM5是32bit定时器,其他的定时器都是16bit定时器。TIM2~TIM5的计数方式有三种可以选择,分别为递增计数、递减计数、递增/递减计数。

递增计数:计数器从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件。

递减计数:计数器从自动重载值(TIMx_ARR 寄存器的内容)开始递减计数到 0,然后重新从自动重载值开始计数并生成计数器下溢事件。

中心对齐:计数器从 0 开始计数到自动重载值(TIMx_ARR 寄存器的内容)- 1,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数。

对于通用定时器TIM2~TIM5,都挂载在APB1外设总线下,定时器的频率为84MHZ,对于TIM12~TIM14都挂载在APB1外设总线下,定时器的频率为84MHZ,TIM9~TIM11是挂载在APB2总线下,所以定时器的频率为168MHZ,如下图

输入捕获与输出比较概念

输入捕获 :可以把定时器的某个通道连接到GPIO引脚上,然后从外部输入脉冲信号,经过通道的滤波以及边沿检测之后,可以记录某个电平信号的脉冲宽度以及周期。

输出比较 :可以把定时器的某个通道连接到GPIO引脚上,主动从引脚输出一个固定的脉冲,原理很简单,其实就是计数器(TIM_CNT)如果超过**比较寄存器(CCR)**中的值,就可以输出一个电平信号(高电平或者低电平)。

对于TIM9~TIM14而言,也可以进行定时功能,同样也具有输入捕获以及输出比较功能,但是只能采用向上计数的方式,并且相比于TIM2~TIM5,只有2个独立通道。

输出比较典型例子:驱动舵机旋转

驱动舵机旋转需要调制PWM,PWM技术的关键参数有两个,一个是频率 ,一个是占空比 。频率指的是利用STM32的定时器通道输出脉冲的次数。占空比是指在一个脉冲周期中通电时间相对于总时间所占的比例,也可以简单理解为一个周期内高电平持续时间相对于总时间所占的比例( %)

舵机(Servo Motor)是一种集成了电机、减速齿轮组、控制电路和位置反馈系统的微型伺服装置,可通过接收外部控制信号实现高精度角度定位。与传统电机不同,舵机无需持续旋转,而是通过内置电位器或编码器实时检测输出轴角度,形成闭环控制,从而精准到达指定位置并保持力矩。

一般180°控制旋转的舵机,驱动的PWM参数:

通用定时器的输出比较库函数

代码

本质调用了如下函数可以实现输出比较功能

cpp 复制代码
RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE) 
RCC_AHBxPeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);

GPIO_Init(GPIOx, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_TIMx);

TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStruct);
TIM_OCxInit(TIMx, &TIM_OCInitStruct);

TIM_OCxPreloadConfig(TIMx, TIM_OCPreload_ENABLE); 
TIM_ARRPreloadConfig(TIMx, ENABLE);

TIM_Cmd(ENABLE)

库函数代码:

PF9的TIM14通用定时器实现的PWM

cpp 复制代码
/**
 * @brief PF9的TIM14通用定时器实现的PWM
 *
 */
void TimerCaptureOutputInit(void)
{
    /* 开启GPIOF与TIM14的时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);

    /* 配置GPIO为AF复用功能 */
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);

    /* 配置定时器的时基配置 20ms*/
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 2000 - 1;
    TIM_TimeBaseInitStruct.TIM_Prescaler = 840 - 1;
    TIM_TimeBaseInit(TIM14, &TIM_TimeBaseInitStruct);

    /* 配置输出捕获配置 */
    TIM_OCInitTypeDef TIM_OCInitStruct;
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse = 1000;
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM14, &TIM_OCInitStruct);

    TIM_ARRPreloadConfig(TIM14, ENABLE);
    TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);

    TIM_Cmd(TIM14, ENABLE);
}

通过操控CRR寄存器或者TIM_SetComparex函数

cpp 复制代码
TIM_SetComparex(TIMx, Compare1)

或者

cpp 复制代码
TIMx->CCRx = 1500;

通用定时器的输出比较寄存器操作

代码

cpp 复制代码
/**
 * @brief 基本定时器TIM4 CH4 PB9
 *        PWM波生成
 */
void TimerNormalTIM4_4RegisterInit(void)
{
    // 初始化时钟
    RCC->AHB1ENR |= (1 << 1); // GPIOB
    RCC->APB1ENR |= (1 << 2); // TIM4

    // 对GPIOB的模式配置
    GPIOB->MODER &= ~(3 << (2 * 9));
    GPIOB->MODER |= (2 << (2 * 9)); //复用功能

    GPIOB->OSPEEDR |= (3 << (2 * 9));
    GPIOB->OTYPER &= ~(1 << 9); //推挽

    GPIOB->PUPDR &= ~(3 << 18); // 先清零
    GPIOB->PUPDR |= (1 << 18);  // 上拉(或 0 浮空,2 下拉)

    // 配置GPIOB与复用功能(TIM4_CH4)联合
    GPIOB->AFR[1] &= ~(0xf << 4);
    GPIOB->AFR[1] |= (2 << 4); //绑定具体的复用功能 TIM4 CH4

    // 配置定时器参数
    TIM4->CR1 &= ~(1 << 0); // 关闭定时器
    /* 配置分频系数等参数 */
    TIM4->ARR = 20000 - 1;
    TIM4->CNT = 0;
    TIM4->PSC = 84 - 1;
    TIM4->CCR4 = 1500 - 1;

    TIM4->CR1 |= (1 << 7);  // 自动重载预装载值
    TIM4->CR1 &= ~(1 << 4); // 计数器向上计数

    TIM4->CCMR2 &= ~(7 << 12);
    TIM4->CCMR2 |= (6 << 12); // PWM模式1
    TIM4->CCMR2 |= (1 << 11); // 输出比较4预装载使能

    TIM4->CCER |= (1 << 12);  //使能通道CH4

    TIM4->DIER &= ~(1 << 0);  //未使用中断,所以禁止中断
    TIM4->EGR |= (1 << 0);  //

    TIM4->CR1 |= (1 << 0); // 开启定时器
}

这里提供数据手册的寄存器

GPIO的模式寄存器设置为复用功能模式

复用功能寄存器

此寄存器需要对照数据手册

TIM的部分寄存器

控制寄存器

TIM捕获/比较模式寄存器

TIM捕获/比较使能寄存器

TIM事件生成寄存器

后言