📄 mc_drv.c
字号:
switch(hall_state)
{
case 2 : Num_turn--;break;
case 1 : Num_turn++;break;
default: break;
}
hall_state = 3;
}
/**
* @brief Set the duty cycle values in the PSC according to the value calculate by the regulation loop
*/
void mc_duty_cycle(U8 level)
{
U8 duty;
duty = level;
PCNF0 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL0)|(1<<POP0); /* set plock */
PCNF1 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL1)|(1<<POP1); /* set plock */
PCNF2 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL2)|(1<<POP2); /* set plock */
// Duty = 0 => Duty Cycle 0%
// Duty = 255 => Duty Cycle 100%
// Set the duty cycle for PSCn0
OCR0SAH = 0;
OCR0SAL = 255 - duty;
OCR1SAH = 0;
OCR1SAL = 255 - duty;
OCR2SAH = 0;
OCR2SAL = 255 - duty;
// Set the duty cycle for PSCn1 according to the PWM strategy
#ifdef HIGH_AND_LOW_PWM
// apply PWM on high side and low side switches
OCR0SBH = 0;
OCR0SBL = 255 - duty ;
OCR1SBH = 0;
OCR1SBL = 255 - duty ;
OCR2SBH = 0;
OCR2SBL = 255 - duty ;
#else
// PWM is only applied on high side switches
// 100% duty cycle on low side switches
OCR0SBH = 0;
OCR0SBL = 2;
OCR1SBH = 0;
OCR1SBL = 2;
OCR2SBH = 0;
OCR2SBL = 2;
#endif
Disable_interrupt();
PCNF0 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL0)|(1<<POP0); /* release plock */
PCNF1 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL1)|(1<<POP1); /* release plock */
PCNF2 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL2)|(1<<POP2); /* release plock */
Enable_interrupt();
}
/**
* @brief Set the Switching Commutation value on outputs
* according to sensor or estimation position
*
* @param position (1 to 6) and direction (FORWARD or BACKWARD)
*/
void mc_switch_commutation(U8 position)
{
// get the motor direction to commute the right switches.
char direction = mci_get_motor_direction();
// Switches are commuted only if the user start the motor and
// the speed consign is different from 0.
if ((mci_motor_is_running()) && (mci_get_motor_speed()!=0))
{
mc_duty_cycle(mc_get_Duty_Cycle());
switch(position)
{
// cases according to rotor position
case HS_001: if (direction==CCW) {Set_Q3Q2();}
else {Set_Q5Q2();}
break;
case HS_101: if (direction==CCW) {Set_Q5Q2();}
else {Set_Q5Q4();}
break;
case HS_100: if (direction==CCW) {Set_Q5Q4();}
else {Set_Q1Q4();}
break;
case HS_110: if (direction==CCW) {Set_Q1Q4();}
else {Set_Q1Q6();}
break;
case HS_010: if (direction==CCW) {Set_Q1Q6();}
else {Set_Q3Q6();}
break;
case HS_011: if (direction==CCW) {Set_Q3Q6();}
else {Set_Q3Q2();}
break;
default : break;
}
}
else
{
Set_none(); // all switches are switched OFF
}
}
/********************************************************************/
/********************************************************************/
/* TIMER 1 : Sampling time configuration */
/********************************************************************/
/********************************************************************/
/**
* @brief Timer 1 Configuration
* Use to generate a 250us activation for main loop
* @pre None
* @post An interrupt all 250us
*/
void mc_config_sampling_period(void)
{
TCCR1A = 0; /* Normal port operation + Mode CTC */
TCCR1B = 1<<WGM12 | 1<<CS11 | 1<<CS10 ; /* Mode CTC + prescaler 64 */
TCCR1C = 0;
OCR1AH = 0;
OCR1AL = 7; /* 31.25 礢 */
TIMSK1=(1<<OCIE1A); /* Output compare B Match interrupt Enable */
}
/**
* @brief Timer 1 interrupt
* Timer 1 generates a periodic interrupt for motor and main loop
* @pre configuration of timer 1 registers
* @post g_tick is used in main.c for regulation loop
*/
#pragma vector = TIMER1_COMPA_vect
__interrupt void timer1_periodic_interrupt(void)
{
count_sub_tick --;
if (count_sub_tick == 0)
{
g_tick = TRUE;
count_sub_tick = 8;
}
if (delay_armed == TRUE)
{
delay_30d --;
if (delay_30d == 0)
{
delay_armed = FALSE;
delay_mask = MASK_DEMAG;
Disable_comparator0_interrupt();
Disable_comparator1_interrupt();
Disable_comparator2_interrupt();
mc_switch_commutation(HALL_SENSOR_VALUE());
}
}
if (delay_mask != 0)
{
delay_mask --;
if (delay_mask == 0)
{
ACSR = (1<<AC2IF)|(1<<AC1IF)|(1<<AC0IF);
Enable_comparator0_interrupt();
Enable_comparator1_interrupt();
Enable_comparator2_interrupt();
}
}
}
/********************************************************************/
/********************************************************************/
/* TIMER 0 : Estimation speed */
/********************************************************************/
/********************************************************************/
/**
* @brief Timer 0 Configuration
* The timer 0 is used to generate an IT when an overflow occurs
* @pre None
* @post Timer0 initialized.
*/
void mc_config_time_estimation_speed(void)
{
TCCR0A = 0;
TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00); // 64 prescaler (8us)
TIMSK0 = (1<<TOIE0);
}
/**
* @brief Timer0 Overflow for speed measurement
* @pre configuration of timer 0
* @post generate an overflow when the motor turns too slowly
*/
#pragma vector = TIMER0_OVF_vect
__interrupt void ovfl_timer(void)
{
TCNT0=0x00;
ovf_timer++;
// if they are no commutation after 125 ms
// 125 ms = (61<<8) * 8us
if(ovf_timer >= 100)
{
ovf_timer = 0;
mci_store_measured_speed(0);
}
}
/**
* @brief estimation speed
* @pre configuration of timer 0 and define or not AVERAGE_SPEED_MEASURE in config_motor.h
* @post new value for real speed
*/
void mc_estimation_speed(void)
{
U16 timer_value;
U32 new_measured_speed;
if (g_mc_read_enable==OK)
{
// Two 8 bits variables are use to simulate a 16 bits timers
timer_value = (ovf_timer<<8) + TCNT0;
/* compute delay for 30 degres */
comp_delay_30d = (timer_value / 94) - FILTER_DELAY;
/* apply a saturation */
if (comp_delay_30d < (S16)MIN_DELAY) comp_delay_30d = MIN_DELAY;
else if (comp_delay_30d > (S16)MAX_DELAY) comp_delay_30d = MAX_DELAY;
if (timer_value == 0) {timer_value += 1 ;} // warning DIV by 0
new_measured_speed = K_SPEED / timer_value;
if(new_measured_speed > 255) new_measured_speed = 255; // Variable saturation
// To avoid noise an average is realized on 16 samples
average += new_measured_speed;
if(count >= 16)
{
count = 1;
mci_store_measured_speed(average >> 4);
average = 0;
}
else count++;
// Reset Timer 0 register and variables
TCNT0=0x00;
ovf_timer = 0;
g_mc_read_enable=KO;
}
}
/********************************************************************/
/********************************************************************/
/* ADC use for current measure and potentiometer... */
/********************************************************************/
/********************************************************************/
/**
* @brief Launch the sampling procedure to get current value
* @pre Amplifier and IT initialization
* @post Set the End Of Conversion flag
*/
#pragma vector = ADC_vect
__interrupt void ADC_EOC(void)
{
if(State == CONV_CURRENT) mci_store_potentiometer_value(Adc_get_8_bits_result());
if(State == CONV_POT) mci_store_measured_current(Adc_get_10_bits_result());
ADC_State = FREE;
}
/**
* @brief Launch the scheduler for the ADC
* @pre none
* @post Get Channel 6 and 12 results for Potentiometer and current values.
*/
void mc_ADC_Scheduler(void)
{
switch(State)
{
case CONV_INIT :
init_adc();
init_amp1();
ADC_State = FREE;
State = CONV_POT;
break;
case CONV_POT :
if(ADC_State == FREE)
{
ADC_State = BUSY;
State= CONV_CURRENT;
Left_adjust_adc_result();
Start_conv_channel(6);
}
break;
case CONV_CURRENT :
if(ADC_State == FREE)
{
ADC_State = BUSY;
State = CONV_POT;
Right_adjust_adc_result();
Start_amplified_conv_channel(12);
// Start_conv_channel(9);
}
break;
}
}
/********************************************************************/
/********************************************************************/
/* Over Current Detection */
/********************************************************************/
/********************************************************************/
/**
* @brief Set the Over Current threshold
* @pre DAC initialization
* @post the Over Current threshold is set.
*/
void mc_set_Over_Current(U8 Level)
{
Set_dac_8_bits(Level);
}
/********************************************************************/
/********************************************************************/
/* Number of turns calculation */
/********************************************************************/
/********************************************************************/
/**
* @brief Get the number of rotor rotation
* @pre none
* @post Get the 32bits signed number of turns
*/
S32 mc_get_Num_Turn()
{
return Num_turn;
}
/**
* @brief Reset the number of rotor rotation
* @pre none
* @post Number of turns = 0
*/
void mc_reset_Num_Turn()
{
Num_turn = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -