欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F103定时器TIM3输出PWM控制电机

程序员文章站 2022-06-08 19:55:40
...

STM32F103ZET6定时器TIM3 CH2输出PWM控制电机

一、认识PWM是如何输出的

输出PWM之前首先查阅STM32中文参考手册,查看哪些定时器可以输出PWM波,该定时器可以映射到哪些引脚作为PWM波的输出。

对应查看的是通用和复用功能I/O里面的软件重新映射I/O复用功能

STM32F1的基本定时器以及功能介绍如下图所示:

STM32F103定时器TIM3输出PWM控制电机

二、查阅STM32中文参考手册复用和通用功能I/O—软件重映射篇

我选用的是TIM3作为PWM输出,所以找到TIM3定时器的复用功能重映像介绍,表格如下:
STM32F103定时器TIM3输出PWM控制电机
根据以上表格,再看自己的板子需要在哪个引脚输出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是控制电机转动的参数值