⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mc_drv.c

📁 无刷电机驱动原理
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
* @file mc_drv.c
*
* Copyright (c) 2005 Atmel.
*
* @brief This module provides the hardware level of BLDC sensorless application.\n
* This module contains initialization and configuration
* It depends on hardware of components
* @version 1.0 (CVS revision : $Revision: 1.4 $)
* @date $Date: 2006/07/12 12:58:27 $
* @author $Author: raubree $
*****************************************************************************/
#include "config.h"
#include "config_motor.h"

#include "mc_drv.h"
#include "mc_interface.h"
#include "mc_control.h"

#include "adc\adc_drv.h"
#include "dac\dac_drv.h"
#include "amplifier\amplifier_drv.h"
#include "pll\pll_drv.h"
#include "comparator\comparator_drv.h"

static U8 count = 1;     //! variable "count" is use for calculate the "average" speed on 'n' samples
static U16 average = 0;  //! average of speed
static U8 ovf_timer = 0; //! variable "ovf_timer" is use to simulate a 16 bits timer with 8 bits timer

static Bool g_mc_read_enable = FALSE;  // the speed can be read
Bool g_tick = FALSE;             //!< Use for control the sampling period value

static Bool delay_armed = FALSE;
static U8 delay_30d = 0;
volatile S16 comp_delay_30d = MIN_DELAY;
static U8 count_sub_tick = 8;
static U8 delay_mask = 0;

static S32 Num_turn = 0; //! Used to count the number of motor revolutions
static U8 hall_state = 0;

static char State = CONV_INIT; //! State of the ADC scheduler
static char ADC_State = FREE;  //! ADC State : running = BUSY not running = FREE


/**********************************************************************************/
/**********************************************************************************/
/*               Hardware Initialization                                          */
/**********************************************************************************/
/**********************************************************************************/

/**
* @brief init hardware (peripherals)
* @pre set all functions mc_init_port(), mc_init_pwm()...
* @post initialization of hardware
*/
void mc_init_HW(void)
{
  mc_init_port();
  mc_init_IT();

  // Be careful : initialize DAC and Over_Current before PWM.
  init_dac();
  mc_set_Over_Current(200); // 5 => 1A ; 8 => 40A
  mc_init_pwm();

  mc_config_time_estimation_speed();
  mc_config_sampling_period();

  init_comparator0();
  init_comparator1();
  init_comparator2();
}

/**
* @brief init SW
* @pre none
* @post initialization of software
*/
void mc_init_SW(void)
{
  Enable_interrupt();
}

/**
* @brief Initialization of IO PORTS for AT90PWM3B
* @pre none
* @post initialization of I/O Ports
*/
void mc_init_port(void)
{
  // Output Pin configuration
  // PD0 => H_A     PB7 => L_A
  // PC0 => H_B     PB6 => L_B
  // PB0 => H_C     PB1 => L_C

  //Do not modify PSCOUT Configuration
  // PORT B :
  DDRB = (1<<DDB7)|(1<<DDB6)|(1<<DDB3)|(1<<DDB1)|(1<<DDB0);
  // PORT C :
  DDRC = (1<<DDC0);
  // PORT D :
  DDRD = (1<<DDD0);


  // DDnx = 0:Input 1:Output    (n = B,C,D,E ; x = 0,1,2,3,4,5,6,7)
  // PB3 => EXT1                        PB4 => EXT2
  // PC1 => EXT3                        PC2 => EXT4
  // PB5 => EXT5/POT                    PE1 => EXT6
  // PD3 => EXT7/MOSI/LIN_TxD/TxD       PD4 => EXT8/MISO/LIN_RxD/RxD
  // PE0 => EXT9/NRES                   PD2 => EXT10/MISO

  // Modify DDnx according to your hardware implementation
  // PORT B :
  DDRB |= (0<<DDB5)|(1<<DDB4)|(0<<DDB3);
  // PORT C :
  DDRC |= (0<<DDC2)|(0<<DDC1);
    // PORT D :
  DDRD |= (0<<DDD4)|(0<<DDD3)|(0<<DDD2); // Becareful if using the UART interface or JTAGE ICE mkII.
  // PORT E :
  DDRE |= (1<<DDE2)|(0<<DDE1)|(0<<DDE0); // Becareful PE0 is you by JTAGE ICE mkII.


  // Warning Output Low for MOSFET Drivers
  PORTB &= ~(1<<PORTB7 | 1<<PORTB6 | 1<<PORTB3 |1<<PORTB1 | 1<<PORTB0);
  PORTC &= ~(1<<PORTC0);
  PORTD &= ~(1<<PORTD0);

  // pull up activation
  PORTC |= (1<<PORTC6)|(1<<PORTC1);
  PORTD |= (1<<PORTD7)|(1<<PORTD5)|(1<<PORTD1);

  // Disable Digital Input for amplifier1
  // Digitals Inputs for comparators are not disable.
  DIDR0 = (0<<ADC6D)|(0<<ADC3D)|(0<<ADC2D);
  DIDR1 = (0<<ACMP0D)|(0<<ACMP1D)|(1<<AMP1PD)|(1<<AMP1ND);
}

/**
* @brief Initialization of PWM generators (PSC) for AT90PWM3B
* @pre none
* @post initialization of PSC
*/
void mc_init_pwm()
{
  Start_pll_32_mega();
  Wait_pll_ready();

  // In Center Aligned Mode :
  // => PSCx_Init(Period_Half, Dutyx0_Half, Synchro, Dutyx1_Half)
#ifdef MCU_REV_B
  PSC0_Init(255,0,255,0);
  PSC1_Init(255,0,255,0);
  PSC2_Init(255,0,255,0);
#else
  PSC0_Init(255,0,1,0);
  PSC1_Init(255,0,1,0);
  PSC2_Init(255,0,1,0);
#endif

}

/**
* @brief Initialization of AT90PWM3B External Interrupts
* @pre none
* @post External Interrupts (INT0, INT1, INT2, INT3) initialized
*/
void mc_init_IT(void)
{
  EICRA =(0<<ISC21)|(1<<ISC20)|(0<<ISC11)|(1<<ISC10)|(0<<ISC01)|(1<<ISC00);
  EIFR = (1<<INTF2)|(1<<INTF1)|(1<<INTF0); // clear possible IT due to config
  EIMSK=(1<<INT2)|(1<<INT1)|(1<<INT0);
}

// PSC initialization depend on the PSC mode
//  0- One ramp Mode
//  1- Two ramp Mode
//  2- Four ramp Mode
//  3- Center Aligned Mode

/**
* @brief Initialization of PWM generator PSC0
*/
void PSC0_Init ( unsigned int OCRnRB,
                 unsigned int OCRnSB,
                 unsigned int OCRnRA,
		 unsigned int OCRnSA)
{
  OCR0SAH = HIGH(OCRnSA);
  OCR0SAL = LOW(OCRnSA);
  OCR0RAH = HIGH(OCRnRA);
  OCR0RAL = LOW(OCRnRA);
  OCR0SBH = HIGH(OCRnSB);
  OCR0SBL = LOW(OCRnSB);
  OCR0RBH = HIGH(OCRnRB);
  OCR0RBL = LOW(OCRnRB);

  PCNF0 =  RAMP_MODE_NUMBER | (1<<PCLKSEL0) | OUTPUT_ACTIVE_HIGH ;
  /* use PSC 0  Input A as Fault Input */
  PFRC0A = (1<<PELEV0A)|(1<<PFLTE0A)|(0<<PRFM0A3)|(1<<PRFM0A2)|(1<<PRFM0A1)|(1<<PRFM0A0);
//  PFRC0A = 0;
  PFRC0B = 0;
  PSOC0 = (1<<PSYNC00); //Send signal on match with OCRnSA (during counting up of PSC)
  PCTL0 = (0<<PAOC0A)|(1<<PARUN0)|PRESC_DIV_BY_4; /* AUTORUN !! */
}

/**
* @brief Initialization of PWM generator PSC1
*/
void PSC1_Init ( unsigned int OCRnRB,
                 unsigned int OCRnSB,
                 unsigned int OCRnRA,
		 unsigned int OCRnSA)
{
  OCR1SAH = HIGH(OCRnSA);
  OCR1SAL = LOW(OCRnSA);
  OCR1RAH = HIGH(OCRnRA);
  OCR1RAL = LOW(OCRnRA);
  OCR1SBH = HIGH(OCRnSB);
  OCR1SBL = LOW(OCRnSB);
  OCR1RBH = HIGH(OCRnRB);
  OCR1RBL = LOW(OCRnRB);

  PCNF1 =  RAMP_MODE_NUMBER | (1<<PCLKSEL1) | OUTPUT_ACTIVE_HIGH ;
  PFRC1A = 0;
  PFRC1B = 0;
  PCTL1 = (0<<PAOC1A)|(1<<PARUN1)|PRESC_DIV_BY_4; /* AUTORUN !! */
}


/**
* @brief Initialization of PWM generator PSC2
*/
void PSC2_Init ( unsigned int OCRnRB,
                 unsigned int OCRnSB,
                 unsigned int OCRnRA,
		 unsigned int OCRnSA)
{
  OCR2SAH = HIGH(OCRnSA);
  OCR2SAL = LOW(OCRnSA);
  OCR2RAH = HIGH(OCRnRA);
  OCR2RAL = LOW(OCRnRA);
  OCR2SBH = HIGH(OCRnSB);
  OCR2SBL = LOW(OCRnSB);
  OCR2RBH = HIGH(OCRnRB);
  OCR2RBL = LOW(OCRnRB);

  PCNF2 =  RAMP_MODE_NUMBER | (1<<PCLKSEL2) | OUTPUT_ACTIVE_HIGH ;
  PFRC2A = 0;
  PFRC2B = 0;
//  PCTL2 = (0<<PAOC2A)|(1<<PRUN2)|PRESC_DIV_BY_4; /* RUN !! */
}

/**********************************************************************************/
/*                   PSC Stop                                                     */
/**********************************************************************************/
/*  This function stops the PSCs :                                                */
/**********************************************************************************/
void PSC_Stop(void)
{
   Set_none();
   PCTL2 = (1<<PCCYC2);
}

/**********************************************************************************/
/*                   PSC Run                                                     */
/**********************************************************************************/
/*  This function starts the PSCs :                                               */
/**********************************************************************************/
void PSC_Run(void)
{
  PCTL2 = (0<<PAOC2A)|(1<<PRUN2)|PRESC_DIV_BY_4; /* RUN !! */
}

/**********************************************************************************/
/**********************************************************************************/
/*         All functions for motor's phases commutation                           */
/**********************************************************************************/
/**********************************************************************************/

/**
* @brief Get the value of hall sensors (1 to 6)
* @param return an unsigned char
*  value of hall sensor
* @pre configuration of port PB and PD
* @post new value of position
*/
U8 mc_get_hall(void)
{
  return HALL_SENSOR_VALUE(); /* sensor */
//  return ((~HALL_SENSOR_VALUE())&0x07); /* sensorless */
}

/**
 * @brief External interruption
 *                 Sensor (A) mode toggle
 * @pre configuration of external interruption (initialization)
 * @post New value in Hall variable
 */
#pragma vector = HALL_A()
__interrupt void mc_hall_a(void)
{

  delay_armed = TRUE;
  delay_30d = comp_delay_30d;

  //estimation speed on rising edge of Hall_A
#ifdef USE_INTERNAL_COMPARATORS
  if (ACSR&(1<<AC0O))
#else
  if (PIND&(1<<PORTD7))
#endif
  {
    mc_estimation_speed();
    g_mc_read_enable=FALSE; // Wait 1 period
  }
  else
  {
    g_mc_read_enable=TRUE;
  }


  switch(hall_state)
  {
  case 2 : Num_turn++;break;
  case 3 : Num_turn--;break;
  default: break;
  }
  hall_state = 1;
}

/**
 * @brief External interruption
 *                 Hall Sensor (B) mode toggle
 * @pre configuration of external interruption (initialization)
 * @post New value in Hall variable
 */
#pragma vector = HALL_B()
__interrupt void mc_hall_b(void)
{

  delay_armed = TRUE;
  delay_30d = comp_delay_30d;

  switch(hall_state)
  {
  case 1 : Num_turn--;break;
  case 3 : Num_turn++;break;
  default: break;
  }
  hall_state = 2;
}

 /**
 * @brief External interruption
 *                 Hall Sensor (C) mode toggle
 * @pre configuration of external interruption (initialization)
 * @post New value in Hall variable
 */
#pragma vector = HALL_C()
__interrupt void mc_hall_c(void)
{

  delay_armed = TRUE;
  delay_30d = comp_delay_30d;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -