?? stm32f10x_svpwm_3shunt.c
字號:
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Enable ADC2 */
ADC_Cmd(ADC2, ENABLE); //喚醒ADC2
/* Enable ADC2 reset calibaration register */
ADC_ResetCalibration(ADC2);
/* Check the end of ADC2 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC2));
/* Start ADC2 calibaration */
ADC_StartCalibration(ADC2);
/* Check the end of ADC2 calibration */
while(ADC_GetCalibrationStatus(ADC2));
//==================================================================================
SVPWM_3ShuntCurrentReadingCalibration();
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// NVIC_StructInit(&NVIC_InitStructure);
/* Enable the ADC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ADC_PRE_EMPTION_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ADC_SUB_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the Update Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIM1_UP_PRE_EMPTION_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIM1_UP_SUB_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM1 BRK Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = BRK_PRE_EMPTION_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = BRK_SUB_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //沒有打開緊急停車功能
NVIC_Init(&NVIC_InitStructure);
/* Enable the DMA_CHANEL1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = DMA_CH1_PRE_EMPTION_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = DMA_CH1_SUB_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //首先軟件觸發規則組,連續掃描
/* ADC1、ADC2 regular conversions trigger is TIM4_CC4*/
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
ADC_ExternalTrigConvCmd(ADC2, ENABLE);
}
/*******************************************************************************
* Function Name : SVPWM_3ShuntCurrentReadingCalibration
* Description : Store zero current converted values for current reading
network offset compensation in case of 3 shunt resistors
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SVPWM_3ShuntCurrentReadingCalibration(void)
{
static u16 bIndex;
/* ADC1 Injected group of conversions end interrupt disabling */
ADC_ITConfig(ADC1, ADC_IT_JEOC, DISABLE);
hPhaseAOffset=0;
hPhaseBOffset=0;
hPhaseCOffset=0;
/* ADC1 Injected conversions trigger is given by software and enabled */
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);
ADC_ExternalTrigInjectedConvCmd(ADC1,ENABLE);
/* ADC1 Injected conversions configuration */
ADC_InjectedSequencerLengthConfig(ADC1,3);
ADC_InjectedChannelConfig(ADC1, PHASE_A_ADC_CHANNEL,1,SAMPLING_TIME_CK);
ADC_InjectedChannelConfig(ADC1, PHASE_B_ADC_CHANNEL,2,SAMPLING_TIME_CK);
ADC_InjectedChannelConfig(ADC1, PHASE_C_ADC_CHANNEL,3,SAMPLING_TIME_CK);
/* Clear the ADC1 JEOC pending flag */
ADC_ClearFlag(ADC1, ADC_FLAG_JEOC);
ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE);
/* ADC Channel used for current reading are read
in order to get zero currents ADC values*/
for(bIndex=0; bIndex <NB_CONVERSIONS; bIndex++)
{
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC)) { }
hPhaseAOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1)>>3);
hPhaseBOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2)>>3);
hPhaseCOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_3)>>3);
/* Clear the ADC1 JEOC pending flag */
ADC_ClearFlag(ADC1, ADC_FLAG_JEOC);
ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE);
}
SVPWM_InjectedConvConfig();
}
/*******************************************************************************
* Function Name : SVPWM_InjectedConvConfig
* Description : This function configure ADC1 for 3 shunt current
* reading and temperature and voltage feedbcak after a
* calibration of the three utilized ADC Channels
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SVPWM_InjectedConvConfig(void)
{
/* ADC1 Injected conversions configuration */
ADC_InjectedSequencerLengthConfig(ADC1,2);
ADC_InjectedChannelConfig(ADC1, PHASE_B_ADC_CHANNEL, 1,
SAMPLING_TIME_CK);
ADC_InjectedChannelConfig(ADC1, BUS_VOLT_FDBK_CHANNEL,
2, SAMPLING_TIME_CK);
/* ADC1 Injected conversions trigger is TIM1 TRGO */
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_TRGO);
/* ADC2 Injected conversions configuration */
ADC_InjectedSequencerLengthConfig(ADC2,2);
ADC_InjectedChannelConfig(ADC2, PHASE_A_ADC_CHANNEL, 1,
SAMPLING_TIME_CK);
ADC_InjectedChannelConfig(ADC2, TEMP_FDBK_CHANNEL, 2,
SAMPLING_TIME_CK);
ADC_ExternalTrigInjectedConvCmd(ADC2,ENABLE);
/* Bus voltage protection initialization*/
ADC_AnalogWatchdogCmd(ADC1,ADC_AnalogWatchdog_SingleInjecEnable);
ADC_AnalogWatchdogSingleChannelConfig(ADC1,BUS_VOLT_FDBK_CHANNEL);
ADC_AnalogWatchdogThresholdsConfig(ADC1, OVERVOLTAGE_THRESHOLD>>3,0x00);
/* ADC1 Injected group of conversions end and Analog Watchdog interrupts
enabling */
ADC_ITConfig(ADC1, ADC_IT_JEOC | ADC_IT_AWD, ENABLE);
}
/*******************************************************************************
* Function Name : SVPWM_3ShuntGetPhaseCurrentValues
* Description : This function computes current values of Phase A and Phase B
* in q1.15 format starting from values acquired from the A/D
* Converter peripheral.
* Input : None
* Output : Stat_Curr_a_b
* Return : None
*******************************************************************************/
Curr_Components SVPWM_3ShuntGetPhaseCurrentValues(void)
{
Curr_Components Local_Stator_Currents;
s32 wAux;
switch (bSector)
{
case 4:
case 5: //Current on Phase C not accessible
// Ia = (hPhaseAOffset)-(ADC Channel 11 value)
wAux = (s32)(hPhaseAOffset)- ((ADC1->JDR1)<<1);
//Saturation of Ia
if (wAux < S16_MIN)
{
Local_Stator_Currents.qI_Component1= S16_MIN;
}
else if (wAux > S16_MAX)
{
Local_Stator_Currents.qI_Component1= S16_MAX;
}
else
{
Local_Stator_Currents.qI_Component1= wAux;
}
// Ib = (hPhaseBOffset)-(ADC Channel 12 value)
wAux = (s32)(hPhaseBOffset)-((ADC2->JDR1)<<1);
// Saturation of Ib
if (wAux < S16_MIN)
{
Local_Stator_Currents.qI_Component2= S16_MIN;
}
else if (wAux > S16_MAX)
{
Local_Stator_Currents.qI_Component2= S16_MAX;
}
else
{
Local_Stator_Currents.qI_Component2= wAux;
}
break;
case 6:
case 1: //Current on Phase A not accessible
// Ib = (hPhaseBOffset)-(ADC Channel 12 value)
wAux = (s32)(hPhaseBOffset)-((ADC1->JDR1)<<1);
//Saturation of Ib
if (wAux < S16_MIN)
{
Local_Stator_Currents.qI_Component2= S16_MIN;
}
else if (wAux > S16_MAX)
{
Local_Stator_Currents.qI_Component2= S16_MAX;
}
else
{
Local_Stator_Currents.qI_Component2= wAux;
}
// Ia = -Ic -Ib
wAux = ((ADC2->JDR1)<<1)-hPhaseCOffset-
Local_Stator_Currents.qI_Component2;
//Saturation of Ia
if (wAux> S16_MAX)
{
Local_Stator_Currents.qI_Component1 = S16_MAX;
}
else if (wAux <S16_MIN)
{
Local_Stator_Currents.qI_Component1 = S16_MIN;
}
else
{
Local_Stator_Currents.qI_Component1 = wAux;
}
break;
case 2:
case 3: // Current on Phase B not accessible
// Ia = (hPhaseAOffset)-(ADC Channel 11 value)
wAux = (s32)(hPhaseAOffset)-((ADC1->JDR1)<<1);
//Saturation of Ia
if (wAux < S16_MIN)
{
Local_Stator_Currents.qI_Component1= S16_MIN;
}
else if (wAux > S16_MAX)
{
Local_Stator_Currents.qI_Component1= S16_MAX;
}
else
{
Local_Stator_Currents.qI_Component1= wAux;
}
// Ib = -Ic-Ia;
wAux = ((ADC2->JDR1)<<1) - hPhaseCOffset -
Local_Stator_Currents.qI_Component1;
// Saturation of Ib
if (wAux> S16_MAX)
{
Local_Stator_Currents.qI_Component2=S16_MAX;
}
else if (wAux <S16_MIN)
{
Local_Stator_Currents.qI_Component2 = S16_MIN;
}
else
{
Local_Stator_Currents.qI_Component2 = wAux;
}
break;
default:
break;
}
return(Local_Stator_Currents);
}
/*******************************************************************************
* Function Name : SVPWM_3ShuntCalcDutyCycles
* Description : Computes duty cycle values corresponding to the input value
and configures the AD converter and TIM0 for next period
current reading conversion synchronization
* Input : Stat_Volt_alfa_beta
* Output : None
* Return : None
*******************************************************************************/
void SVPWM_3ShuntCalcDutyCycles (Volt_Components Stat_Volt_Input)
{
s32 wX, wY, wZ, wUAlpha, wUBeta;
u16 hTimePhA=0, hTimePhB=0, hTimePhC=0, hTimePhD=0;
u16 hDeltaDuty;
wUAlpha = Stat_Volt_Input.qV_Component1 * T_SQRT3 ;
wUBeta = -(Stat_Volt_Input.qV_Component2 * T);
wX = wUBeta;
wY = (wUBeta + wUAlpha)/2;
wZ = (wUBeta - wUAlpha)/2;
// Sector calculation from wX, wY, wZ
if (wY<0)
{
if (wZ<0)
{
bSector = SECTOR_5;
}
else // wZ >= 0
if (wX<=0)
{
bSector = SECTOR_4;
}
else // wX > 0
{
bSector = SECTOR_3;
}
}
else // wY > 0
{
if (wZ>=0)
{
bSector = SECTOR_2;
}
else // wZ < 0
if (wX<=0)
{
bSector = SECTOR_6;
}
else // wX > 0
{
bSector = SECTOR_1;
}
}
/* Duty cycles computation */
PWM4Direction=PWM2_MODE;
switch(bSector)
{
case SECTOR_1:
hTimePhA = (T/8) + ((((T + wX) - wZ)/2)/131072);
hTimePhB = hTimePhA + wZ/131072;
hTimePhC = hTimePhB - wX/131072;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -