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

📄 mc_drv.c

📁 DSP三相交流同步电机矢量控制(C程序_经典著作)
💻 C
📖 第 1 页 / 共 2 页
字号:
  }
  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 + -