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

📄 main.c

📁 ATtiny261 461 861 这份资料介绍了执行Attiny261 461 861微控制器系列正弦波驱动三相无刷直流电动机霍尔传感器。
💻 C
📖 第 1 页 / 共 3 页
字号:
    //Change PWM pins to output again to allow PWM control.
  EnablePWMOutputs();
}


/*! \brief Configures Timer/Counter1 in braking mode.
 *
 *  This function configures Timer/counter1 in sinusoidal mode in a safe way
 *  way by disabling all output before any configuration bits are changed.
 *  After running this function, Timer/counter1 will be in phase and frequency
 *  correct mode with a duty cycle of 0 on all three phases, resulting in
 *  low side braking.
 */
#if (TURN_MODE == TURN_MODE_BRAKE)
#pragma inline = forced
static void TimerSetModeBrake(void)
{
  //Set PWM pins to input (Hi-Z) while changing modes.
  DisablePWMOutputs();

  //Set Timer/counter1 in phase and frequency correct mode.
  TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << COM1B1) | (1 << COM1B0) | (1 << PWM1A) | (1 << PWM1B);
  TCCR1C =  (0 << COM1A1S) | (1 << COM1A0S) | (0 << COM1B1S) | (1 << COM1B0S) | (0 << COM1D1) | (1 << COM1D0) | (1 << PWM1D);
  TCCR1D &= ~((1 << WGM11) | (1 << WGM10));
  TCCR1D |= (0 << WGM11) | (1 << WGM10);

  //All output duty cycles at 0 creates a braking force. (Low side braking)
  TC1_SET_ALL_COMPARE_VALUES(0x0000);

  fastFlags.driveWaveform = WAVEFORM_BRAKING;

  //Change PWM pins to output again to allow PWM control.
  EnablePWMOutputs();
}
#endif


/*! \brief Sets the duty cycle when operating in block commutation mode.
 *
 *  Calling this function sets the duty cycle when operating in block
 *  commutation mode (PWM6 mode). Do not use this function when Timer/counter1
 *  is not operated in PWM6 mode.
 *
 *  Note that the argument specifies the output compare value, not the duty
 *  cycle in percent. The duty cycle in percent can be calculated as
 *  duty = (compareValue / PWM_TOP_VALUE) * 100.
 *
 *  \param compareValue Ouput compare value.
 */
#pragma inline = forced
static void BlockCommutationSetDuty(const uint16_t compareValue)
{
  TC1_PWM6_SET_DUTY_CYCLE(compareValue);
}


/*! \brief Returns the desired direction.
 *
 *  This function returns the current desired direction.
 *  \note The direction input is not read at this time. A
 *  separate pin change interrupt is responsible for reading
 *  the input.
 *
 *  \retval DIRECTION_FORWARD Forward direction is requested.
 *  \retval DIRECTION_REVERSE Reverse direction is requested.
 */
#pragma inline = forced
static uint8_t GetDesiredDirection(void)
{
  return (uint8_t)fastFlags.desiredDirection;
}


/*! \brief Performs block commutation according to running direction and hall sensor input
 *
 *  This function performs a block commutation according to the
 *  specified running direction and hall sensor input.
 *
 *  \note Do not use this function while the timers are configured
 *  for sine wave driving.
 *
 *  \param direction Direction of rotation.
 *  \param hall Hall sensor value at the same form as returned by GetHall().
 */
#pragma inline = forced
static void BlockCommutate(const uint8_t direction, const uint8_t hall)
{
  if (direction == DIRECTION_FORWARD)
  {
    TCCR1E = blockCommutationTableForward[hall];
  }
  else
  {
    TCCR1E = blockCommutationTableReverse[hall];
  }
}


/*! \brief Reads the hall sensor inputs.
 *
 *  This function reads the hall sensor inputs and converts it to
 *  a number from 1 to 6 by combining the hall sensors as bits: H3|H2|H1.
 *
 *  \note It is possible to change the physical placement of hall sensor
 *  inputs, but the recommended configuration is the one used in this
 *  example, since it requires very little code to decode the hall values.
 *
 *  \return The decoded hall sensor value.
 *
 *  \retval 0 Illegal hall state. Possible hardware error.
 *  \retval 1-6 Legal hall sensor values.
 *  \retval 7 Illegal hall state. Possible hardware error.
 */
#pragma inline = forced
static uint8_t GetHall(void)
{
  uint8_t hall;

  hall = (PINA) & ((1 << H3_PIN) | (1 << H2_PIN) | (1 << H1_PIN));
  hall >>= H1_PIN;
  return hall;
}


/*! \brief Updates global desired direction flag.
 *
 *  Running this function triggers a reading of the direction
 *  input pin. The desiredDirection flag is set accordingly.
 */
#pragma inline = forced
static void DesiredDirectionUpdate(void)
{
  if ( (PINA & (1 << DIRECTION_PIN)) != 0 )
  {
    fastFlags.desiredDirection = DIRECTION_REVERSE;
  }
  else
  {
    fastFlags.desiredDirection = DIRECTION_FORWARD;
  }
}


/*! \brief Updates global actual direction flag based on the two latest hall values.
 *
 *  Calling this function with the last two hall sensor values as
 *  parameters triggers an update of the global actualDirection flag.
 *
 *  \param lastHall The last hall value.
 *  \param newHall The current hall value.
 */
#pragma inline = forced
static void ActualDirectionUpdate(uint8_t lastHall, const uint8_t newHall)
{
  //Make sure that lastHall is within bounds of table. If not, set to an
  //illegal hall value, but legal table index.
  if (lastHall > 7)
  {
    lastHall = 0;
  }
  if (expectedHallSequenceForward[lastHall] == newHall)
  {
    fastFlags.actualDirection = DIRECTION_FORWARD;
  }
  else if (expectedHallSequenceReverse[lastHall] == newHall)
  {
   fastFlags.actualDirection = DIRECTION_REVERSE;
  }
  else
  {
    PMSMflags_t tempFlags = fastFlags;
    tempFlags.actualDirection = DIRECTION_UNKNOWN;
    tempFlags.motorSynchronized = FALSE;
    fastFlags = tempFlags;
  }
}


/*! \brief Calculates step size for sine table iteration.
 *
 *  This function calculates the step size to be used for sine
 *  table iteration, based on the number of 'ticks' used for each electrical
 *  revolution.
 *
 *  \param ticks The number of ticks in one electrical revolution.
 *
 *  \return The step size in 8.8 format to be used for sine table iteration.
 */
#pragma inline = forced
static uint16_t SineTableIncrementCalculate(const uint16_t ticks)
{
  return (uint16_t)(((SINE_TABLE_LENGTH / 6) << 8) / ticks);
}


/*! \brief Adjusts the sine table index according to the current increment.
 *
 *  This function increases the sine table index with the given increment
 *  The index is then adjusted to be within the table length.
 *
 *  \param increment The increment (in 8.8 format) added to the sine table index.
 */
#pragma inline = forced
static void AdjustSineTableIndex(const uint16_t increment)
{
  sineTableIndex += increment;

  // If the table index is out of bounds, wrap the index around the table end
  // to continue from the beginning. Also wrap the next sector start index.
  if ((sineTableIndex >> 8) >= SINE_TABLE_LENGTH)
  {
    sineTableIndex -= (SINE_TABLE_LENGTH << 8);
    sineTableNextSectorStart -= SINE_TABLE_LENGTH;
  }

  //Make copy of sineNextSectorStart to specify order of volatile access.
  uint8_t nextSectorStart = sineTableNextSectorStart;
  if ((sineTableIndex >> 8) > nextSectorStart)
  {
    sineTableIndex = (nextSectorStart << 8);
  }
}


/*! \brief Sets the advance commutation.
 *
 *  This function sets the advance commutation to be used during sine
 *  wave operation. An increase of one equals 1.875 degrees.
 *
 *  \note There is no checking of the advanceCommutation input parameter, but this
 *  should not be set to a value above 40 to avoid overflow in the sine table
 *  index.
 *
 *  \param advanceCommutation The advance commutation. (1 equals 1.875 degrees)
 */
#pragma inline = forced
static void SetAdvanceCommutation(const uint8_t advanceCommutation)
{
  advanceCommutationSteps = advanceCommutation;
}


/*! \brief Enable PWM outputs by setting the port direction to output.
 *
 *  Enables PWM outputs by setting the port direction to output for the PWM pins.
 */
#pragma inline = forced
static void EnablePWMOutputs(void)
{
  DDRB |= PWM_PIN_MASK_PORTB;
}


/*! \brief Disable PWM outputs by setting the port direction to input.
 *
 *  Disables PWM outputs by setting the port direction to input for the PWM pins.
 */
#pragma inline = forced
static void DisablePWMOutputs(void)
{
  DDRB &= (~PWM_PIN_MASK_PORTB);
}


/*! \brief Updates the 'tick' counter and checks for stopped motor.
 *
 *  This function should be run at every PWM timer overflow to ensure
 *  that all 'ticks' are counted. It increases the 'tick' counter
 *  until it reaches the maximum tick limit that corresponds to what
 *  is considered a stopped or stalled motor. In that case, the global
 *  motor stopped flag is set.
 */
#pragma inline = forced
static void CommutationTicksUpdate(void)
{
  if (commutationTicks < COMMUTATION_TICKS_STOPPED)
  {
    commutationTicks++;
  }
  else
  {
    fastFlags.motorStopped = TRUE;
    fastFlags.motorSynchronized = FALSE;
    sineTableIncrement = 0;
    if (fastFlags.driveWaveform != WAVEFORM_BLOCK_COMMUTATION)
    {
      TimerSetModeBlockCommutation();
      BlockCommutate(GetDesiredDirection(), GetHall());

#if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
      pid_Reset_Integrator(&pidParameters);
#endif
    }
  }
}


/*! \brief Updates the global motor synchronized flag.
 *
 *  This function updates the global motor synchronized flag. The motor control
 *  is considered to be synchronized with the motor when it is not stopped and
 *  the driver has detected a direction of rotation that corresponds to the
 *  desired direction a predefined number of times.
 */
#pragma inline = forced
static void MotorSynchronizedUpdate(void)
{
  static uint8_t synchCount = 0;

  PMSMflags_t tempFlags;

  tempFlags = fastFlags;

  if ((tempFlags.desiredDirection == tempFlags.actualDirection) &&
      (tempFlags.motorStopped == FALSE) && (tempFlags.motorSynchronized == FALSE))
  {
    synchCount++;
    if (synchCount >= SYNCHRONIZATION_COUNT)
    {
      fastFlags.motorSynchronized = TRUE;
    }
  }
  else
  {
    synchCount = 0;
  }
}


/*! \brief Returns the motor synchronized flag.
 *
 *  This function returns the motor synchronized flag.
 *
 *  \return The motor synchronized flag.
 *
 *  \retval TRUE  Motor control is synchronized with motor.
 *  \retval FALSE Motor control is not yet synchronized with motor.
 */
#pragma inline = forced
static uint8_t IsMotorSynchronized(void)
{
  return (uint8_t)(fastFlags.motorSynchronized);
}


/*! \brief Get the sine table value from the small sine table.
 *
 *  This function returns the value from the small sine table as if it
 *  contained information about one full phase.
 *
 *  \param index Sine table index in the range [0..SINE_TABLE_LENGTH - 1].
 */
#if (SINE_TABLE_SIZE == SINE_TABLE_SIZE_SMALL)
#pragma inline = forced
uint8_t SineTableSmallGetValue(uint8_t index)
{
  //The last 3rd of the table is zero.
  if (index >= (SINE_TABLE_LENGTH * 2 / 3) )
  {
    return 0;
  }

  //The second third of the table is a mirror of the first third.
  if (index >= (SINE_TABLE_LENGTH / 3) )
  {
    index = ((SINE_TABLE_LENGTH * 2 / 3) - 1) - index;
  }

  return sineTable[index];

⌨️ 快捷键说明

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