• 【GD32F427开发板试用】BLDC方波驱动测试


    本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:szit

    0 引

    GD32F427V-START开发板采用主控芯片GD32F427VKT6,MCU基于 Arm® Cortex®-M4内核,系统时钟的最大运行时钟频率可以达到240MHz。本次测试利用STM32CubeMX(STM32F427VITx)生成工程代码,完成无刷电机驱动程序输出。GD外设编号从0开始,如TIM0等效STM32的TIM1。本测试目前没有用实际电机测试,用模拟hall时序输出到hall输入引脚的办法,触发换相。外设使用情况如下:

    1. TIM1-CH1/CH1N/CH2/CH2N/CH3/CH3N,三相互补PWM输出;
    2. TIM1-BKN PA6 刹车输入;
    3. TIM3-HALL CH1/CH2/CH3–PB4/PC7/PC8,三相霍尔捕获;
    4. GPIO输出模拟霍尔数字信号输出到TIM3-HALL PC0 /PC1 /PC2
    5. LED-PC6
    6. KEY-PA0

    注:本实例需要对有感BLDC驱动硬件与驱动方法有一定理解,比如三相H桥、3相霍尔(120°)、正反转时序等。

    1 STM32CubeMX配置

    1. 芯片选择STM32F427VITx(其他未测)
    2. SWD配置
    3. RCC时钟:外置HSE- 25MHZ 外置RTC- 32.768KHz
    4. 时钟配置为180MHz
    5. PC0、PC1、PC2、PC6配置为GPIO_Output,高速
    6. PA0配置为GPIO_Input,上拉
    7. TIM1配置前3个通道三路互补20kHz PWM输出,Prescaler=0,Counter Period = 8899;Activate-Break-Input刹车,BRK State使能 极性为low;PWM模式默认mode1,极性均为High,Idle State为Reset,PA6配置为上拉(低电平刹车,高电平工作);
    8. TIM3配置为XOR ON/Hall Sensor Mode,Prescaler=89,Counter Period = 65535;计数脉冲周期为1us,当产生霍尔捕获中断时获取当前时间即可,一次时间不要超过65535*1us即可,否则会溢出后再计数。

    2 程序设计

    1.启动Keil,芯片选择GD32F427VK,Debug选择CMSIS-DAP Debugger。
    2.启动SYSTICK时钟
    配置1ms中断SYSTICK时钟。
    `void SysTick_Handler(void)
    {
    /USER CODE BEGIN SysTick_IRQn 0/

    HAL_SYSTICK_IRQHandler();
    
    • 1

    /USER CODE END SysTick_IRQn 0/
    HAL_IncTick();
    /USER CODE BEGIN SysTick_IRQn 1/

    /USER CODE END SysTick_IRQn 1/
    }`
    3.在SYSTICK回调函数中输出HALL模拟时序
    电机正传与反转时,霍尔都有相应的时序被检测到,这里用模拟的方法输出三相霍尔信号PC0/PC1/PC2到霍尔传感器输入引脚(杜邦线)PB4/PC7/PC8.

    #define CNT_PSC          100  
    uint32_t CounterPSC = CNT_PSC;   
    int8_t hal_step_simulate=-1;
    uint8_t array_cw[6] = {2,3,1,5,4,6};
    uint8_t array_ccw[6] = {5,1,3,2,6,4};
    void HAL_SYSTICK_Callback()
    {
      CounterPSC--;
      if(!CounterPSC) 
      {        
            hal_step_simulate++;
            if(hal_step_simulate==6)hal_step_simulate=0;    
            if(Motor_Dir == MOTOR_DIR_CW)
            {
                if((array_cw[hal_step_simulate]&0x01)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
                
                if((array_cw[hal_step_simulate]&0x02)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
                
                if((array_cw[hal_step_simulate]&0x04)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
            }
            else if(Motor_Dir == MOTOR_DIR_CCW)
            {
                if((array_ccw[hal_step_simulate]&0x01)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
                
                if((array_ccw[hal_step_simulate]&0x02)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
                
                if((array_ccw[hal_step_simulate]&0x04)!=0)
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
                else
                    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);    
            }
        CounterPSC = CNT_PSC; 
       // BLDCMotor_PhaseCtrl(&uwStep);// ¿ØÖÆ6²½PWM»»Ïà
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    4.换相
    根据三相霍尔状态切换3相6路PWM输出。

    #define MOTOR_DIR_CCW 1
    #define MOTOR_DIR_CW 2
    uint8_t Motor_Dir = 1;
    void BLDCMotor_PhaseCtrl(int32_t HALLPhase)
    {
      if(MOTOR_DIR_CCW == Motor_Dir)
        HALLPhase = 0x07 ^ HALLPhase;// ½«µÍÈýλÒì»ò 111b ^ 010b -> 101b
    
      switch(HALLPhase)
      {
        case 5: //B+  A-
        {
          /*  Channe3 configuration */ 
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
        
          /*  Channe2 configuration  */
          __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);  
          
          /*  Channe1 configuration */
          __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD +1);
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
        }
        break;
        
        case 4:// C+ A-
        {
          /*  Channe2 configuration */ 
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
     
          /*  Channe3 configuration  */
          __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);  
          
          /*  Channe1 configuration  */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD +1);
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
        }
          break;
        
        case 6://C+ B-
        {
          /*  Channe1 configuration  */ 
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
        
          /*  Channe3 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);  
    
          /*  Channe2 configuration  */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD +1);
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
        }
          break;
    
        case 2: // A+ B-
        {
          /*  Channe3 configuration */       
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
        
          /*  Channe1 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);  
          
          /*  Channe2 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD +1);
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
        }
          break;
        
        
        case 3:// A+ C-
        {
          /*  Channe2 configuration */ 
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
    
          /*  Channe1 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);  
          
          /*  Channe3 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD +1);    
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
        }
          break;
        case 1: // B+ C-
        {
          /*  Channe1 configuration */ 
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
        
          /*  Channe2 configuration */
          __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2, BLDCMOTOR_TIM_PERIOD * PWM_Duty);
          HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);  
          
          /*  Channe3 configuration */
          __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, BLDCMOTOR_TIM_PERIOD +1);
          HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
        }
        break;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    5.霍尔捕获
    霍尔捕获后,获取当前霍尔值,而后根据霍尔值切换H桥PWM输出,每次捕获可以记录2次捕获之间的时间,可以用于计算转速。

    uint8_t hal_state = 0;
    uint16_t hal_counter=0;
    uint16_t  RT_hallcomp=0;//hall period cnt
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
        //PB4 PC7 PC8 TIM3
        if(TIM3== htim->Instance){
            
            hal_counter++;//test 
            hal_state = 0;
            hal_state |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4);//U(A)
            hal_state <<= 1;
            hal_state |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7);//V(B)
            hal_state <<= 1;
            hal_state |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8);//W(C)        
            RT_hallcomp = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1); // for speed
            
            BLDCMotor_PhaseCtrl(hal_state);// update phase
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6.其他
    在main函数中启动hall定时器
    HAL_TIMEx_HallSensor_Start_IT(&htim3);

    3 波形测试

    刹车低电平刹车,高电平可以正常输出,逻辑分析仪测量6路PWM输出,

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TKZ0xFBO-1670223689484)(https://pic1.zhimg.com/80/v2-0819d5e94f87c4b14a13635aa75290fc_1440w.webp)]

    4 后续

    先发布后修改。在使用过程中,好像TIM2的hall有一路不行,一直跳变,后改用TIM3,GPIO输出有一路需要设置为高速,原因未深究,后发现可能硬件冲突,部分使用的口连接到USB了。

  • 相关阅读:
    c++面试题汇总(不定期更新...)
    这些数据泄露方式,80%的企业不易发现
    【PAT甲级 - C++题解】1145 Hashing - Average Search Time
    求所有质因子(Java)
    什么是 SYN 洪水攻击?如何防护?
    HTML案例-1.标签练习
    vue3使用QuillEditor
    SpringBoot中Tomcat和SpringMVC整合源码分析
    拓扑几何学
    【利用AI让知识体系化】拍了拍AST
  • 原文地址:https://blog.csdn.net/weixin_47569031/article/details/128186998