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

📄 mc_stm8s_acim_drive.c

📁 STM8S105 BLDC源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : MC_stm8s_ACIM_Drive.c
* Author             : IMS Systems Lab 
* Date First Issued  : mm/dd/yyy
* Description        : low level ACIM drive implementation module
********************************************************************************
* History:
* mm/dd/yyyy ver. x.y.z
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* THIS SOURCE CODE IS PROTECTED BY A LICENSE.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/

/* Includes ******************************************************/
#include "stm8s_lib.h"
#include "MC_dev_drive.h"

#include "MC_ACIM_Drive_Param.h"
#include "MC_PowerStage_Param.h"
#include "MC_ControlStage_Param.h" 
#include "MC_stm8s_ACIM_param.h"
#include "MC_ACIM_Motor.h"
#include "MC_stm8s_ACIM_conf.h"
#include "MC_Faults.h"
#include "MC_dev_DAC.h"

//not to be modified
#define BUSCONVERSION_REPRATE (u16)(PWM_FREQUENCY/BUS_SAMPLING_FREQ)
#define HEATSINK_REPRATE (u16)(PWM_FREQUENCY/HEATSINK_SAMPLING_FREQ)
#define USERADC_REPRATE (u16)(PWM_FREQUENCY/USERADC_SAMPLING_FREQ)

#define MAX_BUS_VOLTAGE8 (u8)((MAX_BUS_VOLTAGE*256.0)/BUSV_CONVERSION)
#define MIN_BUS_VOLTAGE8 (u8)((MIN_BUS_VOLTAGE*256.0)/BUSV_CONVERSION)
#define BUS_VOLTAGE_VALUE8 (u8)((BUS_VOLTAGE_VALUE*256.0)/BUSV_CONVERSION)
#define BRAKE_HYSTERESIS8 (u8)((((MAX_BUS_VOLTAGE*256.0)/BUSV_CONVERSION)/16.0)*15.0)

#define MAX_HEATSINK_TEMP8 (u8)(NTC_THRESHOLD/4)
#define MIN_HEATSINK_TEMP8 (u8)(NTC_HYSTERIS/4)

#define HEAT_SINK_TEMPERATURE_TEMP8 (u8)(((TEMP_SENS_ALPHA * (HEAT_SINK_TEMPERATURE_VALUE - TEMP_SENS_T0)) + TEMP_SENS_BETA)/4)

#define ToCMPxH(CMP,Value)         ( CMP = (u8)((Value >> 8 ) & 0xFF))
#define ToCMPxL(CMP,Value)         ( CMP = (u8)(Value & 0xFF) )

typedef enum
{ADC_BUS,ADC_HEATSINK,ADC_USER1} ADCState_t;

struct ADC_Var_t
{
  ADCState_t Signal;
  u8 Channel;
  u8 Conversion;
  struct ADC_Var_t *NextSignal;
};

static @near struct ADC_Var_t BusNode = {ADC_BUS,BUS_ADC_CHANNEL,0,&BusNode};
static @near struct ADC_Var_t HeatNode = {ADC_HEATSINK,HEATSINK_ADC_CHANNEL,0,&BusNode};
static @near struct ADC_Var_t UserNode = {ADC_USER1,USER1_ADC_CHANNEL,0,&BusNode};
static @near struct ADC_Var_t *pADCNode = &BusNode;

static u16 hBusRepRate = BUSCONVERSION_REPRATE;
static u16 hHeatSinkRepRate = HEATSINK_REPRATE;
static u16 hUserADCRepRate = USERADC_REPRATE;

static pu8 pModulationIndex;
static pu16 pFreq;
static pu16 pBusVoltage;
static pu8 pHeatsinkTemp;
static pu16 pReg16;

static @near u8 bBusVolt_Buffer[BUSVOLT_BUFFER_SIZE];
static u8 bBusVolt_Buffer_Index = 0;

static PACIM_Struct_t pACIM_Motor;
vu8 SineMag = 0;
vu16 SineFreq = 0;
vu16 Phase = 0;
vu8 bOffset;
vu8 bBusVoltage;
vu16 hSineMag16;
vu8 bSineMag8;
u8 bBusTemp;
static vu8 bRepCnt;
const vs8 PhaseShiftB = 85;
const vs8 PhaseShiftC = 86;

/*private prototypes ******************************************************/
void stm8_TIM1_ADC2_Init(pvdev_device_t pDevice);

/*exported functions*/
void dev_driveInit(pvdev_device_t pDevice)
{
  pACIM_Motor = Get_ACIM_Struct();

  pModulationIndex = pDevice->regs.r8+VDEV_REG8_ACIM_MODULATION_INDEX;
  pFreq = pDevice->regs.r16+VDEV_REG16_ACIM_FREQUENCY;
  pBusVoltage =  pDevice->regs.r16 + VDEV_REG16_BOARD_BUS_VOLTAGE;
  pHeatsinkTemp = pDevice->regs.r8 + VDEV_REG8_HEATSINK_TEMPERATURE;
  pReg16 = pDevice->regs.r16;
  
#ifdef TACHO
  dev_tachoInit(pDevice);
  dev_tachoEnable();
#endif
  
  stm8_TIM1_ADC2_Init(pDevice);
}

MC_FuncRetVal_t dev_driveStartUpInit(void)
{
  Phase = STARTUP_ANGLE;
  SineMag = 0;
  SineFreq = 0;
  
  TIM1_CtrlPWMOutputs(ENABLE);
  return FUNCTION_ENDED;
}

MC_FuncRetVal_t dev_driveRun(void)
{
  u16 hSineMagtemp;
  u16 hSineFreqtemp;
  
#ifdef DEAD_TIME_COMPENSATION  
  hSineMagtemp = (((u16)(*pModulationIndex))*
                  pACIM_Motor->pACIM_Const->bPWM_Timer_MMI)/256 + 
                  pACIM_Motor->pACIM_Const->bPWM_DeadTime/
                  ((pACIM_Motor->pACIM_Const->hPWM_Prescaler+1)*2) + 1;
#else
  hSineMagtemp = (((u16)(*pModulationIndex))*
                  pACIM_Motor->pACIM_Const->bPWM_Timer_MMI)/256;
#endif
  
  if (hSineMagtemp > pACIM_Motor->pACIM_Const->bPWM_Timer_MMI)
  {
    hSineMagtemp = pACIM_Motor->pACIM_Const->bPWM_Timer_MMI;
  }  
  
  hSineFreqtemp = (s16)(((pACIM_Motor->pACIM_Const->hHz_to_DPP_Conv *
                          (u32)(*pFreq))/256)*pACIM_Motor->pACIM_Var->bDirection);
  
  disableInterrupts();
  SineMag = (u8)hSineMagtemp;
  SineFreq = hSineFreqtemp;
  enableInterrupts();
  
  return FUNCTION_ENDED;
}

MC_FuncRetVal_t dev_driveStop(void)
{
  TIM1_CtrlPWMOutputs(DISABLE);
  SineMag = 0;
  SineFreq = 0;
  return FUNCTION_ENDED;  
}

MC_FuncRetVal_t dev_driveStartUp(void){return FUNCTION_ENDED;}

MC_FuncRetVal_t dev_driveWait(void){return FUNCTION_ENDED;}

void stm8_TIM1_ADC2_Init(pvdev_device_t pDevice)
{  
  /******************  TIM1 configuration **************************************/
  CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1,ENABLE);
  TIM1_DeInit();  
  
  *(pDevice->regs.r8+VDEV_REG8_ACIM_MAX_MODULATION_INDEX) = pACIM_Motor->pACIM_Const->bPWM_Timer_MMI;
  
  //Initializes the Advanced timer TIM1 according to the specified parameters:
  //prescaler, counter mode, period, repetition counter(update rate of the
  //compare registers
  TIM1_TimeBaseInit(pACIM_Motor->pACIM_Const->hPWM_Prescaler,
                    TIM1_COUNTERMODE_CENTERALIGNED1,
                    pACIM_Motor->pACIM_Const->hPWM_Timer_ARR,
                    (u8)(pACIM_Motor->pACIM_Const->bPWM_RefreshRate*2-1));
  
  //Repetition counter alias
  bRepCnt = (u8)((pACIM_Motor->pACIM_Const->bPWM_RefreshRate*2-1) + 2);
  
  //PWM offset duty cycle
  bOffset = pACIM_Motor->pACIM_Const->bPWM_Timer_MMI;
  
  // Enables TIM1 peripheral Preload register on ARR
  TIM1_ARRPreloadConfig(ENABLE);
  
  // Source of Update Request is set to be only counter overflow/underflow
  TIM1_UpdateRequestConfig(TIM1_UPDATESOURCE_REGULAR);

  //Advanced Timer output compare init:  
  TIM1_OC1Init(TIM1_OCMODE_PWM1,TIM1_OUTPUTSTATE_ENABLE,
               DEV_OUTPUTNSTATE,
               (u16)(pACIM_Motor->pACIM_Const->bPWM_Timer_MMI),
               DEV_PWM_U_HIGH_SIDE_POLARITY,DEV_PWM_U_LOW_SIDE_POLARITY,
               DEV_PWM_U_HIGH_SIDE_IDLE_STATE,DEV_PWM_U_LOW_SIDE_IDLE_STATE);
  TIM1_OC2Init(TIM1_OCMODE_PWM1,TIM1_OUTPUTSTATE_ENABLE,
               DEV_OUTPUTNSTATE,
               (u16)(pACIM_Motor->pACIM_Const->bPWM_Timer_MMI),
               DEV_PWM_V_HIGH_SIDE_POLARITY,DEV_PWM_V_LOW_SIDE_POLARITY,
               DEV_PWM_V_HIGH_SIDE_IDLE_STATE,DEV_PWM_V_LOW_SIDE_IDLE_STATE);
  TIM1_OC3Init(TIM1_OCMODE_PWM1,TIM1_OUTPUTSTATE_ENABLE,
               DEV_OUTPUTNSTATE,
               (u16)(pACIM_Motor->pACIM_Const->bPWM_Timer_MMI),
               DEV_PWM_W_HIGH_SIDE_POLARITY,DEV_PWM_W_LOW_SIDE_POLARITY,
               DEV_PWM_W_HIGH_SIDE_IDLE_STATE,DEV_PWM_W_LOW_SIDE_IDLE_STATE);
  
  TIM1_OC4Init(TIM1_OCMODE_PWM1,TIM1_OUTPUTSTATE_DISABLE,
               (pACIM_Motor->pACIM_Const->hPWM_Timer_ARR)-1,
               TIM1_OCPOLARITY_HIGH,
               TIM1_OCIDLESTATE_RESET);

  // Interrupt request priority on counter overflow and break event
  //ITC_SetSoftwarePriority(ITC_IRQ_TIM1_OVF,ITC_PRIORITYLEVEL_3);
  ITC->ISPR3 |= 0xC0;
  ITC->ISPR3 &= 0xFF;
  
  //TIM1 BDTR config: 
  //OCi outputs forced with their idle level as soon as OCi output is enabled,
  //Lock_level 2, deadtime, break enabled, break polarity, automatic output
  //disabled (Main Output Enable can be set only by software)
  TIM1_BDTRConfig(TIM1_OSSISTATE_ENABLE,TIM1_LOCKLEVEL_2,
                  pACIM_Motor->pACIM_Const->bPWM_DeadTime,
                  TIM1_BREAK_STATUS,DEV_BKIN_POLARITY,
                  TIM1_AUTOMATICOUTPUT_DISABLE);
  
  //Enables the TIM1 peripheral
  TIM1_Cmd(ENABLE);
	
  //Timer Re-synch
  TIM1->EGR = 0x01;

  //TIM1_SelectOutputTrigger(TIM1_TRGOSOURCE_OC4REF);
  TIM1->CR2 = (u8)((TIM1->CR2 & (u8)(~TIM1_CR2_MMS)) | (u8) ((u8)0x70));
	
    // Interrupt request is set on break event and counter overflow
  TIM1_ITConfig(TIM1_IT_UPDATE|TIM1_IT_BREAK, ENABLE);
  
  /******************  ADC2 configuration **************************************/
  CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC,ENABLE);
  ADC2_DeInit();
  
  //BUS voltage measurement port initialization  
  GPIO_Init(BUS_ADC_PORT, BUS_ADC_PIN, GPIO_MODE_IN_FL_NO_IT);
  
  //heatsink temperature measurement port initialization  
  GPIO_Init(HEATSINK_ADC_PORT,HEATSINK_ADC_PIN, GPIO_MODE_IN_FL_NO_IT);
  
  //user1 (potentiometer) measurement port initialization  
  GPIO_Init(USER1_ADC_PORT,USER1_ADC_PIN, GPIO_MODE_IN_FL_NO_IT);

  //Disable Schmitt trigger functionality for selected ADC channels
  {
    u16 ADC_TDR_tmp = 0;
    ADC_TDR_tmp |= (u16)(1) << BUS_ADC_CHANNEL;
    ADC_TDR_tmp |= (u16)(1) << HEATSINK_ADC_CHANNEL;
    ADC_TDR_tmp |= (u16)(1) << USER1_ADC_CHANNEL;
    
    ToCMPxH( ADC2->TDRH, ADC_TDR_tmp);
    ToCMPxL( ADC2->TDRL, ADC_TDR_tmp);
  }
  
  //fADC = fMaster/4
  ADC2_PrescalerConfig(ADC2_PRESSEL_FCPU_D4);  
    
  ADC2_ConversionConfig(ADC2_CONVERSIONMODE_SINGLE,BUS_ADC_CHANNEL,ADC2_ALIGN_LEFT);

  ADC2_Cmd(ENABLE);

  ADC2_ExternalTriggerConfig(ADC2_EXTTRIG_TIM,ENABLE);  
  
  //same software priority as TachoTimer Ovf handler and TIM4 handler, but ADC Hw priority is lower
  //ITC_SetSoftwarePriority(ITC_IRQ_ADC,ITC_PRIORITYLEVEL_3);
  ITC->ISPR6 |= 0x30;
  ITC->ISPR6 &= 0xFF;
  
  ADC2_ITConfig(ENABLE);  
}

@near @interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler (void)
{
  /* In order to detect unexpected events during development,
  it is recommended to set a breakpoint on the following instruction.
  */

//if (TIM1_GetITStatus(TIM1_IT_UPDATE)==SET)
if ((TIM1->SR1 & (u8)TIM1_IT_UPDATE) != 0)
{
  u8 bAsynchStart = 0;
  
  //Resynch Repetition counter alias
  bRepCnt = (u8)((pACIM_Motor->pACIM_Const->bPWM_RefreshRate*2-1) + 2);
  
  //ADC manager
  hBusRepRate--;
  hHeatSinkRepRate--;
  hUserADCRepRate--;
  
  //chain linkage
  pADCNode->Signal = ADC_BUS;

  if (hUserADCRepRate == 1)
  {
    pADCNode = &UserNode;
    HeatNode.NextSignal = &UserNode;
    bAsynchStart = 1;
  }
  else
  {
    HeatNode.NextSignal = &BusNode;
  }
  
  if (hHeatSinkRepRate == 1)
  {
    pADCNode = &HeatNode;
    BusNode.NextSignal = &HeatNode; //
    bAsynchStart = 1;
  }
  else
  {
    BusNode.NextSignal = &UserNode; //
  }
  
  //ADC start
  if (bAsynchStart == 1)
  {
    /* Clear the ADC2 channels */
    ADC2->CSR &= (u8)(~ADC2_CSR_CH);
    /* Select the ADC2 channel */
    ADC2->CSR |= (u8)(pADCNode->Channel);
    
    //Start single conversion      

⌨️ 快捷键说明

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