📄 mc_drv.c
字号:
}
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 = duty;
OCR1SAH = 0;
OCR1SAL = duty;
OCR2SAH = 0;
OCR2SAL = 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 = duty;
OCR1SBH = 0;
OCR1SBL = duty;
OCR2SBH = 0;
OCR2SBL = duty;
#else
// PWM is only applied on high side switches
// 100% duty cycle on low side switches
OCR0SBH = 0;
OCR0SBL = 255;
OCR1SBH = 0;
OCR1SBL = 255;
OCR2SBH = 0;
OCR2SBL = 255;
#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 = mc_get_motor_direction();
// Switches are commuted only if the user start the motor and
// the speed consign is different from 0.
if ((mc_motor_is_running()) && (mc_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_Q1Q6();}
else {Set_Q5Q2();}
break;
case HS_101: if (direction==CCW) {Set_Q3Q6();}
else {Set_Q5Q4();}
break;
case HS_100: if (direction==CCW) {Set_Q3Q2();}
else {Set_Q1Q4();}
break;
case HS_110: if (direction==CCW) {Set_Q5Q2();}
else {Set_Q1Q6();}
break;
case HS_010: if (direction==CCW) {Set_Q5Q4();}
else {Set_Q3Q6();}
break;
case HS_011: if (direction==CCW) {Set_Q1Q4();}
else {Set_Q3Q2();}
break;
default : break;
}
}
else
{
Set_none(); // all switches are switched OFF
}
}
/******************************************************************************************************************************/
/******************************************************************************************************************************/
/* Sampling time configuration */
/******************************************************************************************************************************/
/******************************************************************************************************************************/
/**
* @brief timer 1 Configuration
* Use to generate a 250us activation for sampling speed regulation
* @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 = 31;
TIMSK1=(1<<OCIE1A); // Output compare B Match interrupt Enable
}
/**
* @brief Launch the regulation loop (see main.c) .
* @pre configuration of timer 1 registers
* @post g_tic use in main.c for regulation loop
*/
#pragma vector = TIMER1_COMPA_vect
__interrupt void launch_sampling_period(void)
{
g_tic = TRUE;
}
/******************************************************************************************************************************/
/******************************************************************************************************************************/
/* 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;
mc_set_motor_measured_speed(0);
//if the motor was turning and no stop order
// was given, motor run automatically.
if(mc_motor_is_running())mc_motor_run();
}
}
/**
* @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;
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
#ifdef AVERAGE_SPEED_MEASURE
// To avoid noise an average is realized on 8 samples
average += new_measured_speed;
if(count >= n_SAMPLE)
{
count = 1;
mc_set_motor_measured_speed(average >> 3);
average = 0;
}
else count++;
#else
// else get the real speed
mc_set_motor_measured_speed(new_measured_speed);
#endif
// 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) mc_set_potentiometer_value(Adc_get_8_bits_result());
if(State == CONV_POT) mc_set_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);
}
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 + -