BLDC电机的dome列子

本文介绍了两种无刷直流电机(BLDC)的控制方法,均基于STM32微控制器。第一种方法使用霍尔传感器和高级定时器检测转子位置,通过定时器中断检测电机是否堵转。第二种方法利用三个外部中断检测霍尔传感器的电平变化,同样实现电机位置检测。这两种方法均涉及到霍尔传感器的中断处理和PWM输出配置,确保电机稳定运行。
摘要由CSDN通过智能技术生成

1.开环-霍尔传感器检测转子位置的方式

说明:一个高级定时器T1(产生六步PWM),定时器3通用定时器(霍尔传感器接口检测转子位置)开启霍尔传感器的触发中断,并且还使用了定时器的通道4并开启比较中断来检测电机是否堵转,中断函数的回调在main里面。按键来控制电机的启停(控制PWM是否输出)快慢(控制PWM的占空比)按键代码不列出。

高级定时器.h

#ifndef __ADVANCED_TIM_H__
#define __ADVANCED_TIM_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
#define ADVANCED_TIMx                        TIM1
#define ADVANCED_TIM_RCC_CLK_ENABLE()        __HAL_RCC_TIM1_CLK_ENABLE()
#define ADVANCED_TIM_RCC_CLK_DISABLE()       __HAL_RCC_TIM1_CLK_DISABLE()
#define ADVANCED_TIM_GPIO_RCC_CLK_ENABLE()   {__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();}

/* 高级定时器的六个互补通道 */
#define ADVANCED_TIM_CH1_PORT                GPIOA
#define ADVANCED_TIM_CH1_PIN                 GPIO_PIN_8
#define ADVANCED_TIM_CH2_PORT                GPIOA
#define ADVANCED_TIM_CH2_PIN                 GPIO_PIN_9
#define ADVANCED_TIM_CH3_PORT                GPIOA
#define ADVANCED_TIM_CH3_PIN                 GPIO_PIN_10

#define ADVANCED_TIM_CH1N_PORT               GPIOB
#define ADVANCED_TIM_CH1N_PIN                GPIO_PIN_13
#define ADVANCED_TIM_CH2N_PORT               GPIOB
#define ADVANCED_TIM_CH2N_PIN                GPIO_PIN_14
#define ADVANCED_TIM_CH3N_PORT               GPIOB
#define ADVANCED_TIM_CH3N_PIN                GPIO_PIN_15
/* 高级定时器的刹车通道 有效时高级定时器不会输出PWM */
#define ADVANCED_TIM_BKIN_PORT               GPIOB
#define ADVANCED_TIM_BKIN_PIN                GPIO_PIN_12

#define ADVANCED_TIM_PWM_FREQ                20000 // PWM频率 20khz

// 定义定时器预分频,定时器实际时钟频率为:72MHz/(ADVANCED_TIMx_PRESCALER+1)
#define ADVANCED_TIM_PRESCALER               0  // (不分频)实际时钟频率为:72MHz

// 定义定时器周期,当定时器开始计数到ADVANCED_TIMx_PERIOD值并且重复计数寄存器为0时更新定时器并生成对应事件和中断
/* ARR值根据固定的PWM频率给出 */
#define ADVANCED_TIM_PERIOD                  (SystemCoreClock/(ADVANCED_TIM_PRESCALER+1)/ADVANCED_TIM_PWM_FREQ)

// 定义高级定时器重复计数寄存器值,
#define ADVANCED_TIM_REPETITIONCOUNTER       0


/* 扩展变量 ------------------------------------------------------------------*/
extern TIM_HandleTypeDef      htimx_BLDC;
extern TIM_OC_InitTypeDef     sPWMConfig1, sPWMConfig2, sPWMConfig3;
/* 函数声明 ------------------------------------------------------------------*/

void ADVANCED_TIMx_Init(void);

#endif	/* __ADVANCED_TIM_H__ */

高级定时器.c

#include "AdvancedTIM/bsp_AdvancedTIM.h" 

/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
TIM_HandleTypeDef      htimx_BLDC;
/* Timer Output Compare Configuration Structure declaration */
TIM_OC_InitTypeDef     sPWMConfig1, sPWMConfig2, sPWMConfig3;

/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 定时器硬件初始化配置
  * 输入参数: htim:定时器句柄类型指针
  * 返 回 值: 无
  * 说    明: 该函数被ADVANCED_TIMx_Init函数调用
  */
void ADVANCED_TIM_MspPostInit(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 定时器通道功能引脚端口时钟使能 */
  ADVANCED_TIM_GPIO_RCC_CLK_ENABLE();
  
  /* 定时器通道1功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(ADVANCED_TIM_CH1_PORT, &GPIO_InitStruct);
  /* 定时器通道1互补通道功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH1N_PIN;
  HAL_GPIO_Init(ADVANCED_TIM_CH1N_PORT, &GPIO_InitStruct);

  /* 定时器通道2功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH2_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(ADVANCED_TIM_CH2_PORT, &GPIO_InitStruct);
  /* 定时器通道2互补通道功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH2N_PIN;
  HAL_GPIO_Init(ADVANCED_TIM_CH2N_PORT, &GPIO_InitStruct);
  
  /* 定时器通道3功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH3_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(ADVANCED_TIM_CH3_PORT, &GPIO_InitStruct);
  /* 定时器通道3互补通道功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_CH3N_PIN;
  HAL_GPIO_Init(ADVANCED_TIM_CH3N_PORT, &GPIO_InitStruct);
  
  /* 定时器制动功能引脚IO初始化 */
  GPIO_InitStruct.Pin = ADVANCED_TIM_BKIN_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(ADVANCED_TIM_BKIN_PORT, &GPIO_InitStruct);
}

/**
  * 函数功能: 基本定时器初始化
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void ADVANCED_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  /* 基本定时器外设时钟使能 */
  ADVANCED_TIM_RCC_CLK_ENABLE();
  ADVANCED_TIM_MspPostInit();
  
  htimx_BLDC.Instance = ADVANCED_TIMx;
  htimx_BLDC.Init.Prescaler = ADVANCED_TIM_PRESCALER;
  htimx_BLDC.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx_BLDC.Init.Period = ADVANCED_TIM_PERIOD;
  htimx_BLDC.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
  htimx_BLDC.Init.RepetitionCounter = ADVANCED_TIM_REPETITIONCOUNTER;
  HAL_TIM_PWM_Init(&htimx_BLDC);
  
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;/* 定时器选择内部时钟 */
  HAL_TIM_ConfigClockSource(&htimx_BLDC, &sClockSourceConfig); 
  
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 5;                 /* 死区时间 */
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; /* 高电平有效 */
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  HAL_TIMEx_ConfigBreakDeadTime(&htimx_BLDC, &sBreakDeadTimeConfig); /* 刹车初始化 */

  sPWMConfig1.OCMode = TIM_OCMODE_PWM1;                     // PWM1模式
  sPWMConfig1.Pulse = 0;
  sPWMConfig1.OCPolarity = TIM_OCPOLARITY_HIGH;
  sPWMConfig1.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sPWMConfig1.OCFastMode = TIM_OCFAST_DISABLE;
  sPWMConfig1.OCIdleState = TIM_OCIDLESTATE_SET;
  sPWMConfig1.OCNIdleState = TIM_OCNIDLESTATE_SET;
  HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1); // 指定的初始化TIM PWM通道1

  sPWMConfig2 = sPWMConfig1;
  HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); // 指定的初始化TIM PWM通道2

  sPWMConfig3 = sPWMConfig1;
  HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3); // 指定的初始化TIM PWM通道3
  /* 一开始先关闭 */
  HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
  HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
  HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
  HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
  HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
  HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
}

通用定时器.h

#ifndef __BSP_HALL_H__
#define __BSP_HALL_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
#define HALL_TIMx                        TIM3
#define HALL_TIM_RCC_CLK_ENABLE()        __HAL_RCC_TIM3_CLK_ENABLE()
#define HALL_TIM_RCC_CLK_DISABLE()       __HAL_RCC_TIM3_CLK_DISABLE()

#define HALL_TIM_AFIO_REMAP()            __HAL_AFIO_REMAP_TIM3_ENABLE() /* 启用TIM3备用功能通道1至4的重新映射 */
#define HALL_TIM_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()
/* 定时器3的三个霍尔传感器接口 */
#define HALL_TIM_CH1_PIN                 GPIO_PIN_6
#define HALL_TIM_CH1_GPIO                GPIOC
#define HALL_TIM_CH2_PIN                 GPIO_PIN_7
#define HALL_TIM_CH2_GPIO                GPIOC
#define HALL_TIM_CH3_PIN                 GPIO_PIN_8
#define HALL_TIM_CH3_GPIO                GPIOC

// 定义定时器预分频,定时器实际时钟频率为:72MHz/(HALL_TIMx_PRESCALER+1)
#define HALL_TIM_PRESCALER               71

// 定义定时器周期,当定时器开始计数到HALL_TIMx_PERIOD值是更新定时器并生成对应事件和中断
#define HALL_TIM_PERIOD                  0xFFFF

#define HALL_TIM_IRQn                    TIM3_IRQn
#define HALL_TIM_IRQHANDLER              TIM3_IRQHandler

/* 扩展变量 ------------------------------------------------------------------*/
extern TIM_HandleTypeDef htimx_HALL;

/* 函数声明 ------------------------------------------------------------------*/
void HALL_TIMx_Init(void);

#endif	/* __HALL_TIM_H__ */

通用定时器.c

/* 包含头文件 ----------------------------------------------------------------*/
#include "hall/bsp_hall.h"

/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* Timer handler declaration */
TIM_HandleTypeDef              htimx_HALL;

/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 通用定时器初始化并配置通道PWM输出
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void HALL_TIMx_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  TIM_OC_InitTypeDef      sOCConfig;
  TIM_HallSensor_InitTypeDef     sHallSensorConfig;  
  
  /* 基本定时器外设时钟使能 */
  HALL_TIM_RCC_CLK_ENABLE();
  HALL_TIM_GPIO_CLK_ENABLE();

  /* 定时器通道1功能引脚IO初始化 */
  GPIO_InitStruct.Pin = HALL_TIM_CH1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  GPIO_InitStruct.Pull=GPIO_PULLUP;
  HAL_GPIO_Init(HALL_TIM_CH1_GPIO, &GPIO_InitStruct);

  /* 定时器通道2功能引脚IO初始化 */
  GPIO_InitStruct.Pin = HALL_TIM_CH2_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  GPIO_InitStruct.Pull=GPIO_PULLUP;
  HAL_GPIO_Init(HALL_TIM_CH2_GPIO, &GPIO_InitStruct);
      
  /* 定时器通道3功能引脚IO初始化 */
  GPIO_InitStruct.Pin = HALL_TIM_CH3_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  GPIO_InitStruct.Pull=GPIO_PULLUP;
  HAL_GPIO_Init(HALL_TIM_CH3_GPIO, &GPIO_InitStruct);
  
  HALL_TIM_AFIO_REMAP(); // 定时器引脚重映射
  
  htimx_HALL.Instance = HALL_TIMx;
  htimx_HALL.Init.Prescaler = HALL_TIM_PRESCALER;
  htimx_HALL.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx_HALL.Init.Period = HALL_TIM_PERIOD;
  htimx_HALL.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
  
  sHallSensorConfig.IC1Prescaler=TIM_ICPSC_DIV1;
  sHallSensorConfig.IC1Polarity=TIM_ICPOLARITY_RISING;
  sHallSensorConfig.IC1Filter=10;
  sHallSensorConfig.Commutation_Delay=0;  
  HAL_TIMEx_HallSensor_Init(&htimx_HALL,&sHallSensorConfig); // 初始化TIM3霍尔传感器接口
  
  sOCConfig.OCMode = TIM_OCMODE_TIMING;
  sOCConfig.Pulse = 0xFFFF;
  sOCConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
  sOCConfig.OCFastMode = TIM_OCFAST_DISABLE;
  sOCConfig.OCIdleState = TIM_OCIDLESTATE_SET;
  HAL_TIM_OC_ConfigChannel(&htimx_HALL, &sOCConfig, TIM_CHANNEL_4); /* 初始化TIM3输出比较通道4 */
  TIM_CCxChannelCmd(HALL_TIMx, TIM_CHANNEL_4, TIM_CCx_ENABLE); /* TIM3捕获比较通道4 */
  
  HAL_NVIC_SetPriority(HALL_TIM_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(HALL_TIM_IRQn);
}

main.c

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "AdvancedTIM/bsp_AdvancedTIM.h"
#include "key/bsp_key.h"
#include "hall/bsp_hall.h"

/* 私有类型定义 --------------------------------------------------------------*/
typedef enum
{
  CW=0,  // 顺时钟方向
  CCW=1  // 逆时针方向
}MOTOR_DIR;

typedef enum 
{
  STOP=0,  // 停机
  RUN=1    // 运行
}MOTOR_STATE;

/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
__IO int16_t      speed_duty=15;       // 速度占空比:0~100  为100是占空比为100%
__IO MOTOR_STATE  motor_state=STOP;    // 电机状态
__IO MOTOR_DIR    motor_direction=CW;  // 电机方向

__IO uint8_t time_over  = 0;           // 卡住超时溢出计数(防止堵转)
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void BLDC_PHASE_CHANGE(uint8_t step);
/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 系统时钟配置
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟:72MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;               // APB1时钟:36MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;               // APB2时钟:72MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  HAL_RCC_EnableCSS();
  
 	// HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
	// HAL_RCC_GetHCLKFreq()/100000	 10us中断一次
	// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器
  /* 系统滴答定时器时钟源 */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  /* 系统滴答定时器中断优先级配置 */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{
  uint8_t key_count=1;
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();

  KEY_GPIO_Init();
  HALL_TIMx_Init();
  
  /* 高级控制定时器初始化并配置PWM输出功能 */
  ADVANCED_TIMx_Init();

  /* 无限循环 */
  while (1)
  {
    if(KEY1_StateRead()==KEY_DOWN) // 功能选择
    {
      key_count++;
      if(key_count>5)
        key_count=1;
    }
    if(KEY2_StateRead()==KEY_DOWN)// 功能执行
    {
      switch(key_count)
      {
        case 1: // 电机启动
          if(motor_state==STOP)
          {
            motor_state=RUN;
            HAL_TIM_TriggerCallback(&htimx_HALL); // 非阻塞模式下的霍尔触发器检测回调
            HAL_Delay(4);
            HAL_TIMEx_HallSensor_Start(&htimx_HALL); /* 启动TIM3霍尔传感器接口 */
            /* 开启通道4输出比较中断的 与霍尔传感器的触发中断(三个通道任意发生边沿跳变) */
            __HAL_TIM_ENABLE_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
            HAL_TIM_TriggerCallback(&htimx_HALL);
          }          
          break;
        case 2: // 加速
          speed_duty+=5;
          if(speed_duty>100)
            speed_duty=100;   
          break;
        case 3: // 减速
          speed_duty-=5;
          if(speed_duty<7)
            speed_duty=7;  
          break;
        case 4: // 方向反转
          if(motor_direction==CW)
            motor_direction=CCW;
          else
            motor_direction=CW;
          break;
        case 5: // 停机
          motor_state=STOP;            
          HAL_TIMEx_HallSensor_Stop(&htimx_HALL); 
          __HAL_TIM_DISABLE_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
          __HAL_TIM_CLEAR_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
          HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
          HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
          HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
          HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
          HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
          HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
          break;
      }
           
    }
  }
}

/**
  * 函数功能: 无刷驱动换相
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void BLDC_PHASE_CHANGE(uint8_t step)
{
  /* BLDC的六步换相各绕组的导通控制要根据自己BLDC厂家给的六步换相表因为不同的厂家不一样 */
  /* 采用上桥臂PWM 下桥臂高电平的PWM方式 */
  switch(step)
  {
    case 4: //B+ C-
      /* Next step: Step 2 Configuration -------------------------------------- */ 
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      
      /*  Channel1 configuration */
      /*  Channel2 configuration */    
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD; /* 100%的占空比相当于给高电平 */
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 5: //B+ A-
      /* Next step: Step 3 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);    
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      break;
    case 1: //C+ A-
      /* Next step: Step 4 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */ 
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 3: //C+ B-
      /* Next step: Step 5 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);      
    
      /*  Channel1 configuration */      
      /*  Channel2 configuration */   
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */      
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 2: //A+ B-
      /* Next step: Step 6 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
      /*  Channel3 configuration */
      break;
    case 6: //A+ C-
      /* Next step: Step 1 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */      
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    default:
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      break;
  }
}



// 通道4输出比较中断的 只是用来防止电机堵转的 也可以不用
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
  time_over++;
  if(time_over>6) // 电机卡住超时
  {
    // 停止转动标志
    motor_state=STOP;            
    HAL_TIMEx_HallSensor_Stop(&htimx_HALL); 
    __HAL_TIM_DISABLE_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
    __HAL_TIM_CLEAR_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
    HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
    HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
  }
}
/**
  * 函数功能: 定时器触发中断服务函数
  * 输入参数: GPIO_Pin:中断引脚
  * 返 回 值: 无
  * 说    明: 无
  */

//霍尔传感器的触发中断(三个通道任意发生边沿跳变)
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
{
  uint8_t pinstate=0; // 获取霍尔传感器三个I/o口的值从而获得转子的位置
  if(motor_state==STOP)return;

  if((HALL_TIM_CH1_GPIO->IDR & HALL_TIM_CH1_PIN) != GPIO_PIN_RESET)  //霍尔传感器状态获取
  {
    pinstate |= 0x01;
  }
  if((HALL_TIM_CH2_GPIO->IDR & HALL_TIM_CH2_PIN) != GPIO_PIN_RESET)  //霍尔传感器状态获取
  {
    pinstate |= 0x02;
  }
  if((HALL_TIM_CH3_GPIO->IDR & HALL_TIM_CH3_PIN) != GPIO_PIN_RESET)  //霍尔传感器状态获取
  {
    pinstate |= 0x04;
  }
  if(motor_direction==CW) // 方向判断
    pinstate=7-pinstate;
  BLDC_PHASE_CHANGE(pinstate);//驱动换相
  time_over  = 0;
}

2.开环-三个外部中断检测转子位置的方式

说明:高级定时器T1,三个外部中断线(任意选择空闲的三个引脚),滴答定时器中断2s检测电机是否堵转。

高级定时器不在列出与上面一样。

外部中断.h

#ifndef __BSP_HALL_H__
#define __BSP_HALL_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
#define HALL_RCC_CLK_ENABLE()          __HAL_RCC_GPIOC_CLK_ENABLE()
#define HALL_GPIOx                     GPIOC
#define HALL1_GPIO_PIN                 GPIO_PIN_6
#define HALL2_GPIO_PIN                 GPIO_PIN_7
#define HALL3_GPIO_PIN                 GPIO_PIN_8

#define HALL_EXTI_IRQHandler          EXTI9_5_IRQHandler
#define HALL_EXTI_IRQn                EXTI9_5_IRQn

/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void HALL_GPIO_Init(void);

外部中断.c

#include "hall/bsp_hall.h"
void HALL_GPIO_Init(void)
{
   /* 定义IO硬件初始化结构体变量 */
  GPIO_InitTypeDef GPIO_InitStruct;
	
	/* 使能外部中断引脚对应IO端口时钟 */  
  HALL_RCC_CLK_ENABLE();
  
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;/* 具有上升/下降沿触发检测的外部中断模式 */
  GPIO_InitStruct.Pull = GPIO_PULLUP;  
  GPIO_InitStruct.Pin = HALL1_GPIO_PIN;
  HAL_GPIO_Init(HALL_GPIOx, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = HALL2_GPIO_PIN;
  HAL_GPIO_Init(HALL_GPIOx, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = HALL3_GPIO_PIN;
  HAL_GPIO_Init(HALL_GPIOx, &GPIO_InitStruct);
  
  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(HALL_EXTI_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(HALL_EXTI_IRQn);

}

main.c

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "AdvancedTIM/bsp_AdvancedTIM.h"
#include "key/bsp_key.h"
#include "hall/bsp_hall.h"

/* 私有类型定义 --------------------------------------------------------------*/
typedef enum
{
  CW=0,  // 顺时钟方向
  CCW=1  // 逆时针方向
}MOTOR_DIR;

typedef enum 
{
  STOP=0,  // 停机
  RUN=1    // 运行
}MOTOR_STATE;

/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
__IO int16_t      speed_duty=15;       // 速度占空比:0~100  为100是占空比为100%
__IO MOTOR_STATE  motor_state=STOP;    // 电机状态
__IO MOTOR_DIR    motor_direction=CW;  // 电机方向
__IO uint16_t     time_count=0;        // 卡住超时溢出计数

/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void BLDC_PHASE_CHANGE(uint8_t step);
/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 系统时钟配置
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟:72MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;               // APB1时钟:36MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;               // APB2时钟:72MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  HAL_RCC_EnableCSS();
  
 	// HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
	// HAL_RCC_GetHCLKFreq()/100000	 10us中断一次
	// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器
  /* 系统滴答定时器时钟源 */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  /* 系统滴答定时器中断优先级配置 */
  HAL_NVIC_SetPriority(SysTick_IRQn, 2, 0);
}

/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{
  uint8_t key_count=1;
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();

  KEY_GPIO_Init();
  HALL_GPIO_Init();
  
  /* 高级控制定时器初始化并配置PWM输出功能 */
  ADVANCED_TIMx_Init();

  /* 无限循环 */
  while (1)
  {
    if(KEY1_StateRead()==KEY_DOWN) // 功能选择
    {
      key_count++;
      if(key_count>5)
        key_count=1;
    }
    if(KEY2_StateRead()==KEY_DOWN) // 功能执行
    {
      switch(key_count)
      {
        case 1: // 电机启动
          if(motor_state==STOP)
          {
            motor_state=RUN;
            HAL_GPIO_EXTI_Callback(GPIO_PIN_All);
            HAL_Delay(5);
            HAL_NVIC_EnableIRQ(HALL_EXTI_IRQn);
            HAL_GPIO_EXTI_Callback(GPIO_PIN_All);
          }          
          break;
        case 2: // 加速
          speed_duty+=5;
          if(speed_duty>100)
            speed_duty=100;   
          break;
        case 3: // 减速
          speed_duty-=5;
          if(speed_duty<7)
            speed_duty=7;  
          break;
        case 4: // 方向反转
          if(motor_direction==CW)
            motor_direction=CCW;
          else
            motor_direction=CW;
          break;
        case 5: // 停机
            motor_state=STOP;
            __HAL_GPIO_EXTI_CLEAR_IT(HALL1_GPIO_PIN|HALL2_GPIO_PIN|HALL3_GPIO_PIN);
            HAL_NVIC_DisableIRQ(HALL_EXTI_IRQn);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
          break;
      }           
    }
  }
}

void BLDC_PHASE_CHANGE(uint8_t step)
{
  switch(step)
  {
#if 1  // H_PWM_L_ON的PWM模式
    case 4: //B+ C-
      /* Next step: Step 2 Configuration -------------------------------------- */ 
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      
      /*  Channel1 configuration */
      /*  Channel2 configuration */    
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 5: //B+ A-
      /* Next step: Step 3 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);    
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      break;
    case 1: //C+ A-
      /* Next step: Step 4 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */ 
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 3: //C+ B-
      /* Next step: Step 5 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);      
    
      /*  Channel1 configuration */      
      /*  Channel2 configuration */   
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */      
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 2: //A+ B-
      /* Next step: Step 6 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
      /*  Channel3 configuration */
      break;
    case 6: //A+ C-
      /* Next step: Step 1 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */      
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
#elif 1  // H_ON_L_PWM
        case 4: //B+ C-
      /* Next step: Step 2 Configuration -------------------------------------- */ 
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      
      /*  Channel1 configuration */
      /*  Channel2 configuration */    
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 5: //B+ A-
      /* Next step: Step 3 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);    
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      break;
    case 1: //C+ A-
      /* Next step: Step 4 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */ 
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 3: //C+ B-
      /* Next step: Step 5 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);      
    
      /*  Channel1 configuration */      
      /*  Channel2 configuration */   
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */      
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 2: //A+ B-
      /* Next step: Step 6 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
      /*  Channel3 configuration */
      break;
    case 6: //A+ C-
      /* Next step: Step 1 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */      
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
#else // ON_PWM
    case 4: //B+ C-
      /* Next step: Step 2 Configuration -------------------------------------- */ 
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      
      /*  Channel1 configuration */
      /*  Channel2 configuration */    
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 5: //B+ A-
      /* Next step: Step 3 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);    
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      break;
    case 1: //C+ A-
      /* Next step: Step 4 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */ 
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 3: //C+ B-
      /* Next step: Step 5 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);      
    
      /*  Channel1 configuration */      
      /*  Channel2 configuration */   
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */      
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 2: //A+ B-
      /* Next step: Step 6 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
      /*  Channel3 configuration */
      break;
    case 6: //A+ C-
      /* Next step: Step 1 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/100;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */      
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
#endif
    default:
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      break;
  }
}
/* 滴答定时器中断1ms进入一次 */
void HAL_SYSTICK_Callback(void)
{
  if(motor_state==RUN)
  {
    time_count++;
    if(time_count>2000) // 电机卡住超时
    {
      motor_state=STOP;
      __HAL_GPIO_EXTI_CLEAR_IT(HALL1_GPIO_PIN|HALL2_GPIO_PIN|HALL3_GPIO_PIN);
      HAL_NVIC_DisableIRQ(HALL_EXTI_IRQn);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);      
    }
  }
}

/**
  * 函数功能: 外部中断服务函数
  * 输入参数: GPIO_Pin:中断引脚
  * 返 回 值: 无
  * 说    明: 无
  */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  __IO uint32_t uwStep = 0;
  uint16_t hall_read=(HALL_GPIOx->IDR)&0x01c0; // 霍尔传感器信号获取
  
  if(motor_state==STOP)return;
  uwStep=hall_read>>6;
  if(motor_direction==CW) // 方向判断
  uwStep=7-uwStep;  
  BLDC_PHASE_CHANGE(uwStep);  // 驱动换相
  time_count=0;
}

3.速度环(闭环)-霍尔传感器检测转子位置的方式

HAL_SYSTICK_Callback滴答定时器回调函数比较重要。速度具体怎么得出。

四对极为例。每转60度三个霍尔传感器会经历四个磁极性。一圈就是4*6=24次经历磁极性。

其实就是三个霍尔传感器任意引脚发生电平跳变就是经历一次磁极性。在霍尔传感器触发中断记录经历的磁极性。24次就是一圈。假如50ms有48次就说明50ms转两个圈。接着除50就是1ms时间可以多少次。从而可以求出rps,rpm。代码里HAL_SYSTICK_Callback函数有。

高级定时器与通用定时器是一样的与dome1.

main.c

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "AdvancedTIM/bsp_AdvancedTIM.h"
#include "key/bsp_key.h"
#include "hall/bsp_hall.h"

/* 私有类型定义 --------------------------------------------------------------*/
typedef enum
{
  CW=0,       // 顺时钟方向
  CCW=1       // 逆时针方向
}MOTOR_DIR;

typedef enum 
{
  STOP=0,    // 停止
  RUN=1      // 运转
}MOTOR_STATE;

typedef struct
{
  __IO int          motor_speed;        // 电机转速(RPM):0..2500
  __IO MOTOR_STATE  motor_state;        // 电机旋转状态
  __IO MOTOR_DIR    motor_direction;    // 电机转动方向
  __IO uint32_t     step_counter;       // 霍尔传感器步数,用于测量电机转速
  __IO uint16_t     stalling_count;     // 停机标志,如果该值超2000,认为电机停止旋转
}MOTOR_DEVICE;

//定义PID结构体
typedef struct 
{
   __IO int      SetPoint;      //设定目标 Desired Value
   __IO double   Proportion;    //比例常数 Proportional Const
   __IO double   Integral;      //积分常数 Integral Const
   __IO double   Derivative;    //微分常数 Derivative Const
   __IO int      LastError;     //Error[-1]
   __IO int      PrevError;     //Error[-2]
}PID;

/* 私有宏定义 ----------------------------------------------------------------*/
/*************************************/
//定义PID相关宏
// 这三个参数设定对电机运行影响非常大
/*************************************/
#define  P_DATA                   0.5                            //P参数
#define  I_DATA                   0.06                           //I参数
#define  D_DATA                   0                              //D参数

#define  MOTOR_RATED_SPEED        2500
#define  MOTOR_MAX_SPEED          3500
#define  MOTOR_MIN_SPEED          100            
#define  MOTOR_POLE_NUM           4

/* 私有变量 ------------------------------------------------------------------*/
MOTOR_DEVICE bldc_dev={1000,STOP,CW,0,0};
static PID bldc_pid;
__IO int16_t speed_duty=100; // 速度占空比:0~1000  为1000是占空比为100%
                              // 初始化值必须不小于70,否则电机会堵塞
__IO uint8_t time_over  = 0; 	//定时器溢出计数

/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void BLDC_PHASE_CHANGE(uint8_t step);
void IncPIDInit(void);
int IncPIDCalc(int NextPoint);

/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 系统时钟配置
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟:72MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;               // APB1时钟:36MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;               // APB2时钟:72MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  HAL_RCC_EnableCSS();
  
 	// HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
	// HAL_RCC_GetHCLKFreq()/100000	 10us中断一次
	// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器
  /* 系统滴答定时器时钟源 */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  /* 系统滴答定时器中断优先级配置 */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{
  uint8_t key_count=1; /* 为不同值有不同的功能 由按键1调节 */
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();

  KEY_GPIO_Init();

  HALL_TIMx_Init();
  
  /* 高级控制定时器初始化并配置PWM输出功能 */
  ADVANCED_TIMx_Init();
  
  /* 无限循环 */
  while (1)
  {
    if(KEY1_StateRead()==KEY_DOWN) // 功能选择
    {
      key_count++;
      if(key_count>5)
        key_count=1;
    }
    if(KEY2_StateRead()==KEY_DOWN) // 功能执行
    {
      switch(key_count)
      {
        case 1:
          if(bldc_dev.motor_state==STOP)
          {
            bldc_dev.motor_state=RUN;
            bldc_dev.step_counter=0;
            bldc_dev.stalling_count=0;
            IncPIDInit();
            if((bldc_dev.motor_speed*10/25)>70)
              /* 当占空比为10对应的转速是25 */
              speed_duty=bldc_dev.motor_speed*10/25;// *10/25为转速和占空比一个转换,转速(0~2500),占空比(0~1000)
            else
              speed_duty=70;
            HAL_TIMEx_HallSensor_Start(&htimx_HALL); 
            __HAL_TIM_ENABLE_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
            HAL_TIM_TriggerCallback(&htimx_HALL);
          }          
          break;
        case 2:  // 加速
          bldc_dev.motor_speed+=100;
          if(bldc_dev.motor_speed>MOTOR_MAX_SPEED)
            bldc_dev.motor_speed=MOTOR_MAX_SPEED;
          bldc_pid.SetPoint=bldc_dev.motor_speed;
          break;
        case 3: // 减速
          bldc_dev.motor_speed-=50;
          if(bldc_dev.motor_speed<MOTOR_MIN_SPEED)
            bldc_dev.motor_speed=MOTOR_MIN_SPEED;
          bldc_pid.SetPoint=bldc_dev.motor_speed;
          break;
        case 4: // 方向反转
          if(bldc_dev.motor_direction==CW)
          {
            bldc_dev.motor_direction=CCW;
          }
          else
          {
            bldc_dev.motor_direction=CW;
          }
          break;
        case 5:     // 停机   
            HAL_TIMEx_HallSensor_Stop(&htimx_HALL); 
            __HAL_TIM_DISABLE_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
            __HAL_TIM_CLEAR_IT(&htimx_HALL, TIM_IT_TRIGGER|TIM_IT_CC4);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
            HAL_Delay(5);
            /* 下面代码只是一个简要的刹车功能也可以不要 */
            HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
            while(bldc_dev.stalling_count<1);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
            HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3); 
            bldc_dev.motor_state=STOP;
          break;
      }    
    }
  }
}
/**
  * 函数功能: 无刷驱动换相
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void BLDC_PHASE_CHANGE(uint8_t step)
{
  switch(step)
  {
    case 4: //B+ C-
      /* Next step: Step 2 Configuration -------------------------------------- */ 
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      
      /*  Channel1 configuration */
      /*  Channel2 configuration */    
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 5: //B+ A-
      /* Next step: Step 3 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);    
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2); 
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */
      break;
    case 1: //C+ A-
      /* Next step: Step 4 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
    
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);      
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */ 
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 3: //C+ B-
      /* Next step: Step 5 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);      
    
      /*  Channel1 configuration */      
      /*  Channel2 configuration */   
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);    
      /*  Channel3 configuration */      
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);    
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    case 2: //A+ B-
      /* Next step: Step 6 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */
      sPWMConfig2.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig2, TIM_CHANNEL_2);    
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_2);
      /*  Channel3 configuration */
      break;
    case 6: //A+ C-
      /* Next step: Step 1 Configuration -------------------------------------- */
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      
      /*  Channel1 configuration */
      sPWMConfig1.Pulse      = ADVANCED_TIM_PERIOD*speed_duty/1000;    
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig1, TIM_CHANNEL_1);        
      HAL_TIM_PWM_Start(&htimx_BLDC, TIM_CHANNEL_1);
      /*  Channel2 configuration */      
      /*  Channel3 configuration */
      sPWMConfig3.Pulse      = ADVANCED_TIM_PERIOD;
      HAL_TIM_PWM_ConfigChannel(&htimx_BLDC, &sPWMConfig3, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htimx_BLDC, TIM_CHANNEL_3);
      break;
    default:
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_1);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_2);
      HAL_TIM_PWM_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htimx_BLDC, TIM_CHANNEL_3);
      break;
  }
}

/**************PID参数初始化********************************/
void IncPIDInit(void) 
{
  bldc_pid.LastError=0;                    //Error[-1]
  bldc_pid.PrevError=0;                    //Error[-2]
  bldc_pid.Proportion=P_DATA;              //比例常数 Proportional Const
  bldc_pid.Integral=I_DATA;                //积分常数  Integral Const
  bldc_pid.Derivative=D_DATA;              //微分常数 Derivative Const
  bldc_pid.SetPoint=bldc_dev.motor_speed;  //设定目标Desired Value
}
/********************增量式PID控制设计************************************/
int IncPIDCalc(int NextPoint) 
{
  int iError,iIncpid;                                       //当前误差
  iError=bldc_pid.SetPoint - NextPoint;                     //增量计算
  iIncpid=(bldc_pid.Proportion * iError)                    //E[k]项
              -(bldc_pid.Integral * bldc_pid.LastError)     //E[k-1]项
              +(bldc_pid.Derivative * bldc_pid.PrevError);  //E[k-2]项
              
  bldc_pid.PrevError=bldc_pid.LastError;                    //存储误差,用于下次计算
  bldc_pid.LastError=iError;
  return(iIncpid);                                    //返回增量值
}

/**
  * 函数功能: 系统滴答定时器回调函数
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 1ms运行该函数一次
  */
void HAL_SYSTICK_Callback(void)
{
  static uint16_t time_count=0;
 
  if(bldc_dev.motor_state==RUN)
  {
    time_count++;
    if(time_count>50) // 50ms
    {
      int temp;
      int pid_result;
      // bldc_dev.step_counter记录霍尔传感器在50ms时间内产生的脉冲个数,而电机旋转一圈会有总共(MOTOR_POLE_NUM*6)个脉冲,
      // 使用 n=bldc_dev.step_counter/(MOTOR_POLE_NUM*6) 为50ms内电机转动圈数,为换算为【转/分钟(rpm)】
      //  n/50 = x/(60*1000) --> x=bldc_dev.step_counter*50
      temp=bldc_dev.step_counter*50;
      pid_result=IncPIDCalc(temp);     // 计算增量
      pid_result =pid_result*10/25;    // *10/25为转速和占空比一个转换,转速(0~2500),占空比(0~1000)
      if((pid_result+speed_duty)<70)
        speed_duty =70;
      else if((pid_result+speed_duty)>1000)
        speed_duty =1000;
      else
        speed_duty +=pid_result;    
      time_count=0;
      bldc_dev.step_counter=0;
    }
  }
  else
  {
    time_count=0;
  }
}

/**
  * 函数功能: 定时器输出比较中断服务函数
  * 输入参数: htim:定时器号
  * 返 回 值: 无
  * 说    明: 无
  */
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
  time_over++;
  if(time_over>6)
  {
    bldc_dev.stalling_count++;// 停止转动标志
    time_over=0;
  }
}

/**
  * 函数功能: 定时器触发中断服务函数
  * 输入参数: htim:定时器号
  * 返 回 值: 无
  * 说    明: 无
  */
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
{
  uint8_t pinstate=0;
  static __IO int8_t pinstate0=0;

  if(bldc_dev.motor_state==STOP)return;
  
  if((HALL_TIM_CH1_GPIO->IDR & HALL_TIM_CH1_PIN) != GPIO_PIN_RESET) //霍尔传感器状态获取
  {
    pinstate |= 0x01;
  }
  if((HALL_TIM_CH2_GPIO->IDR & HALL_TIM_CH2_PIN) != GPIO_PIN_RESET) //霍尔传感器状态获取
  {
    pinstate |= 0x02;
  }
  if((HALL_TIM_CH3_GPIO->IDR & HALL_TIM_CH3_PIN) != GPIO_PIN_RESET) //霍尔传感器状态获取
  {
    pinstate |= 0x04;
  }
    
  if(bldc_dev.motor_direction==CW) // 方向判断
    pinstate=7-pinstate;
  BLDC_PHASE_CHANGE(pinstate);//驱动换相 
  
  if(pinstate0!=pinstate) // 测试发现有时会连续出现两个相同的数据,这里滤掉重复的
  {
    bldc_dev.step_counter++;
    bldc_dev.stalling_count=0;
  }  
  pinstate0=pinstate;
  time_over  = 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值