本帖最后由 1nnocet- 于 2019-7-23 14:50 编辑
《PWM控制直流电机加减速正反转》
由于近期比较忙这里做简单介绍:该篇使用TIM3的通道3和通道4来输出两路PWM。可以通过触摸按键控制占空比。
下面为系统的主要框图:
整个系统由以上几部分组成,以ufun为主控模块,控制电机驱动电路;通过触摸键盘设置输出PWM波的占空比,控制电机转动的快慢;设置两个GPIO口决定是否输出PWM波;控制电机转动的方向。
接下来简单介绍下程序:定时器和按键初始化这里不再赘述,前面的学习篇有讲解。程序要注意的地方是不能让两个通道同时输出PWM,一路控制正转,另一路控制反转。文末有部分代码,如果想练手又实在写不出来的,需要源文件可以私信分享
运行效果:
1.示波器测量占空比:占空比在1%-100%可调
2.电机驱动效果
3.另外方便测试还做了接口的拓展板,电机驱动模块是以前在淘宝买的,驱动模块是H桥电机驱动拓扑
接口拓展板主要拓展地的接口
电机驱动板
此内容由EEWORLD论坛网友1nnocet-原创,如需转载或用于商业用途需征得作者同意并注明出处
#include "stm32f10x.h"
#include "stdio.h"
#include "main.h"
#include "LED.h"
#include "PWM.h"
#include "DELAY.h"
#include "TOUCH_KEY.h"
#include "stdlib.h"
#define Arr 500
#define Psc 5
extern int channel;
int main()
{
int key_value,Duty_num=Arr/2; //占空比默认50%
int mode=0;
PwmGPIO_Init();
TIM3_PWM2_Init(Arr,Psc); //pwm初始化
TIM3_PWM1_Init(Arr,Psc);
TK_GPIO_Init(); //触摸按键初始化
//初始化捕获比较值输出PWM
TIM_SetCompare2(TIM3,Duty_num);
TIM_SetCompare1(TIM3,Duty_num);
while (1)
{
key_value=Key_Scan(mode); //获取键值
if(key_value==1) //检测到touch0被按下 进行加速操作
{
if(channel==1) //判断通道
{
Duty_num+=Psc;
if(Duty_num>=Arr)
{
Duty_num=Psc;
}
TIM_SetCompare1(TIM3,Duty_num); //通过改变占空比改变速度
}
if(channel==2)
{
Duty_num+=Psc;
if(Duty_num>=Arr)
{
Duty_num=Psc;
}
TIM_SetCompare2(TIM3,Duty_num); //通过改变占空比改变速度
}
}
if(key_value==2) //检测到touch1被按下 进行减速操作
{
if(channel==1)
{
Duty_num-=Psc;
if(Duty_num<=Psc)
{
Duty_num=Arr;
}
TIM_SetCompare1(TIM3,Duty_num); //通过改变占空比改变速度
}
if(channel==2)
{
Duty_num-=Psc; //亮度上升
if(Duty_num<=Psc)
{
Duty_num=Arr;
}
TIM_SetCompare2(TIM3,Duty_num); //通过改变占空比改变速度
}
}
if(key_value==4) //检测到touch3被按下 切换通道(正反转切换)
{
if(channel==1)
{
TIM3_PWM2_Init(Arr,Psc);
TIM_SetCompare2(TIM3,Duty_num);
}
else if(channel==2)
{
TIM3_PWM1_Init(Arr,Psc);
TIM_SetCompare1(TIM3,Duty_num);
}
}
if(key_value==3) //检测到touch2被按下
{
if(mode==0) //按键模式切换,mode=0为关闭连续按键,mode=1位开启连续按键
{
mode=1;
while(TOUCH2);
}
else
mode=0;
}
}
}
void TIM3_PWM1_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器2时钟
//初始化TIM
TIM_TimeBaseStructure.TIM_Period = arr-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc-1; //设置用来作为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的时间基数单位
//初始化TIM Channe PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
// TIM_OC1Init(TIM3, &TIM_OCInitStructure); //初始化外设TIM2 OC1
// TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM2在CCR1上的预装载寄存器
//
// TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化外设TIM2 OC2
// TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //初始化外设TIM2 OC3
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM2在CCR3上的预装载寄存器
//初始化TIM Channe PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //初始化外设TIM2 OC4
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM2在CCR3上的预装载寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIM2
TIM_ARRPreloadConfig(TIM3, ENABLE);//使能或者失能 TIM2 在 ARR 上的预装载寄存器
TIM_CtrlPWMOutputs(TIM3, ENABLE);//
channel=1;
}