[分享]三相直流无刷电机驱动

2019-07-14 21:53发布

1.检测霍尔传感器的值可以判断出转子的位置,再使能相应的上下桥臂,则能驱动电机运动;若要让电机持续转动,则必须再次检测传感器值及使能相应的上下桥臂。这里采用的是将霍尔传感器输出的三根线相边的IO口配置成外部中断,并且为边沿触发,在中断函数中加入传感器检测与上下桥臂切换程序,如此电机就能持续运转了。
2.上桥臂的控制采用IO口置高低电平来控制上桥臂的通断,下桥臂则使用单片机内部集成的三路PWM波来控制,通过控制PWM波的占空比,可以实现对电机的调速了。实际测得,占空比与电机的速度成正比例关系,在PWM波频率为20KHz时,占空比增加1%,速度增加60rpm,并在占空比为53%时达到额定转速3000rpm(空载)。
3.速度测量则采用如下公式:
电机每转一圈,霍尔值改变6次x5个周期=30次,记录边沿触发的中断次数N/30=电机转 过的圈数,设运转时间为t(s)则电机转速v=N/30/t*60 rpm。即动转时间为2s时,霍尔值改变次数即为速度值,单位rpm。
4.调速:给定速度,由电机驱动板自动由当前速度平滑过渡到给定速度。实际测试发现,速度变化量很大时,电机会有突然加速或减速时的冲击;因此,调速应有一个缓冲的过程。即加速或减速应以小步进缓慢增加或减少占空比来让速度渐渐达到最终值。


#include "STM32f10x.h"
#include "driver_motor.h"


#define PWM_PERIOD_T 400




#define U_Up_On GPIOB->BSRR = GPIO_Pin_13
#define U_Up_Off GPIOB->BRR = GPIO_Pin_13
#define U_Dn_On GPIOA->BSRR = GPIO_Pin_8
#define U_Dn_Off GPIOA->BRR = GPIO_Pin_8


#define V_Up_On GPIOB->BSRR = GPIO_Pin_14
#define V_Up_Off GPIOB->BRR = GPIO_Pin_14
#define V_Dn_On GPIOA->BSRR = GPIO_Pin_9
#define V_Dn_Off GPIOA->BRR = GPIO_Pin_9


#define W_Up_On GPIOB->BSRR = GPIO_Pin_15
#define W_Up_Off GPIOB->BRR = GPIO_Pin_15
#define W_Dn_On GPIOA->BSRR = GPIO_Pin_10
#define W_Dn_Off GPIOA->BRR = GPIO_Pin_10


#define SU_HOR GPIOA->IDR & GPIO_Pin_15
#define SV_HOR GPIOA->IDR & GPIO_Pin_12
#define SW_HOR GPIOA->IDR & GPIO_Pin_11




//u8 Motor_Dir=0;


//u8 Motor_EN=0;


//u8 Hor_Value=7;
//u16 tiM2_Conter=0;
u16 Hall_Conter=0;




MotorStruct Motor={CLOCK,40,STOP};


/*******************************************************************************
* 函数:void IO_Init(void)
* 描述:IO
* 参数:
* 返回:
* 其它:
*******************************************************************************/
void IO_Init(void)
{


    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStructure;
    //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /*使能SWD 禁用JTAG*/


    /**********************LED Light***********/
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;


    GPIO_Init(GPIOB, &GPIO_InitStruct);


    /***********************霍尔传感器中断**********/
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;


    GPIO_Init(GPIOA, &GPIO_InitStruct);//Harl


    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource11);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource12);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource15);
   
    EXTI_InitStructure.EXTI_Line = EXTI_Line11 | EXTI_Line12|EXTI_Line15;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}
/***************************************************************************
函数:void PWM_Init(void)
描述:配置PWM定时器TIM1
参数:
返回:无
***************************************************************************/
void PWM_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  TIM_OCInitTypeDef TIM_OCInitStructure;
  //TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
  TIM_Cmd(TIM1 , DISABLE);
  TIM_CtrlPWMOutputs(TIM1, DISABLE);//禁止OC输出
  
    //IO口设置
    GPIO_SetBits(GPIOA, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);  //PWM口
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  
    GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);//普通IO口
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   
    //定时器设置
    TIM_TimeBaseInitStruct.TIM_Period = PWM_PERIOD_T;//5极电机,3000RPM,每个Step有10个脉冲,载波15KHZ
    TIM_TimeBaseInitStruct.TIM_Prescaler = 2;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1 , &TIM_TimeBaseInitStruct);
    //TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
    //TIM_ARRPreloadConfig(TIM1, ENABLE);
    //TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
    //配置PWM输出
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    TIM_OCInitStructure.TIM_Pulse = 1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;   
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;  
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);


  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);


  TIM_ARRPreloadConfig(TIM1, ENABLE);                        //使能TIMx在ARR上的预装载寄存器  TIM_Cmd(TIM1 , ENABLE);


  TIM_Cmd(TIM1 , ENABLE);
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
/*****************************************************************************************
函数:void Motor_Init(void)
描述:
参数:
返回:
*****************************************************************************************/
void Motor_Init(void)
{
    IO_Init();
    PWM_Init();
}
/*****************************************************************************************
函数:void Flash_Led(u8 n)
描述:
参数:
返回:
*****************************************************************************************/
void Flash_Led(u8 n)
{
    u8 i=0;
    for(i=0;i<n;i++)
    {
        Led_On;
        DelayMs(100*n);
        Led_Off;
        DelayMs(100*n);
    }
}
/*****************************************************************************************
函数:void SetPWMduty(u8 PWMChanel,u16 pulse)
描述:设置pwm波占空比
参数:
返回:
*****************************************************************************************/
void SetPWMduty(u8 PWMChanel,u16 pulse)
{
    switch(PWMChanel)
    {
        case 1 :
                TIM1->CCR1=pulse;
            break;
        case 2 :
                TIM1->CCR2=pulse;
            break;
        case 3 :
                TIM1->CCR3=pulse;
            break;
        default :
            break;
    }

}
/*******************************************************************************
函数:PWM_T_Output
描述:设置相应的PWM梯形波输出
参数:pName上桥臂名称,nName下桥臂名称
返回:无
void PWM_T_Output(u8 pName , u8 nName , u8 mRate)
{
  switch(pName)
  {
    case 1:
      GPIO_SetBits(GPIOB, GPIO_Pin_15 | GPIO_Pin_14 );
      GPIO_ResetBits(GPIOB , GPIO_Pin_13);
      break;
    case 2:
      GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15 );
      GPIO_ResetBits(GPIOB , GPIO_Pin_14);
      break;
    case 3:
      GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 );
      GPIO_ResetBits(GPIOB , GPIO_Pin_15);
      break;
    default:
      GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
  }
  switch(nName)
  {
    case 1:
      
      TIM_SetCompare2(TIM1,0);
      TIM_SetCompare3(TIM1,0);
      TIM_SetCompare1(TIM1,(u16)(PWM_PERIOD_T * mRate / 100));
      break;
    case 2:
      
      TIM_SetCompare3(TIM1,0);
      TIM_SetCompare1(TIM1,0);
      TIM_SetCompare2(TIM1,(u16)(PWM_PERIOD_T * mRate / 100));
      break;
    case 3:
      
      TIM_SetCompare2(TIM1,0);
      TIM_SetCompare1(TIM1,0);
      TIM_SetCompare3(TIM1,(u16)(PWM_PERIOD_T * mRate / 100));
      break;
    default:
      TIM_SetCompare1(TIM1,0);
      TIM_SetCompare2(TIM1,0);
      TIM_SetCompare3(TIM1,0);
  }

  TIM_SetAutoreload(TIM1, PWM_PERIOD_T);
}
函数:PWM_T_Calculation
描述:梯形波计算
参数:HallValue霍尔值,mRate调制百分比,direction方向
返回:无
void PWM_T_Calculation(u8 hallValue , u8 mRate , u8 direction)
{
if(direction == 1)
{
  switch(hallValue)
  {
  case 5:
    PWM_T_Output(1 , 3 , mRate);
    break;
  case 1:
    PWM_T_Output(1 , 2 , mRate);
    break;
  case 3:
    PWM_T_Output(3 , 2 , mRate);
    break;
  case 2:
    PWM_T_Output(3 , 1 , mRate);
    break;
  case 6:
    PWM_T_Output(2 , 1 , mRate);
    break;
  case 4:
    PWM_T_Output(2 , 3 , mRate);
    break;
  default:
    PWM_T_Output(4 , 4 , 0);
    break;
  }
}
else
{
  switch(hallValue)
  {
  case 5:
    PWM_T_Output(3 , 1 , mRate);
    break;
  case 1:
    PWM_T_Output(2 , 1 , mRate);
    break;
  case 3:
    PWM_T_Output(2 , 3 , mRate);
    break;
  case 2:
    PWM_T_Output(1 , 3 , mRate);
    break;
  case 6:
    PWM_T_Output(1 , 2 , mRate);
    break;
  case 4:
    PWM_T_Output(3 , 2 , mRate);
    break;
  default:
    PWM_T_Output(4 , 4 , 0);
    break;
  }
}
}


函数:PWM_T_Int
描述:定时器中断程序,根据霍尔位置设置输出梯形波
参数:direction=顺时针/逆时针,mRate调制率
返回:无
void PWM_T_Int(u8 direction , u8 mRate)
{
  u8 hallValueTemp;
  u8 hallValue;
  hallValueTemp = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) << 1) + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) << 2);
  hallValue = hallValueTemp;
  PWM_T_Calculation(hallValue , mRate , direction);
}



函数:PWM_Stop
描述:PWM控制信号使能输出,禁止TIM1中断,使能TIM1中断
参数:pwmflag=DISABLE,PWM信号使能输出,pwmflag=ENABLE,禁止 PWM输出
返回:无
void PWM_Stop(u8 pwmflag)
{
   NVIC_InitTypeDef NVIC_InitStructure;
   GPIO_InitTypeDef GPIO_InitStructure;
   if(pwmflag == ENABLE)//禁止 PWM输出
   {
     TIM_Cmd(TIM1 , DISABLE);
    //TIM_Cmd(TIM2 , DISABLE);
     NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
     NVIC_Init(&NVIC_InitStructure);
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);  //PWM口
   
     //PWM_T_Output(4 , 4 , 0);
   }
if(pwmflag == DISABLE)//使能PWM输出
   {
     NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
     
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
   
     
    // TIM_Cmd(TIM2 , ENABLE);
   }
}
函数:void Motor_Start(void)
描述:启动电机
参数:
返回:
*****************************************************************************************/
void Motor_Start(void)
{   
    PWM_T_Int(Motor.Dir,Motor.Speed);
}
函数:void Motor_Stop(void)
描述:停止
参数:
返回:void Motor_Stop(void)
{
     //U_Up_On;V_Up_On;W_Up_On;
     //U_Dn_On;V_Dn_On;W_Dn_On;
     PWM_T_Output(4,4,0);
}


/*****************************************************
函数:void EXTI15_10_IRQHandler(u8 dir,u8 hall)
描述:霍尔传感器中断
参数:
返回:******************************************************************/
void EXTI15_10_IRQHandler(void)
{
    Hall_Conter++;
    if ((EXTI_GetITStatus(EXTI_Line11) != RESET)||(EXTI_GetITStatus(EXTI_Line12) != RESET)||(EXTI_GetITStatus(EXTI_Line15) != RESET))
    {
        
        if(Motor.State!=STOP)
        PWM_T_Int(Motor.Dir,Motor.Speed);
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
9条回答
卜诺耶
1楼-- · 2019-07-15 06:24
好东西,占一个
云梦飘飘
2楼-- · 2019-07-15 09:23
 精彩回答 2  元偷偷看……
vc9181
3楼-- · 2019-07-15 09:55
不错的东西,谢谢楼主分享
rzh188
4楼-- · 2019-07-15 13:46
十分感谢分享,谢谢啦
yangzhixiong11
5楼-- · 2019-07-15 16:48
一篇不错的文章,谢谢分享
乔治艾伦
6楼-- · 2019-07-15 22:29
Mark一下~....................

一周热门 更多>