STM32F103定时器TIM3输出PWM控制电机
程序员文章站
2022-06-08 19:55:40
...
STM32F103ZET6定时器TIM3 CH2输出PWM控制电机
一、认识PWM是如何输出的
输出PWM之前首先查阅STM32中文参考手册,查看哪些定时器可以输出PWM波,该定时器可以映射到哪些引脚作为PWM波的输出。
对应查看的是通用和复用功能I/O里面的软件重新映射I/O复用功能。
STM32F1的基本定时器以及功能介绍如下图所示:
二、查阅STM32中文参考手册复用和通用功能I/O—软件重映射篇
我选用的是TIM3作为PWM输出,所以找到TIM3定时器的复用功能重映像介绍,表格如下:
根据以上表格,再看自己的板子需要在哪个引脚输出PWM
我这里选择的是TIM3_CH2通道,该通道对应可以映射的引脚是PB5
注意:该引脚是部分重映射引脚,所以在对引脚进行重映射时的函数应该用: GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE)
三、直流电机与单片机的硬件连线
采用的硬件有:STM32F103ZET6开发板、直流电机、L298N电机驱动模块、杜邦线、直流可调稳压电源
根据L298N模块的接线要求,仔细与开发板接好线
注意:
模块集成了一个内置的5V供电。当你的驱动电压为7V-35V的时候,可以使能板载的5V逻辑供电,当使用板载5V供电之后,接口中的+5V供电不要输入电压,但是可以引出5V电压供外部使用
当ENA 使能 IN1 IN2 控制 OUT1 OUT2 当ENB 使能 IN3 IN4 控制 OUT3 OUT4
如果你没有+12V电源,也可以用开发板的5V电压输出引脚来给L298N模块供电
注意:L298N模块与开发板一定要共地!!!
否则可能出现,程序写对了但是电机毫无反应等一系列问题
四、PWM.h程序
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif
五、PWM.c程序
#include "PWM.h"
//这里使用的是定时器3!
//TIM3挂在APB2上,所以这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//TIM3 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
//设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM3 Channel2 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
六、main.c程序
#include "delay.h"
#include "sys.h"
#include "PWM.h"
int main(void)
{
int i;
delay_init(); //延时函数初始化
TIM3_PWM_Init(899,0); //不分频。PWM频率=72000000/900=80Khz
TIM_SetCompare2(TIM3,400);
while(1)
{
//不断改变比较值CCRx,达到不同的占空比效果:第二值参数范围:0~499
for(i = 0; i <= 499; i++) //逐快
{
delay_ms(15);
TIM_SetCompare2(TIM3, i);
}
if(i > 499)
{
for(i = 499; i >= 0; i--) //逐渐
{
delay_ms(15);
TIM_SetCompare2(TIM3, i);
}
}
}
}
七、调试过程中可能出现的问题归纳
1、L298N与开发板没有共地
2、PWM.c 中要注意选用的通道,并且初始化输出比较参数时候的函数:
TIM_OC2Init(TIM3, &TIM_OCInitStruct);
我这里选用的是TIM3_CH2通道
3、TIM3部分重映射函数:
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
4、使能预装载寄存器时候的函数:
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
我这里选用的是TIM3_CH2通道
5、main.c函数调节占空比的函数注意所选择的通道:
TIM_SetCompare2(TIM3, 499);
499是控制电机转动的参数值