STM32 IR2110驱动BLDC无刷直流电机-软硬件介绍

[复制链接]
1895|2
 楼主| 感动 发表于 2019-9-14 20:09 | 显示全部楼层 |阅读模式
本帖最后由 感动 于 2019-9-14 20:21 编辑

无刷直流电机比较流行,很多电机内部加入霍尔元件,通过霍尔元件可以知道电机转子的位置,根据这个位置给电机相线供电,这样电机就转起来了。框图如下所示
霍尔元件输出与相线输入电压的关系可以让BLDC电机厂家提供,一般都提供这个对应关系表,如下图所示
有了上面这些足可以让我们设计电路编写程序让电机转起来!

有上面的框图可以看出,3相电机的驱动需要六个mos管,一般用的是NMOS,大功率的NMOS比较便宜。大功率MOS管有较大的结电容,控制电压也高些,无法用单片机直接驱动,所以需要驱动电路。驱动芯片组成的驱动电路比较简单,常见的有IR2110S,我这里用IR2110S设计了MOS驱动电路,如下图所示,其中C24D5是自举电路,为了控制Q3抬高电压。
3IR2110S驱动6NMOS,如下图
霍尔元件供电是5V,他的输出一般也是5V,可以分压后给单片机用。

单片机用流行STM32,他有高级定时器T1T8,可以输出3对互补的PWM波,还有刹车信号输入,这些特性对于电机的可控制非常合适。电路如下图所示

BLDC电机控制用到单片机定时器及IO中断,初始化部分如下

  1. {
  2.   GPIO_InitTypeDef GPIO_InitStructure;
  3.         TIM_TimeBaseInitTypeDef        TIM_TimeBaseInitStruct;
  4.         TIM_OCInitTypeDef  TIM_OCInitStructure;
  5.         TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
  6.         EXTI_InitTypeDef EXTI_InitStructure;//
  7.         NVIC_InitTypeDef NVIC_InitStructure;
  8.         TIM_ICInitTypeDef TIM_ICInitStructure;
  9.         // ¿ªÆô¶¨Ê±Æ÷ʱÖÓ,¼´ÄÚ²¿Ê±ÖÓCK_INT=72M
  10.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_TIM1, ENABLE);
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  12.         
  13.    // Êä³ö±È½ÏͨµÀ1 GPIO ³õʼ»¯
  14.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  18.         
  19.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  21.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  23.         //»ô¶ûÊäÈë
  24.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 ;
  25.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  26.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  27.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 ;
  28.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  29.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  30.         
  31.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
  32.         
  33.         EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  34.         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  35.         EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  36.         EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  37.         EXTI_Init(&EXTI_InitStructure);
  38.         
  39.         NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  40.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;  
  41.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
  42.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  43.   NVIC_Init(&NVIC_InitStructure);
  44.         
  45.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource6);
  46.         
  47.         EXTI_InitStructure.EXTI_Line= EXTI_Line6;
  48.         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  49.         EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  50.         EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  51.         EXTI_Init(&EXTI_InitStructure);
  52.         
  53.         NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
  54.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;  
  55.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  56.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  57.   NVIC_Init(&NVIC_InitStructure);
  58.         
  59.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource7);
  60.         
  61.         EXTI_InitStructure.EXTI_Line= EXTI_Line7;
  62.         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  63.         EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  64.         EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  65.         EXTI_Init(&EXTI_InitStructure);
  66.         
  67.         NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
  68.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;  
  69.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
  70.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  71.   NVIC_Init(&NVIC_InitStructure);
  72.         
  73.         TIM_DeInit(TIM1);
  74.         TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;
  75.         TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;
  76.         TIM_TimeBaseInitStruct.TIM_Period = 1000 ;
  77.         TIM_TimeBaseInitStruct.TIM_Prescaler = 3 ;
  78.         TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
  79.         TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct ) ;      
  80.         

  81.   
  82.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  83.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  84.   TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  85.   TIM_OCInitStructure.TIM_Pulse = 1000;
  86.   
  87.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  88.   TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_High;
  89.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  90.   TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
  91.   
  92.   TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  93.   TIM_OC2Init(TIM1, &TIM_OCInitStructure);
  94.   TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  95.   /* Automatic Output enable, Break, dead time and lock configuration*/
  96.   TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  97.   TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
  98.   TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
  99.   TIM_BDTRInitStructure.TIM_DeadTime = 1;
  100.   TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
  101.   TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
  102.   TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  103.   TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
  104.   
  105.   TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
  106.   TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
  107.   TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);
  108.         
  109.   TIM_ARRPreloadConfig(TIM1, ENABLE);
  110.   TIM_Cmd(TIM1, ENABLE);
  111.   TIM_CtrlPWMOutputs(TIM1, ENABLE);
  112.   
  113.   TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Enable);
  114.   TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Enable);
  115.   TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Enable);
  116.   TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Enable);
  117.   TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Enable);
  118.   TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Enable);
让电机转起来需要知道电机转子的位置,根据霍尔相位对应表驱动电机相线,程序里用中断获取霍尔电平的变化。
  1. void EXTI0_IRQHandler(void)
  2. {
  3.         int i,j;
  4.         if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
  5.         {
  6.                 EXTI_ClearITPendingBit(EXTI_Line0);


  7.                 step=((GPIOA->IDR & GPIO_Pin_6)>>6)+((GPIOA->IDR & GPIO_Pin_7)>>6)+((GPIOB->IDR & GPIO_Pin_0)<<2);
  8.                 if(start==1)
  9.                 {
  10.                         TIM1->CCER=PHASE_CHANGE[step];
  11.                         int_count1++;
  12.                 }
  13.         }
  14. }

  15. void EXTI9_5_IRQHandler(void)
  16. {
  17.         int i,j;
  18.         if(EXTI_GetITStatus(EXTI_Line6)!=RESET)
  19.         {
  20.                 EXTI_ClearITPendingBit(EXTI_Line6);

  21.                 step=((GPIOA->IDR & GPIO_Pin_6)>>6)+((GPIOA->IDR & GPIO_Pin_7)>>6)+((GPIOB->IDR & GPIO_Pin_0)<<2);
  22.                 if(start==1)
  23.                 {
  24.                         TIM1->CCER=PHASE_CHANGE[step];
  25.                         int_count2++;
  26.                 }

  27.         }
  28.         if(EXTI_GetITStatus(EXTI_Line7)!=RESET)
  29.         {
  30.                 EXTI_ClearITPendingBit(EXTI_Line7);

  31.                 step=((GPIOA->IDR & GPIO_Pin_6)>>6)+((GPIOA->IDR & GPIO_Pin_7)>>6)+((GPIOB->IDR & GPIO_Pin_0)<<2);
  32.                 if(start==1)
  33.                 {
  34.                         TIM1->CCER=PHASE_CHANGE[step];
  35.                         int_count3++;
  36.                 }
  37.         }
  38. }
检测到变化后改变定时器输出,从而使电机相线得到驱动,我在程序里做好了数组,把得到了位置通过数组给定时器CCER寄存器,这样电机就转起来了

这是霍尔输出与PWM输出波形的截图
这是定时器3对PWM的输出截图

这是电机和电路板




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 感动 发表于 2019-9-20 16:51 | 显示全部楼层
很多资料无法上传
wenjunying 发表于 2019-10-16 09:07 | 显示全部楼层
我觉得写的很好啊,目前正在学习。谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:关注我的博客https://blog.csdn.net/gd1984812 淘宝店 https://shop570248211.taobao.

35

主题

57

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部