这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 用STM32的PWM实现小电机的正反转(带源码)

共5条 1/1 1 跳转至

用STM32的PWM实现小电机的正反转(带源码)

工程师
2020-09-01 20:51:57     打赏
大概思路就是:用TIM1和TIM4两个时钟共8个通道,用PWM来控制小车的4个轮子。

TIM1中的PA8 A9代表左前轮, A10 A11代表左后轮;
TIM4中的PB6 B7代表右前轮,B8 B9代表右后轮

下面附上完整代码:

timer.h

    #ifndef __TIMER_H
    #define __TIMER_H
    #include "sys.h"
    void TIM4_PWM_Init();
    void TIM1_PWM_Init();
    void Prun();   //前进
    void Nrun();   //后退
    void Tleft();  //左转
    void Trighet();//右转
    #endif


timer.c

    #include "timer.h"
    #include "led.h"
    //TIM4 PWM部分初始化
    //PWM输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    void TIM4_PWM_Init()
    {  
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
       //初始化TIM4
    TIM_TimeBaseStructure.TIM_Period = 99; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =719; //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    //初始化TIM4 Channel/2/3/4 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(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC1
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC2
    TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC3
    TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC4
      TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR1上的预装载寄存器
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
    TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR3上的预装载寄存器
    TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR4上的预装载寄存器
    TIM_ARRPreloadConfig(TIM4,ENABLE);
    TIM_Cmd(TIM4, ENABLE);  //使能TIM4
    }
    void TIM1_PWM_Init()
    {  
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器1时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIO外设
       //设置该引脚为复用输出功能,输出TIM1 PWM脉冲波形
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11; //TIM_CHX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
       //初始化TIM1
    TIM_TimeBaseStructure.TIM_Period = 99; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =719; //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    //初始化TIM4 Channel/2/3/4 PWM模式  
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    TIM_OCInitStructure.TIM_OutputNState=TIM_OutputState_Disable;//高级定时器有一个输出N不使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCPolarity_High;//
    TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset;//这三个是高级定时器要配置的
    TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCIdleState_Reset;//
    //TIM_OCInitStructure.TIM_Pulse=10;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 OC1
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 OC2
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 OC3
    TIM_OC4Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 OC4
      TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR2上的预装载寄存器
    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR3上的预装载寄存器
    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR4上的预装载寄存器
    TIM_ARRPreloadConfig(TIM1,ENABLE);//使能自动重装载值
    TIM_CtrlPWMOutputs(TIM1,ENABLE);//主输出使能
    TIM_Cmd(TIM1, ENABLE);  //使能TIM1
    }
    //TIM1中的PA8 A9代表左前轮, A10 A11代表左后轮; TIM4中的PB6 B7代表右前轮,B8 B9代表右后轮
    void Prun()
    {
      TIM_SetCompare1(TIM1,10); //左前前进
    TIM_SetCompare2(TIM1,0);
    TIM_SetCompare3(TIM1,10); //左后前进
    TIM_SetCompare4(TIM1,0);
    TIM_SetCompare1(TIM4,10); //右前前进
    TIM_SetCompare2(TIM4,0);
    TIM_SetCompare3(TIM4,10); //右后前进
    TIM_SetCompare4(TIM4,0);
    }
    void Nrun()
    {
    TIM_SetCompare1(TIM1,0); //左前后退
    TIM_SetCompare2(TIM1,10);
    TIM_SetCompare3(TIM1,0); //左后后退
    TIM_SetCompare4(TIM1,10);  
    TIM_SetCompare1(TIM4,0); //右前后退
    TIM_SetCompare2(TIM4,10);
    TIM_SetCompare3(TIM4,0); //右后后退
    TIM_SetCompare4(TIM4,10);
    }
    void Tleft()  //  原地左转  左边的两个轮子往后转,右边的两个轮子往前转
    {
      TIM_SetCompare1(TIM1,0); //左前后退
    TIM_SetCompare2(TIM1,10);
    TIM_SetCompare3(TIM1,0); //左后后退
    TIM_SetCompare4(TIM1,10);
    TIM_SetCompare1(TIM4,10); //右前前进
    TIM_SetCompare2(TIM4,0);
    TIM_SetCompare3(TIM4,10); //右后前进
    TIM_SetCompare4(TIM4,0);
    }
    void Trighet()
    {
      TIM_SetCompare1(TIM1,10); //左前前进
    TIM_SetCompare2(TIM1,0);
    TIM_SetCompare3(TIM1,10); //左后前进
    TIM_SetCompare4(TIM1,0);
    TIM_SetCompare1(TIM4,0); //右前后退
    TIM_SetCompare2(TIM4,10);
    TIM_SetCompare3(TIM4,0); //右后后退
    TIM_SetCompare4(TIM4,10);
    }

进行一些简单说明

上面的重装载值arr=99,预分频系数psc=719;

T=arr * psc /72M,结果为1ms,也就是频率为1KHz;

PWM模式设置为TIM_OCMode_PWM1,arr=99,

这样一来占空比调整比较方便:

arr=10——占空比为10%;

arr=20——占空比为20%;

上面的占空比我设置的是10%,电机转的比较慢(还可以),你可以根据你自己的情况进行自己更改。


main.c


#include "delay.h"
#include "sys.h"
#include "timer.h"

int main(void)
{   
    delay_init();       //延时函数初始化   
   TIM4_PWM_Init();
   TIM1_PWM_Init();
    while(1)
{
  Prun();//前进
}  
}

实际调试的波形图:




希望对大家有帮助。






关键词: STM32     电机     PWM    

工程师
2020-09-01 21:09:15     打赏
2楼
非常不错 哦!



工程师
2020-09-01 21:13:38     打赏
3楼
请问sys.h和system.h是一样的吗?



工程师
2020-09-01 21:17:54     打赏
4楼

不用电平而是PWM的控制方式,挺新颖~


工程师
2020-09-01 21:17:59     打赏
5楼

确实不错


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]