📄 mc_stm8s_bldc_drive.c
字号:
#else
LS_A_PORT->ODR &= (u8)(~LS_A_PIN);
#endif
// Deactivate B
#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_B_PORT->ODR &= (u8)(~LS_B_PIN);
#else
LS_B_PORT->ODR |= LS_B_PIN;
#endif
}
if (LS_Conf == LS_B_C)
{
// Activate C
#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_C_PORT->ODR |= LS_C_PIN;
#else
LS_C_PORT->ODR &= (u8)(~LS_C_PIN);
#endif
// Deactivate B
#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_B_PORT->ODR &= (u8)(~LS_B_PIN);
#else
LS_B_PORT->ODR |= LS_B_PIN;
#endif
}
if (LS_Conf == LS_C_A)
{
// Activate A
#if (PWM_U_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_A_PORT->ODR |= LS_A_PIN;
#else
LS_A_PORT->ODR &= (u8)(~LS_A_PIN);
#endif
// Deactivate C
#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_C_PORT->ODR &= (u8)(~LS_C_PIN);
#else
LS_C_PORT->ODR |= LS_C_PIN;
#endif
}
if (LS_Conf == LS_C_B)
{
// Activate B
#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_B_PORT->ODR |= LS_B_PIN;
#else
LS_B_PORT->ODR &= (u8)(~LS_B_PIN);
#endif
// Deactivate C
#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_C_PORT->ODR &= (u8)(~LS_C_PIN);
#else
LS_C_PORT->ODR |= LS_C_PIN;
#endif
}
}
#endif
Current_BEMF = BEMFSteps[Current_Step].BEMF_Level;
Current_BEMF_Channel = BEMFSteps[Current_Step].ADC_Channel;
if (g_pBLDC_Struct->pBLDC_Var->bFastDemag == 0)
{
// Update CCMRx OCxCE bit (Actual)
TIM1->CCMR1 = (u8)(PhaseSteps[Current_Step].CCMR_1 & 0x80);
TIM1->CCMR2 = (u8)(PhaseSteps[Current_Step].CCMR_2 & 0x80);
TIM1->CCMR3 = (u8)(PhaseSteps[Current_Step].CCMR_3 & 0x80);
}
else
{
// Update CCMRx OCxCE bit (Actual)
TIM1->CCMR1 = (u8)(Fast_Demag_Steps[Current_Step].CCMR_1 & 0x80);
TIM1->CCMR2 = (u8)(Fast_Demag_Steps[Current_Step].CCMR_2 & 0x80);
TIM1->CCMR3 = (u8)(Fast_Demag_Steps[Current_Step].CCMR_3 & 0x80);
}
// Preload next values
TIM1->CCMR1 |= (u8)(PhaseSteps[Current_Step].CCMR_1 & 0x7F);
TIM1->CCMR2 |= (u8)(PhaseSteps[Current_Step].CCMR_2 & 0x7F);
TIM1->CCMR3 |= (u8)(PhaseSteps[Current_Step].CCMR_3 & 0x7F);
TIM1->CCER1 = PhaseSteps[Current_Step].CCER_1;
TIM1->CCER2 = PhaseSteps[Current_Step].CCER_2;
//calc demag time
if( (MTC_Status & MTC_STEP_MODE) == MTC_STEP_MODE )
{
if( (MTC_Status & MTC_LAST_FORCED_STEP) == MTC_LAST_FORCED_STEP )
{
MTC_Status &= (u8)(~MTC_STEP_MODE);
#ifdef DEBUG_PINS
AUTO_SWITCH_PORT |= AUTO_SWITCH_PIN;
#endif
}
//Demag_Time = (u16)((u32)(Commutation_Time * BLDC_Get_Demag_Time()) / 100);
tmp_u8 = BLDC_Get_Demag_Time();
#asm
; tmp_sc_u8 = (u8)((tmp_u8 * 256) / (u8)(100));
ld A,_tmp_u8
clrw x
ld XH,A
ld A,#0x64
div X,A
ld A,XL
ld _tmp_u8,A
; Demag_Time = (Commutation_Time * tmp_sc_u8) >> 8;
ld A,_Commutation_Time
ld XL,A
ld A,_tmp_u8
mul X,A
ldw _tmp_u16,X
ld A,_Commutation_Time + 1
ld XL,A
ld A,_tmp_u8
mul X,A
ld A,XH
clrw X
ld XL,A
addw X,_tmp_u16
ldw _Demag_Time,X
#endasm
}
else
{
//Demag_Time = (u16)((u32)(Average_Zero_Cross_Time * BLDC_Get_Demag_Time()) / 100);
tmp_u8 = BLDC_Get_Demag_Time();
#asm
; tmp_sc_u8 = (u8)((BLDC_Get_Demag_Time() * 256) / (u8)(100));
ld A,_tmp_u8
clrw x
ld XH,A
ld A,#0x64
div X,A
ld A,XL
ld _tmp_u8,A
; Demag_Time = (Average_Zero_Cross_Time * tmp_sc_u8) >> 8;
ld A,_Average_Zero_Cross_Time
ld XL,A
ld A,_tmp_u8
mul X,A
ldw _tmp_u16,X
ld A,_Average_Zero_Cross_Time + 1
ld XL,A
ld A,_tmp_u8
mul X,A
ld A,XH
clrw X
ld XL,A
addw X,_tmp_u16
ldw _Demag_Time,X
#endasm
}
LastSwitchedCom = hTim3Cnt;
hTim3Th = hTim3Cnt + Demag_Time;
}
#endif
#ifdef HALL
void Commutate_Motor( void )
{
//commutate the motor
TIM1->EGR |= BIT5;
#ifdef LS_GPIO_CONTROL
LS_Conf = LS_Steps[Current_Step];
if (LS_Conf == LS_A)
{ // Activate A
#if (PWM_U_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_A_PORT->ODR |= LS_A_PIN;
#else
LS_A_PORT->ODR &= (u8)(~LS_A_PIN);
#endif
}
else
{
// Deactivate A
#if (PWM_U_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_A_PORT->ODR &= (u8)(~LS_A_PIN);
#else
LS_A_PORT->ODR |= LS_A_PIN;
#endif
}
if (LS_Conf == LS_B)
{
// Activate B
#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_B_PORT->ODR |= LS_B_PIN;
#else
LS_B_PORT->ODR &= (u8)(~LS_B_PIN);
#endif
}
else
{
// Deactivate B
#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_B_PORT->ODR &= (u8)(~LS_B_PIN);
#else
LS_B_PORT->ODR |= LS_B_PIN;
#endif
}
if (LS_Conf == LS_C)
{
// Activate C
#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_C_PORT->ODR |= LS_C_PIN;
#else
LS_C_PORT->ODR &= (u8)(~LS_C_PIN);
#endif
}
else
{
// Deactivate C
#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_HIGH)
LS_C_PORT->ODR &= (u8)(~LS_C_PIN);
#else
LS_C_PORT->ODR |= LS_C_PIN;
#endif
}
#endif
}
#endif
void StopMotor( void )
{
//Disable update interrupt
TIM1->IER &= (u8)(~BIT0);
#ifdef HALL
// Disable Input Capture Interrupt
TIM2->IER = 0;
#endif
TIM1->CCMR1 = CCMR_PWM;
TIM1->CCMR2 = CCMR_PWM;
TIM1->CCMR3 = CCMR_PWM;
TIM1->CCER1 = (A_OFF|B_OFF);
TIM1->CCER2 = C_OFF;
TIM1->EGR |= BIT5;
#ifdef LS_GPIO_CONTROL
LS_GPIO_OFF();
#endif
Enable_ADC_User_Sync_Sampling();
Motor_Frequency = 0;
}
void BrakeMotor( void )
{
u16 brake_pwm_cnt;
brake_pwm_cnt = (u16)(((u32)hArrPwmVal * BRAKE_DUTY) / 100);
ToCMPxH( TIM1->CCR1H, brake_pwm_cnt );
ToCMPxL( TIM1->CCR1L, brake_pwm_cnt );
ToCMPxH( TIM1->CCR2H, brake_pwm_cnt );
ToCMPxL( TIM1->CCR2L, brake_pwm_cnt );
ToCMPxH( TIM1->CCR3H, brake_pwm_cnt );
ToCMPxL( TIM1->CCR3L, brake_pwm_cnt );
//Disable update interrupt
TIM1->IER &= (u8)(~BIT0);
TIM1->CCMR1 = CCMR_PWM;
TIM1->CCMR2 = CCMR_LOWSIDE;
TIM1->CCMR3 = CCMR_LOWSIDE;
TIM1->CCER1 = (A_ON|B_COMP);
TIM1->CCER2 = C_COMP;
TIM1->EGR |= BIT5;
#ifdef LS_GPIO_CONTROL
LS_GPIO_BRAKE();
#endif
}
u8 BootStrap(void)
{
TIM1->CCMR1 = CCMR_LOWSIDE;
TIM1->CCMR2 = CCMR_LOWSIDE;
TIM1->CCMR3 = CCMR_LOWSIDE;
TIM1->CCER1 = (A_COMP|B_COMP);
TIM1->CCER2 = C_COMP;
//force update of output states
TIM1->EGR |= BIT5;
// Enable MC Outputs
TIM1->BKR |= BIT7;
#ifdef LS_GPIO_CONTROL
LS_GPIO_BOOT();
#endif
return (vtimer_TimerElapsed(MTC_ALIGN_RAMP_TIMER));
}
u8 AlignRotor( void )
{
u8 status;
u16 temp;
u32 temp32;
status = 0;
switch( Align_State )
{
default:
case ALIGN_IDLE:
TIM1->CCMR1 = CCMR_PWM;
TIM1->CCMR2 = CCMR_LOWSIDE;
TIM1->CCMR3 = CCMR_LOWSIDE;
TIM1->CCER1 = (A_ON|B_COMP);
TIM1->CCER2 = C_COMP;
ToCMPxH( TIM1->CCR1H, 0 );
ToCMPxL( TIM1->CCR1L, 0 );
ToCMPxH( TIM1->CCR2H, 0 );
ToCMPxL( TIM1->CCR2L, 0 );
ToCMPxH( TIM1->CCR3H, 0 );
ToCMPxL( TIM1->CCR3L, 0 );
Align_Target = ALIGN_DUTY_CYCLE;
Align_Index = 0;
vtimer_SetTimer(MTC_ALIGN_RAMP_TIMER,ALIGN_SLOPE,0);
vtimer_SetTimer(MTC_ALIGN_TIMER,ALIGN_DURATION,0);
//force update of output states
TIM1->EGR |= BIT5;
#ifdef LS_GPIO_CONTROL
LS_GPIO_BRAKE();
#endif
//preload next step
Current_Step=0;
TIM1->CCMR1 = PhaseSteps[Current_Step].CCMR_1;
TIM1->CCMR2 = PhaseSteps[Current_Step].CCMR_2;
TIM1->CCMR3 = PhaseSteps[Current_Step].CCMR_3;
TIM1->CCER1 = PhaseSteps[Current_Step].CCER_1;
TIM1->CCER2 = PhaseSteps[Current_Step].CCER_2;
BEMF_Falling_Factor = BEMF_FALL_DELAY_FACTOR;
BEMF_Rising_Factor = BEMF_RISE_DELAY_FACTOR;
TIM1->DTR = (u8)(hCntDeadDtime);
Align_State = ALIGN_RAMP;
break;
case ALIGN_RAMP:
if (vtimer_TimerElapsed(MTC_ALIGN_RAMP_TIMER))
{
if( Align_Index < Align_Target )
{
Align_Index += 1;
temp32 = ((u32)Align_Index * (u16)hArrPwmVal);
temp32 = temp32/(u16)100;
temp = (u16)temp32;
ToCMPxH( TIM1->CCR1H, temp );
ToCMPxL( TIM1->CCR1L, temp );
ToCMPxH( TIM1->CCR2H, temp );
ToCMPxL( TIM1->CCR2L, temp );
ToCMPxH( TIM1->CCR3H, temp );
ToCMPxL( TIM1->CCR3L, temp );
}
vtimer_SetTimer(MTC_ALIGN_RAMP_TIMER,ALIGN_SLOPE,0);
}
if (vtimer_TimerElapsed(MTC_ALIGN_TIMER))
{
Align_State = ALIGN_DONE;
status = 1;
}
break;
case ALIGN_DONE:
status = 1;
break;
}
return( status );
}
void StartMotor( void )
{
u16 cur_time;
u16 temp;
u32 data;
Zero_Cross_Count=0;
Last_Zero_Cross_Count=0;
Ramp_Step=0;
Commutation_Time = RAMP_TABLE[ Ramp_Step ];
Ramp_Step++;
//force update of output states
TIM1->EGR |= BIT5;
#ifdef LS_GPIO_CONTROL
LS_GPIO_MANAGE();
#endif
Current_BEMF = BEMFSteps[Current_Step].BEMF_Level;
Current_BEMF_Channel = BEMFSteps[Current_Step].ADC_Channel;
//preload next step
Current_Step++;
if( Current_Step >= NUMBER_PHASE_STEPS )
{
Current_Step = 0;
}
TIM1->CCMR1 = PhaseSteps[Current_Step].CCMR_1;
TIM1->CCMR2 = PhaseSteps[Current_Step].CCMR_2;
TIM1->CCMR3 = PhaseSteps[Current_Step].CCMR_3;
tmp_TIM1_CCER1 = PhaseSteps[Current_Step].CCER_1;
tmp_TIM1_CCER2 = PhaseSteps[Current_Step].CCER_2;
// Store the values for the commutation
tmp_TIM1_CCMR1 = TIM1->CCMR1;
tmp_TIM1_CCMR2 = TIM1->CCMR2;
tmp_TIM1_CCMR3 = TIM1->CCMR3;
// Set to frozen for next COM
TIM1->CCMR1 &= 0x8F;
TIM1->CCMR2 &= 0x8F;
TIM1->CCMR3 &= 0x8F;
//load commutation time into timer
hTim3Th = Commutation_Time;
data = ((u32)RAMP_DUTY_CYCLE * (u16)hArrPwmVal);
data = data / (u16)100;
temp = (u16)data;
// Set Startup Duty
ToCMPxH( TIM1->CCR1H, temp );
ToCMPxL( TIM1->CCR1L, temp );
ToCMPxH( TIM1->CCR2H, temp );
ToCMPxL( TIM1->CCR2L, temp );
ToCMPxH( TIM1->CCR3H, temp );
ToCMPxL( TIM1->CCR3L, temp );
// Current Limitation
#ifdef SENSORLESS
ToCMPxH( TIM2->CCR2H, MILLIAMP_TOCNT (STARTUP_CURRENT_LIMITATION) );
ToCMPxL( TIM2->CCR2L, MILLIAMP_TOCNT (STARTUP_CURRENT_LIMITATION) );
#endif
#ifdef HALL
ToCMPxH( TIM1->CCR4H, hArrPwmVal - MILLIAMP_TOCNT (STARTUP_CURRENT_LIMITATION) );
ToCMPxL( TIM1->CCR4L, hArrPwmVal - MILLIAMP_TOCNT (STARTUP_CURRENT_LIMITATION) );
#endif
Phase_State = PHASE_ZERO;
}
/*-----------------------------------------------------------------------------
ROUTINE Name : Set_Duty
Description: This is the update routine of the PWM duty cycle -> feed MCPUH/L
Input is the new duty to be set express in Timer counts
Comments: Used in Voltage Mode
-----------------------------------------------------------------------------*/
u16 Set_Duty(u16 duty)
{
u16 time;
// Adjust Delay coefficient
DelayCoefAdjust();
if( Z_Detection_Type == Z_DETECT_PWM_OFF )
{
if (duty > hMaxDutyCnt)
{
duty = hMaxDutyCnt;
}
//set dead time
TIM1->DTR = (u8)(hCntDeadDtime);
}
else
{
//adjust deadtime generator to get smaller off time than deadtime allows
time = hArrPwmVal - duty;
if( time >= hCntDeadDtime )
{
TIM1->DTR = (u8)(hCntDeadDtime);
}
else
{
if( time <= 16 )
{
// if less than 1us then turn off deadtime generator
TIM1->DTR = 0;
}
else
{
TIM1->DTR = (u8)time;
}
}
if( duty > hArrPwmVal )
{
//set to 100%
duty = hArrPwmVal;
}
}
ToCMPxH( TIM1->CCR1H, duty );
ToCMPxL( TIM1->CCR1L, duty );
ToCMPxH( TIM1->CCR2H, duty );
ToCMPxL( TIM1->CCR2L, duty );
ToCMPxH( TIM1->CCR3H, duty );
ToCMPxL( TIM1->CCR3L, duty );
// Current Limitation
#ifdef SENSORLESS
ToCMPxH( TIM2->CCR2H, CurrentLimitCnt );
ToCMPxL( TIM2->CCR2L, CurrentLimitCnt );
#endif
#ifdef HALL
ToCMPxH( TIM1->CCR4H, hArrPwmVal - CurrentLimitCnt );
ToCMPxL( TIM1->CCR4L, hArrPwmVal - CurrentLimitCnt );
#endif
*pDutyCycleCounts_reg = duty;
return duty;
}
/*-----------------------------------------------------------------------------
ROUTINE Name :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -