📄 mc_drv.c
字号:
/**
* @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 + -