《SLAM机器人基础教程》第三章 单片机与STM32:PWM电机转动实验

3.11节 PWM电机转动实验

本节介绍使用STM32的TIM定时器输出PWM控制电机转动。

a.实验准备:码盘电机,USB转串口模块,ST-Llink下载器,CHEAPX机器人控制板

b.实验目的:STM32实现PWM输出

c.相关知识点:

PWM由STM32的定时器产生,通过设置计数频率实现PWM频率设置,设置最大计数值ARR和CCR调节PWM占空比

d.编程及运行

(1)初始化

void initMoter(void)
{
    //LFT MOTOR PE13 PE14
    //RGT MOTOR PE9  PE11
    GPIO_InitTypeDef GPIO_InitStruct;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;
    TIM_OCInitTypeDef  TIM_OCInitStruct;
    
    //Config Clock 配置时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOE, ENABLE);
    
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM1, ENABLE);    //映射管脚

    //配置GPIO
    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_9|GPIO_Pin_11;    
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽输出     
    GPIO_Init(GPIOE, &GPIO_InitStruct);         //传入结构体GPIO_InitStruct,配置GPIO
    
    GPIO_SetBits(GPIOE,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_9|GPIO_Pin_11); //管脚电平置高,保证电机处于停止状态         
    
    //TIM1 PE13 CH3,PE14 CH4
    //TIM1 PE9  CH1,PE11 CH2
    TIM_TimeBaseStruct.TIM_ClockDivision = 0;      //时钟分割,不分割,即为该定制器时钟最大值72M
    TIM_TimeBaseStruct.TIM_Prescaler = Motor_PSC-1;//预分频值,
    TIM_TimeBaseStruct.TIM_Period    = Motor_ARR-1;//最大计数值 
    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
    TIM_TimeBaseStruct.TIM_RepetitionCounter=0; //重复计数器
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStruct);//传入结构TIM_TimeBaseStruct,配置TIM1
    
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//TIM脉冲宽度调制模式2:CNT值小于比较器TIM_Period设定值时输出有效低电平,否者高电平
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;    //开启 OC正相输出到对应引脚
    TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; //关闭 OC反相输出到对应引脚
    TIM_OCInitStruct.TIM_Pulse = 0; //重置计数器的值,保证电机处于停止状态        
    TIM_OCInitStruct.TIM_OCPolarity   = TIM_OCPolarity_High; //输出极性:高电平
  TIM_OCInitStruct.TIM_OCIdleState  = TIM_OCIdleState_Set; //空闲状态下的TIM输出比较的引脚电平
    TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Set;//空闲状态下的TIM互补输出比较的引脚电平
  TIM_OC1Init(TIM1, &TIM_OCInitStruct);//传入结构TIM_OCInitStruct,配置TIM1 OC1通道
    TIM_OC2Init(TIM1, &TIM_OCInitStruct);//传入结构TIM_OCInitStruct,配置TIM1 OC2通道
    TIM_OC3Init(TIM1, &TIM_OCInitStruct);//传入结构TIM_OCInitStruct,配置TIM1 OC3通道
    
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//TIM脉冲宽度调制模式2:CNT值小于比较器TIM_Period设定值时输出有效低电平,否者高电平
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//开启 OC正相输出到对应引脚
    TIM_OCInitStruct.TIM_Pulse = 0;                           //重置计数器的值,保证电机处于停止状态        
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;    //输出极性:高电平
  TIM_OC4Init(TIM1, &TIM_OCInitStruct);                     //传入结构TIM_OCInitStruct,配置TIM1 OC4通道
    
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//开启OC1重装载,写入CCR1立即生效
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//开启OC2重装载,写入CCR2立即生效
    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);//开启OC3重装载,写入CCR3立即生效
    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);//开启OC4重装载,写入CCR4立即生效
    
    
  TIM_CtrlPWMOutputs(TIM1, ENABLE);  //使能PWM输出
    TIM_ARRPreloadConfig(TIM1, ENABLE);//开启自动装载
    TIM_Cmd(TIM1, ENABLE);             //开启TIM1

//  TIM1->CCR3=10000;TIM1->CCR4=10000;
//    TIM1->CCR1=10000;TIM1->CCR2=10000;
    
}

(2)更新函数

//参数:左电机速度,左电机方向,右电机速度,右电机方向
//速度值范围[4000,30000],值过小电机可能会不转
//方向:参照小车朝向,0往后转,1向前转
void moterControl(u16 lv,u8 ldir, u16 rv,u8 rdir)
{

    //限最大值,防止小车过快
    if(lv>30000)lv=30000;
    if(rv>30000)rv=30000;
    
    //驱动器通过两路PWM控制,分别连接IN1、IN2。IN1低电平,IN2高电平时正传;IN1高电平,IN2低电平时反传。高电平的占空比决定电机转速。
    if(ldir>0)
    {
      TIM1->CCR4=0;TIM1->CCR3=lv;//电机反转,参照小车朝向是向前转
    }
    else
  {
      TIM1->CCR3=0;TIM1->CCR4=lv;//电机正转,参照小车朝向是向后转
    }


    if(rdir>0)
    {
      TIM1->CCR1=0;TIM1->CCR2=rv;//电机正转,参照小车朝向是向前转
    }
    else
    {
      TIM1->CCR2=0;TIM1->CCR1=rv;//电机反转,参照小车朝向是向后转
    }

}

(3)主函数

扫描二维码关注公众号,回复: 11440353 查看本文章
//PWM电机转动实验
int main(void)
{
    
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //PriorityGroupConfig NVIC中断分组设置 组2(2位抢占优先级,2位响应优先级)
    initDebugSerial(500000);//初始化调试串口USART1,波特率500000
    initSysTick();//初始化滴答定时器和TIM4定时器
    showVersion();//显示版本
    
    initMoter();  //初始化电机
    
    //参数:左电机速度,左电机方向,右电机速度,右电机方向
    //速度值范围[4000,30000],值过小电机可能会不转
    //方向:参照小车朝向,0往后转,1向前转
    moterControl(10000,1,10000,1); 
    delay_ms(300);
//moterControl(0,1,0,1);//停止
    
}

(4)实验结果:电机转动0.3秒后停止

猜你喜欢

转载自www.cnblogs.com/Baron-Lu/p/13378760.html