有感无刷BLDC电机

STM32F103_简单BLDC驱动
第一章 :转动原理
第二章 :硬件及连接方式
第三章:代码初始化及注意事项
第四章:转动



前言

本例程只适合:三相 120°霍尔无刷电机。程序为简单的转动功能(120°检测Hall状态),只作为检测电机使用。

一、转动原理

通过Hall_U / Hall_V / Hall_W 三根线连接芯片的pin 脚,根据这三个pin脚的信号变化判断转子当前的角度或者位置。根据获取的转子角度或位置启动下一角度对应的电压(简单说就是根据当前的位置,开启下一个转子前往的点,然后一直循环)。

霍尔需要注意有两点不同:线性霍尔和开关型霍尔(应用环境不同,本例程只作为检测电机好坏使用,所以配置的是开关型霍尔)。

请添加图片描述
假设转子当前正处于300°,所测信号如下:
请添加图片描述
如果电机需要转动,需要开启U相的电压。(若使用6步换相法,应该先开启V相的下管,再开启W相的下管)。将转子拽到60°

二、硬件连接

1.驱动板硬件

驱动板正面
驱动板背面
驱动板原理图

驱动板的第一版没有做PGND和AGND分离。但经过测试,也可以使用。
需要注意的是:此版本硬件,控制LED状态的Q7和Q8是错误的(D/S反向),目前是不受控状态。但是不影响使用(DRV8301的OCTW和FAUL信号内部是开漏输出,正常状态是拉低的。由上拉电阻拉高的3.3V信号,经过开漏,拉低。如果异常,开漏截止,信号上拉为高。此时LED无法作为提醒功能。因为+3.3V通过体二极管直接就输出了,所以,LED是常量状态)

2.MCU与驱动板连接

淘宝买的
采用杜邦线与驱动板连接
请添加图片描述
MCU供电和霍尔的供电直接采用DRV8301输出的3.3V

pin脚定义如下:

Hall_U ----->PD0
Hall_V ----->PD1
Hall_W ----->PD2

Debug_usart_Tx ------->PB6
Debug_usart_Rx ------->PB7

AH -------->PA8
AL -------->PB13
BH -------->PA9
BL -------->PB14
CH -------->PA10
CL -------->PB15

DRV8301_SPIx_CS ----->PF0
DRV8301_SPIx_SCK ----->PF1
DRV8301_SPIx_MISO ----->PF2
DRV8301_SPIx_MOSI ----->PF3

OCTW ------->PF6
EN_GATE ---->PF5
FAULT ------->PF7
DC_CAL ------>PF4

三、代码初始化

1.debug_usart初始化

#ifndef __DEBUG_H
#define __DEBUG_H
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include <stdio.h>

	  	


void debug_usart1_config(uint32_t  bound);
#endif
#include "debug.h"

#pragma import(__use_no_semihosting)             
                
struct __FILE { 
	int handle; 

}; 

FILE __stdout;       
  
void _sys_exit(int x) { 
	x = x; 
} 

int fputc(int ch, FILE *f){      
	while((USART1->SR&0X40)==0){
    } 
    USART1->DR = (u8) ch;      
	return ch;
}

  
void debug_usart1_config(uint32_t  Bound){

	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOB, ENABLE);	//使能USART1,GPIOA时钟
    GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
	//USART1_TX   GPIOB.6
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//USART1_RX	  GPIOB.7初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  

	USART_InitStructure.USART_BaudRate = Bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	

    USART_Init(USART1, &USART_InitStructure); 
    USART_Cmd(USART1, ENABLE);                    

}

2.debug_led初始化

#ifndef __LED_H
#define __LED_H

#include <stm32f10x.h>   
#include "SEGGER_RTT.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "stm32f10x_exti.h"
#include "delay.h"
#include "debug.h"

#define led_on    GPIOC->BRR =0x2000;//输出低电平
#define led_off    GPIOC->BSRR=0x2000;//输出高电平
#define KEY0  GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_6)

void led_config(void);

#endif
#include "led.h"

static void led_timer_init(void);
static void led_gpio_init(void);
static void key_init(void);

void led_config(void){
    
    led_gpio_init();
    led_timer_init();
    key_init();
}

static void led_gpio_init(void){
    
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
 	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
 	GPIO_Init(GPIOC, &GPIO_InitStructure); 
    
    GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}


static void led_timer_init(void){
    
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); 
      NVIC_InitTypeDef  NVIC_InitStruct;
    
     TIM6->PSC= 8000-1;//预分频器
     TIM6->ARR= 7000-1;//自动重装载寄存器 

     TIM6->DIER |=0x01;//更新中断开启
     TIM6->CR1  |=0x01;//开启定时器
  
    NVIC_InitStruct.NVIC_IRQChannel=TIM6_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=4;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=3;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    
    NVIC_Init(&NVIC_InitStruct);
}

int8_t led_start=0;
void TIM6_IRQHandler(void){
    
    if(TIM6->SR&0x01){
        led_start =~led_start;
       if(led_start){
       	 led_on
       }else{
       	 led_off
       }           
//     printf("led_start=%d\n\r",led_start);
    }
     TIM6->SR &=~(1<<0);      
}

3.DRV8301初始化

#ifndef __SPI_H
#define __SPI_H

#include "SEGGER_RTT.h"
#include <stm32f10x.h>   
#include "delay.h"	 

#define DRV8301_REG0    0
#define DRV8301_REG1    1
#define DRV8301_REG2    2
#define DRV8301_REG3    3

//reg2
#define GATE_CURRENT_1_7_A        0x0000
#define GATE_CURRENT_0_7_A        0x0001
#define GATE_CURRENT_0_25_A       0x0002

#define GATE_RESET_NOMAL          0x0000
#define GATE_RESET_FAULTS         0x0004

#define PWM_MODE_6_INPUTS         0x0000
#define PWM_MODE_3_INPUTS         0x0008

#define OCP_CURR_LIMIT            0x0000
#define OCP_LATCH_SHUT_DOWN       0x0010
#define OCP_REPORT_ONLY           0x0020
#define OCP_DISABLED              0x0030

#define OC_ADJ_SET_0              0x0000      //0.060V
#define OC_ADJ_SET_1              0x0040      //0.068V
#define OC_ADJ_SET_2              0x0080      //0.076V
#define OC_ADJ_SET_3              0x00c0      //0.086V
#define OC_ADJ_SET_4              0x0100      //0.097V
#define OC_ADJ_SET_5              0x0140      //0.109V
#define OC_ADJ_SET_6              0x0180      //0.123V
#define OC_ADJ_SET_7              0x01c0      //0.138V
#define OC_ADJ_SET_8              0x0200      //0.155V
#define OC_ADJ_SET_9              0x0240      //0.175V
#define OC_ADJ_SET_10             0x0280      //0.197V
#define OC_ADJ_SET_11             0x02c0      //0.222V
#define OC_ADJ_SET_12             0x0300      //0.250V
#define OC_ADJ_SET_13             0x0340      //0.282V
#define OC_ADJ_SET_14             0x0380      //0.317V
#define OC_ADJ_SET_15             0x03c0      //0.358V
#define OC_ADJ_SET_16             0x0400      //0.403V
#define OC_ADJ_SET_17             0x0440      //0.454V
#define OC_ADJ_SET_18             0x0480      //0.511V
#define OC_ADJ_SET_19             0x04c0      //0.576V
#define OC_ADJ_SET_20             0x0500      //0.648V
#define OC_ADJ_SET_21             0x0540      //0.730V
#define OC_ADJ_SET_22             0x0580      //0.822V
#define OC_ADJ_SET_23             0x05c0      //0.926V
#define OC_ADJ_SET_24             0x0600      //1.043V
#define OC_ADJ_SET_25             0x0640      //1.175V
#define OC_ADJ_SET_26             0x0680      //1.324V
#define OC_ADJ_SET_27             0x06c0      //1.491V
#define OC_ADJ_SET_28             0x0700      //1.679V
#define OC_ADJ_SET_29             0x0740      //1.892V
#define OC_ADJ_SET_30             0x0780      //2.131V
#define OC_ADJ_SET_31             0x07c0      //2.400V

//reg3
#define OCTW_OT_AND_OC            0x0000
#define OCTW_OT_ONLY              0x0001
#define OCTW_OC_ONLY              0x0002

#define GAIN_AMP_10               0x0000              
#define GAIN_AMP_20               0x0004
#define GAIN_AMP_40               0x0008
#define GAIN_AMP_80               0x000C

#define DC_CAL_CH1_CON            0x0000
#define DC_CAL_CH1_DIS            0x0010

#define DC_CAL_CH2_CON            0x0000
#define DC_CAL_CH2_DIS            0x0020

#define OC_TOFF_CYCLE             0x0000
#define OC_TOFF_OFF_TIME          0x0040

/*SPI 片选  PF0 */
#define DRV8301_SPIx_CS_PIN_SET           (1<<0)

/*SPI 时钟  PF1 */
#define DRV8301_SPIx_SCK_PIN_SET           (3<<4)

/*SPI输入 PF2 */
#define DRV8301_SPIx_MISO_PIN_SET          (8<<8)

/*SPI输出 PF3 */
#define DRV8301_SPIx_MOSI_PIN_SET          (3<<12)

/*PF6 输入模式 */
#define OCTW_PIN_SET                       (8<<0)
/*PF5 输出*/
#define EN_GATE_PIN_SET                    (1<<20)  
/*PF7 输入模式*/
#define FAULT_PIN_SET                      (8<<28)      

#define DC_CAL_PIN_SET                    (1<<16)  
/*清除端口位*/
#define BSRR_BIT0_BR0       (1<<0)
#define BSRR_BIT1_BR1       (1<<1)
#define BSRR_BIT2_BR2       (1<<2)
#define BSRR_BIT3_BR3       (1<<3)
#define BSRR_BIT4_BR4       (1<<4)
#define BSRR_BIT5_BR5       (1<<5)
#define BSRR_BIT6_BR6       (1<<6)
#define BSRR_BIT7_BR7       (1<<7)
#define BSRR_BIT8_BR8       (1<<8)
#define BSRR_BIT9_BR9       (1<<9)
#define BSRR_BIT10_BR10     (1<<10)
#define BSRR_BIT11_BR11     (1<<11)
#define BSRR_BIT12_BR12     (1<<12)
#define BSRR_BIT13_BR13     (1<<13)
#define BSRR_BIT14_BR14     (1<<14)
#define BSRR_BIT15_BR15     (1<<15)


/*设置端口位*/
#define BSRR_BIT0_BS0       (1<<16)
#define BSRR_BIT1_BS1       (1<<17)
#define BSRR_BIT2_BS2       (1<<18)
#define BSRR_BIT3_BS3       (1<<19)
#define BSRR_BIT4_BS4       (1<<20)
#define BSRR_BIT5_BS5       (1<<21)
#define BSRR_BIT6_BS6       (1<<22)
#define BSRR_BIT7_BS7       (1<<23)
#define BSRR_BIT8_BS8       (1<<24)
#define BSRR_BIT9_BS9       (1<<25)
#define BSRR_BIT10_BS10     (1<<26)
#define BSRR_BIT11_BS11     (1<<27)
#define BSRR_BIT12_BS12     (1<<28)
#define BSRR_BIT13_BS13     (1<<29)
#define BSRR_BIT14_BS14     (1<<30)
#define BSRR_BIT15_BS15     (1<<31)

#define DRV8301_SCLK_Clr()   (GPIOF->BRR |=0x0002)
#define DRV8301_SCLK_Set() (GPIOF->BSRR |=0x0002)

#define DRV8301_MOSI_Clr()  GPIOF->BRR |=0x0008;
#define DRV8301_MOSI_Set() GPIOF->BSRR |=0x0008;

#define DRV8301_CS_Clr() GPIOF->BRR |=0x0001;
#define DRV8301_CS_Set() GPIOF->BSRR |=0x0001;

#define DRV8301_MISO_Clr()  GPIOF->BRR |=0x0004;
#define DRV8301_MISO_Set()  GPIOF->BSRR |=0x0004;

#define DRV8301_ENGATE_Clr() GPIOF->BRR |=0x0020;
#define DRV8301_ENGATE_Set() GPIOF->BSRR |=0x0020;

void drv8301_config(void);
uint8_t read_gpio(void);

#endif
#include "spi.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "debug.h"

static void drv8301_gpio_init(void);
static void drv8301_spi_write(uint8_t address,uint16_t data);
static uint16_t drv8301_spi_read(uint8_t address);
static void drv8301_init(void);

void drv8301_config(void){
    
   drv8301_gpio_init(); 
   drv8301_init(); 
}

static void drv8301_init(void){
   
  uint16_t drv8301_reg_read[4]={0};
  /*设置8301*/
  drv8301_spi_write(DRV8301_REG2,GATE_CURRENT_1_7_A|GATE_RESET_NOMAL|PWM_MODE_6_INPUTS|OCP_LATCH_SHUT_DOWN|OC_ADJ_SET_30);
  drv8301_spi_write(DRV8301_REG3,OCTW_OT_ONLY|GAIN_AMP_10|DC_CAL_CH1_CON|DC_CAL_CH2_CON|OC_TOFF_CYCLE);
  /*读取8301的ID*/
  drv8301_reg_read[0] = drv8301_spi_read(DRV8301_REG0);
  drv8301_reg_read[1] = drv8301_spi_read(DRV8301_REG1);
  drv8301_reg_read[2] = drv8301_spi_read(DRV8301_REG2);
  drv8301_reg_read[3] = drv8301_spi_read(DRV8301_REG3);   
      /*打印8301的ID*/
      printf("drv8301_reg_read[0]=%d\n\r",drv8301_reg_read[0]);
      printf("drv8301_reg_read[1]=%d\n\r",drv8301_reg_read[1]);
      printf("drv8301_reg_read[2]=%d\n\r",drv8301_reg_read[2]);
      printf("drv8301_reg_read[3]=%d\n\r",drv8301_reg_read[3]);  
    GPIOF->BSRR |=BSRR_BIT4_BS4;//设置DC_CAL 为低电平。复位8301完成 
}


static void drv8301_gpio_init(void){
    
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); 
     GPIOF->CRL=0;
    GPIOF->CRH=0;    
    /*CS_PIN:     10MHz  通用推挽输出*/
    GPIOF->CRL |= DRV8301_SPIx_CS_PIN_SET; 
    /*SCK_PIN:    50MHz  通用推挽输出*/
    GPIOF->CRL |= DRV8301_SPIx_SCK_PIN_SET;
    /*MOSI_PIN:   50MHz  通用推挽输出*/    
    GPIOF->CRL |= DRV8301_SPIx_MOSI_PIN_SET;
    /*MISO_PIN:   上拉/下拉输入模式*/
    GPIOF->CRL |= DRV8301_SPIx_MISO_PIN_SET;
    /*上拉/下拉输入模式*/
    GPIOF->CRH |= OCTW_PIN_SET;
    /*GATE_PIN:    2MHz  通用推挽输出*/
    GPIOF->CRL |= EN_GATE_PIN_SET; 
    /*上拉/下拉输入模式*/
    GPIOF->CRL |= FAULT_PIN_SET;
    
    GPIOF->CRL |=DC_CAL_PIN_SET;
    
    /*设置GPIO为低电平*/
    GPIOF->BSRR |=BSRR_BIT1_BS1+BSRR_BIT2_BS2+BSRR_BIT3_BS3+BSRR_BIT5_BS5;
    /* spi片选和EN_GATE信号为高,DC_CAL为高*/
    GPIOF->BSRR |= BSRR_BIT0_BR0+BSRR_BIT5_BR5+BSRR_BIT4_BR4;
}



uint8_t read_gpio(void){
   uint8_t temp=0;

   if(GPIOF->IDR&(1<<2)){
       temp=1;
   }else{
      temp=0;
   }       
    return temp;
}


static void drv8301_spi_write(uint8_t address,uint16_t data){

  uint16_t send_data = 0;
  uint8_t i;
  send_data = (uint16_t)(address&0x03);
  send_data <<= 11;
  send_data |= data; 
  DRV8301_CS_Clr();
   
    delay_us(800);
  for(i=0;i<16;i++)
  {
    DRV8301_SCLK_Set();
    if(send_data&0x8000)
    {
      DRV8301_MOSI_Set();
        delay_us(800);
    }
    else
    {
      DRV8301_MOSI_Clr();
        delay_us(800);
    }
    DRV8301_SCLK_Clr();
    send_data <<= 1;
    delay_us(800);
  } 
  DRV8301_SCLK_Clr();
  DRV8301_MOSI_Clr();
  DRV8301_CS_Set();

}


static uint16_t drv8301_spi_read(uint8_t address){
    
  uint16_t send_data = 0;
  uint16_t receive_data = 0;
  uint8_t i;
  send_data = (uint16_t)(address&0x03);
  send_data <<= 11;
  send_data |= 0x8000;
  DRV8301_CS_Clr();
    delay_us(800);
  for(i=0;i<16;i++){
    DRV8301_SCLK_Set();
    if(send_data&0x8000){
      DRV8301_MOSI_Set();
      delay_us(800);
    }
    else{
      DRV8301_MOSI_Clr();
      delay_us(800);
    }
    send_data <<= 1;
    DRV8301_SCLK_Clr();
    delay_us(800);
  }
  DRV8301_CS_Set();
  send_data = (uint16_t)(address&0x03);
  send_data <<= 11;
  send_data |= 0x8000;
  send_data = 0;
  DRV8301_CS_Clr();
  delay_us(800);
  for(i=0;i<16;i++) {
    DRV8301_SCLK_Set();
    if(send_data&0x8000) {
      DRV8301_MOSI_Set();
      delay_us(800);
    }
    else {
      DRV8301_MOSI_Clr();
      delay_us(800);
    }
    send_data <<= 1;
    receive_data <<= 1;
    DRV8301_SCLK_Clr();
    delay_us(800);
    if(read_gpio()==1) {
      receive_data |= 0x0001;
    }
  }
  DRV8301_CS_Set();
  DRV8301_SCLK_Clr();
  return receive_data;

}

打印结果
以10进制打印ID,如果数据不等于0,不等于0xFFFF,一般情况下是通讯正常。默认程序设置成功

4.Hall引脚初始化

#ifndef __TIM2_H
#define __TIM2_H

#include "misc.h"
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
#include "debug.h"
#include "tim1.h"

#define H_PWM  3000

    /*橙色=Hall_U=PD0  紫色=Hall_V=PD1 黄色=Hall_W=PD2 */
#define Hall_U_pin   GPIO_Pin_0
#define Hall_V_pin   GPIO_Pin_1
#define Hall_W_pin   GPIO_Pin_2



void hall_config(void);

#endif
#include "tim2.h"
#include "stm32f10x_tim.h"

static void NVIC_Configuration(void);
static void hall_gpio_init(void);

/*如果使用线性霍尔,这里初始化需要改成adc注入通道初始化,启动JEOC,通过timer1_cc4 触发*/

void hall_config(void){
    
    hall_gpio_init();
    NVIC_Configuration();
}

static void hall_gpio_init(void){
   
    GPIO_InitTypeDef  GPIO_InitStruct;
 	EXTI_InitTypeDef EXTI_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
    
    GPIO_InitStruct.GPIO_Pin=Hall_U_pin|Hall_V_pin|Hall_W_pin;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init( GPIOD, &GPIO_InitStruct);
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource0 );
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource1 );
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource2 );    
    
  	EXTI_InitStructure.EXTI_Line=EXTI_Line0 ;	//PD0
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 

  	EXTI_InitStructure.EXTI_Line=EXTI_Line1 ;	//PD1
  	EXTI_Init(&EXTI_InitStructure);	    
    
  	EXTI_InitStructure.EXTI_Line=EXTI_Line2 ;	//PD1
  	EXTI_Init(&EXTI_InitStructure);	    
}




static void NVIC_Configuration(void){
  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
    
  NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn ;    
  NVIC_Init(&NVIC_InitStructure);
    
  NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn ;    
  NVIC_Init(&NVIC_InitStructure);
}



 

void EXTI0_IRQHandler(void){
    
   TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);     
   TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Disable);     
   TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Enable);  
   TIM1->CCR1=0;
   TIM1->CCR2=0;
   TIM1->CCR3=H_PWM;  
     PWM_AL_H;    
     PWM_BL_L;
     PWM_CL_L;   
     
    EXTI_ClearITPendingBit(EXTI_Line0);
}

void EXTI1_IRQHandler(void){
  
    
   TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable); 
   TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Disable);     
   TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Disable);      
   TIM1->CCR1=H_PWM;
   TIM1->CCR2=0;
   TIM1->CCR3=0;  
     PWM_AL_L;    
     PWM_BL_H;
     PWM_CL_L;    
    
        
    
     EXTI_ClearITPendingBit(EXTI_Line1);   
}


void EXTI2_IRQHandler(void){

     
   TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);     
   TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Enable); 
   TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Disable);
   TIM1->CCR1=0;
   TIM1->CCR2=H_PWM;
   TIM1->CCR3=0;  
     PWM_AL_L;    
     PWM_BL_L;
     PWM_CL_H;     
       
        EXTI_ClearITPendingBit(EXTI_Line2);
}


4.PWM配置

#ifndef __tim1_H
#define __tim1_H
#include "spi.h"
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"


#define PWM_AL_H   GPIOB->BSRR|=BSRR_BIT13_BR13    
#define PWM_AL_L   GPIOB->BRR|=BSRR_BIT13_BR13  

#define PWM_BL_H   GPIOB->BSRR|=BSRR_BIT14_BR14   
#define PWM_BL_L   GPIOB->BRR|=BSRR_BIT14_BR14  

#define PWM_CL_H   GPIOB->BSRR|=BSRR_BIT15_BR15    
#define PWM_CL_L   GPIOB->BRR|=BSRR_BIT15_BR15   


void svpwm_config(void);
void pwm_stop(void);
void pwm_start(void);

#endif

#include "tim1.h"


static void svpwm_gpio_config(void);
static void svpwm_tim_config(void);


void svpwm_config(void){
    
    svpwm_gpio_config(); 
    svpwm_tim_config();
}

static void svpwm_gpio_config(void){
    
     /*GPIOA  GPIOB 时钟开启*/
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);   
	GPIO_InitTypeDef GPIO_InitStructure;	
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15|GPIO_Pin_13|GPIO_Pin_14;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //下管采用方波控制
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
    
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出  
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO         
    
}




static void svpwm_tim_config(void){
    
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStruct;
   TIM_BDTRInitTypeDef  TIM_BDTRInitStruct;	
    
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);   
    
    // 配置定时器基本参数
    TIM_TimeBaseStructure.TIM_Prescaler = 0;          // 时钟预分频
    TIM_TimeBaseStructure.TIM_Period = 3200;          // 计数周期
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;   // 向上计数模式
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       // 时钟分频
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;  // 重复计数器
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);    
    
   
   TIM_OCInitStruct.TIM_OCIdleState= TIM_OCIdleState_Reset;
   TIM_OCInitStruct.TIM_OCMode  =  TIM_OCMode_PWM1;
   TIM_OCInitStruct.TIM_OCNIdleState=TIM_OCNIdleState_Reset;
   TIM_OCInitStruct.TIM_OCNPolarity=TIM_OCNPolarity_High;
   TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
   TIM_OCInitStruct.TIM_OutputNState= TIM_OutputNState_Disable;//互补模式关闭,下管采用程序控制
   TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;

   TIM_OC1Init(TIM1,&TIM_OCInitStruct); 
   TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  

   
   TIM_OC2Init(TIM1,&TIM_OCInitStruct); 
   TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  

   
   TIM_OC3Init(TIM1,&TIM_OCInitStruct);    
   TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);  

   TIM1->CCR1=0;
   TIM1->CCR2=0;
   TIM1->CCR3=0;  

    TIM_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Disable;
    TIM_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Disable;
    TIM_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
    TIM_BDTRInitStruct.TIM_DeadTime = 0;     // 这里设置无意义,可以通过程序控制,或者设置8301的死区时间
    TIM_BDTRInitStruct.TIM_Break = TIM_Break_Enable;
    TIM_BDTRInitStruct.TIM_BreakPolarity = TIM_BreakPolarity_Low;
    TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;//关闭自动输出
    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStruct);
    
    // 使能定时器
    TIM_Cmd(TIM1, ENABLE);
    
   TIM_CtrlPWMOutputs(TIM1, ENABLE);    
    
}

void pwm_start(void){
    
              TIM1->CCER  |= (1<<0);
              TIM1->CCER  |= (1<<4);
              TIM1->CCER  |= (1<<8);      

              TIM1->CCER  |=(1<<2);
              TIM1->CCER  |=(1<<6);
              TIM1->CCER  |=(1<<10);   
   
}

void pwm_stop(void){
    
              TIM1->CCER  |= (0<<0);
              TIM1->CCER  |= (0<<4);
              TIM1->CCER  |= (0<<8);      

              TIM1->CCER  |=(0<<2);
              TIM1->CCER  |=(0<<6);
              TIM1->CCER  |=(0<<10);   
    
}

四、转动效果

1.验证程序

写入代码,用手转动电机,查看波形是否与设置的相匹配。因为手动转动电机,和转动起来的波形是有差距的。主要体现在时基上。手的转动速度无法达到自动转起来的那么均匀与平滑,可能在某一个霍尔区间停留的时间较长
手转电机波形
Hall_W :转子停留的位置,未能触发gpio中断,为无效位置。
Hall_U:转动的第一个信号对应的起始A1 指结束A2,对应上管为HC,下管LA。
Hall_V:转动的第二个信号对应的起始A2 指结束B1,对应上管为HA,下管LB。
Hall_W:转动的第三个信号对应的起始B1 指结束B2,对应上管为HB,下管LC。

2.转动的波形与图片

转动起来,Hall的波形
转动起来霍尔的波形
转动电流
请添加图片描述
转动效果图片
请添加图片描述
相位波形
请添加图片描述
下管波形
请添加图片描述

上管波形
请添加图片描述


若有不对的,请指正。大家相互交流,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值