【STM32】通用定时器TIM(输出比较)
本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发
目录
前言
输出比较简介
PWM简介
输出比较配置
初始化IO口
输出比较初始化
输出比较代码
PWM.h
PWM.c
main.c
应用案例
前言
建议先阅读这篇博客,理解时基单元的配置
【STM32】通用定时器TIM(时钟源选择与更新中断)-CSDN博客
输出比较简介
OC(Output Compare)输出比较,可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
STM32F10xxx通用定时器为TIM2、TIM3、TIM4和TIM5,每个通用定时器都拥有4个输出比较通道和4个输入捕获通道
输出比较和输入捕获的共用一个通用定时器的4个通道,一个定时器使用了其中一个功能,另一个就不能用了。
输出比较框图
定时器的PSC预分频器,自动重装载寄存器,捕获/比较寄存器下面都有黑色影子,这些寄存器可选择寄存器值在更新事件装入或者即时装入
高级定时器
- 每个高级定时器也拥有4个输出比较通道
- 高级定时器的前3个通道额外拥有死区生成和互补输出的功能
高级定时器不是本博客学习内容,了解即可
PWM简介
PWM(Pulse Width Modulation)脉冲宽度调制
在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
将数字量等效为模拟量
PWM参数 | 含义 |
频率 | 1/T_S |
占空比 | T_ON/T_S |
分辨率 | 占空比变化步距 |
图解
输出比较配置
PWM频率Freq= CK_PSC/(PSC + 1)/(ARR + 1)
PWM占空比:Duty = CCR/(ARR + 1)
PWM分辨率:Reso =1/(ARR + 1)
初始化IO口
GPIO的其它参数的理解可以阅读下方博客,这里不再赘述。
【STM32】GPIO和AFIO标准库使用框架_gpio afio-CSDN博客
查找引脚定义表,将通用定时器2的输出比较通道1(PA0)配置为复用推挽输出,由定时器输出至GPIO。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
输出比较初始化
输出比较框图
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化,若结构体没有完整赋值
//则最好执行此函数,给结构体所有成员都赋一个默认值
//避免结构体初值不确定的问题
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //初始的CCR值
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1
参数TIM_OCMode:
输出比较模式
参数TIM_OCPolarity :
输出比较代码
PWM.h
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);
#endif
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
/**
* 函 数:PWM设置CCR1
* 参 数:Compare 要写入的CCR的值,范围:0~100
* 返 回 值:无
* 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
* 占空比Duty = CCR / (ARR + 1)
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);
}
/**
* 函 数:PWM设置PSC
* 参 数:Prescaler 要写入的PSC的值,范围:0~65535
* 返 回 值:无
* 注意事项:PSC和ARR共同决定频率,此函数仅设置PSC的值,并不直接是频率
* 频率Freq = CK_PSC / (PSC + 1) / (ARR + 1)
*/
void PWM_SetPrescaler(uint16_t Prescaler)
{
TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate); //设置PSC的值
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "PWM.h"
uint8_t i;
int main(void)
{
PWM_Init();
while (1)
{
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(i);
Delay_ms(10);
}
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(100 - i);
Delay_ms(10);
}
}
}
应用案例
呼吸灯
LED-STM32单片机驱动单色LED和RGB全彩LED亮灭与呼吸灯代码_rgb led驱动代码-CSDN博客
舵机
SG90舵机介绍与PWM驱动代码_sg90是数字舵机还是模拟舵机-CSDN博客
电机
TB6612FNG电机驱动模块(控制电机转向和转速)-CSDN博客
无源蜂鸣器
蜂鸣器—STM32驱动有源与无源蜂鸣器的介绍与代码示例_tmb12a05驱动电路-CSDN博客