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

📄 mc_stm8s_bldc_drive.c

📁 STM8S105 BLDC源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				#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 + -