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

📄 mc_stm8s_bldc_drive.c

📁 STM8S105 BLDC源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : MC_stm8s_BLDC_drive.c
* Author             : IMS Systems Lab 
* Date First Issued  : mm/dd/yyy
* Description        : Low level BLDC drive 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 "MC_dev_drive.h"

#include "stm8s_lib.h"

#include "MC_stm8s_clk_param.h"
#include "MC_stm8s_BLDC_param.h"

#include "MC_Faults.h"

#include "MC_vtimer.h" 						
#include "MC_BLDC_timers.h" 			
#include "MC_bldc_motor.h"				
#include "MC_BLDC_Motor_Param.h"  
#include "MC_BLDC_Drive_Param.h"  
#include "MC_PowerStage_Param.h" 	
#include "MC_ControlStage_Param.h" 	

#include "MC_BLDC_conf.h"  // Include sensor configuration
#ifdef HALL
	#include "MC_stm8s_hall_param.h"
#endif

#ifdef DAC_FUNCTIONALITY
	#include "MC_dev_DAC.h"
#endif

#ifndef PWM_LOWSIDE_OUTPUT_ENABLE
	#define LS_GPIO_CONTROL

	#if (defined(LS_GPIO_CONTROL) && (FAST_DEMAG != 0))
		#error "Invalid configuration: Is not possible to enable the FAST_DEMAG option with LS_GPIO_CONTROL"
	#endif
#endif

/*private prototypes ******************************************************/
void dev_BLDC_driveUpdate(void);
void Application_ADC_Manager( void );
void GetCurrent(void);
void GetSyncUserAdc(void);
void GetBusVoltage(void);
void GetTemperature(void);
void GetNeutralPoint(void);
void GetAsyncUserAdc(void);
void GetStepTime(void);
void SpeedMeasurement(void);
void DebugPinsOff(void);
void Init_TIM1( void );
void Init_TIM2( void );
void TIM2_InitCapturePolarity(void);
void ComHandler(void);
void Commutate_Motor( void );
void StopMotor( void );
void BrakeMotor( void );
u8 BootStrap(void);
u8 AlignRotor( void );
void StartMotor( void );
void Init_ADC( void );
void Enable_ADC_BEMF_Sampling( void );
void Enable_ADC_Current_Sampling( void );
void Enable_ADC_User_Sync_Sampling( void );
u16 CheckMaxDuty(u16 bRequested_Duty);
void DelayCoefAdjust(void);
u16 Set_Duty(u16 duty);
u16 Set_Current(u16 current);
void SetSamplingPoint_BEMF(void);
void SetSamplingPoint_Current(void);
void SetSamplingPoint_User_Sync(void);

#ifdef LS_GPIO_CONTROL
	void LS_GPIO_MANAGE(void);
	void LS_GPIO_OFF(void);
	void LS_GPIO_BRAKE(void);
	void LS_GPIO_BOOT(void);
	u8 LS_Conf;
#endif

/* Private Typedef */
typedef enum
{STARTUP_IDLE,STARTUP_BOOTSTRAP,STARTUP_ALIGN,STARTUP_START,STARTUP_RAMPING} StartUpStatus_t;

static StartUpStatus_t StartUpStatus = STARTUP_IDLE;

/* Private vars and define */
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80

#define ARRTIM2 500

#ifdef SENSORLESS
	#define ARR_CURRENT_REF_TIM ARRTIM2
#endif
#ifdef HALL
	#define ARR_CURRENT_REF_TIM hArrPwmVal
#endif

#define MILLIAMP_TOCNT(ma) (((((u32)ma * RS_M)/1000) * AOP * (u32)ARR_CURRENT_REF_TIM)/5000)
#define ADC_TOMILLIAMP(adc) ((((u32)adc * 1000 * 1000) / ((u32)1024 * AOP * RS_M)) * 5)

// Internal global pointer to Device and BLDC struct
pvdev_device_t g_pDevice = 0;
PBLDC_Struct_t g_pBLDC_Struct = 0;
static PBLDC_Var_t g_pMotorVar = 0;

u8 ADC_State;
#define ADC_SYNC	0x00
#define ADC_ASYNC	0x01

u8 ADC_Sync_State = 0x04;
#define ADC_BEMF_INIT			0x00
#define ADC_BEMF_SAMPLE			0x01
#define ADC_CURRENT_INIT		0x12//0x02
#define ADC_CURRENT_SAMPLE		0x13//0x03
#define ADC_USER_SYNC_INIT		0x04
#define ADC_USER_SYNC_SAMPLE	0x05

u8 ADC_Async_State = 0;
#define ADC_BUS_INIT				0x00
#define ADC_BUS_SAMPLE				0x01
#define ADC_TEMP_INIT				0x02
#define ADC_TEMP_SAMPLE				0x03
#define ADC_NEUTRAL_POINT_INIT		0x04
#define ADC_NEUTRAL_POINT_SAMPLE	0x05
#define ADC_USER_ASYNC_INIT			0x06
#define ADC_USER_ASYNC_SAMPLE		0x07

#define SIZE_ADC_BUFFER 6
#define ADC_CURRENT_INDEX		0
#define ADC_USER_SYNC_INDEX		1 
#define ADC_BUS_INDEX			2
#define ADC_TEMP_INDEX			3
#define ADC_NEUTRAL_POINT_INDEX	4
#define ADC_USER_ASYNC_INDEX	5

u16 ADC_Buffer[ SIZE_ADC_BUFFER ];

static volatile u8 bCSR_Tmp; // Temporary storage of ADC channel selection

u16 hNeutralPoint;

#define NUMBER_PHASE_STEPS 6

#ifdef ETR_INPUT
	#define OCxCE_ENABLE BIT7
#else
	#define OCxCE_ENABLE 0
#endif

//select PWM mode 1, OC1 preload enabled, OCxCE enabled.
#define CCMR_PWM (OCxCE_ENABLE|BIT6|BIT5|BIT3)

//select PWM mode 2, OC1 preload enabled, OCxCE enabled. Low Side
#define CCMR_PWM_LS (OCxCE_ENABLE|BIT6|BIT5|BIT3)

//select OCREF - Forced Inactive, OC1 preload enabled (LS Off, HS On) X_COMP mode
#define CCMR_LOWSIDE (BIT6|BIT3)

//select OCREF - Forced Active, OC1 preload enabled (LS ON, HS Off) X_COMP mode
#define CCMR_HIGHSIDE (BIT6|BIT4|BIT3)

#if (PWM_U_LOW_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_LS_A BIT3
#else
	#define PWM_POL_LS_A 0
#endif
#if (PWM_U_HIGH_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_HS_A BIT1
#else
	#define PWM_POL_HS_A 0
#endif
#define PWM_POL_A PWM_POL_LS_A|PWM_POL_HS_A

#if (PWM_V_LOW_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_LS_B BIT7
#else
	#define PWM_POL_LS_B 0
#endif
#if (PWM_V_HIGH_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_HS_B BIT5
#else
	#define PWM_POL_HS_B 0
#endif
#define PWM_POL_B PWM_POL_LS_B|PWM_POL_HS_B

#if (PWM_W_LOW_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_LS_C BIT3
#else
	#define PWM_POL_LS_C 0
#endif
#if (PWM_W_HIGH_SIDE_POLARITY == ACTIVE_LOW)
	#define PWM_POL_HS_C BIT1
#else
	#define PWM_POL_HS_C 0
#endif
#define PWM_POL_C PWM_POL_LS_C|PWM_POL_HS_C

#define A_ON  (BIT0|PWM_POL_A) // PWM mode on High Side
#define A_ON_LS  (BIT2|PWM_POL_A) // PWM mode on Low Side
#ifdef LS_GPIO_CONTROL
	#define A_COMP (PWM_POL_A)
#else
	#define A_COMP (BIT2|BIT0|PWM_POL_A)
#endif

#define A_OFF PWM_POL_A

#define B_ON (BIT4|PWM_POL_B)	// PWM mode on High Side
#define B_ON_LS (BIT6|PWM_POL_B) // PWM mode on Low Side
#ifdef LS_GPIO_CONTROL
	#define B_COMP (PWM_POL_B)
#else
	#define B_COMP (BIT6|BIT4|PWM_POL_B)
#endif

#define B_OFF PWM_POL_B

#define C_ON (BIT4|BIT0|PWM_POL_C) // PWM mode on High Side
#define C_ON_LS (BIT4|BIT2|PWM_POL_C) // PWM mode on Low Side
#ifdef LS_GPIO_CONTROL
	#define C_COMP (BIT4|PWM_POL_C)
#else
	#define C_COMP (BIT4|BIT2|BIT0|PWM_POL_C)
#endif

#define C_OFF (BIT4|PWM_POL_C)

// BRK settings
#ifdef BKIN
	#define DEV_BKIN TIM1_BREAK_ENABLE
#else
	#define DEV_BKIN TIM1_BREAK_DISABLE
#endif

#if (BKIN_POLARITY == ACTIVE_HIGH)
	#define DEV_BKIN_POLARITY            TIM1_BREAKPOLARITY_HIGH
#else
	#define DEV_BKIN_POLARITY            TIM1_BREAKPOLARITY_LOW
#endif

#define BEMF_RISING  1
#define BEMF_FALLING 0

#define SAMPLING_POINT_DURING_TOFF_CNT (u16)(((u32)SAMPLING_POINT_DURING_TOFF * STM8_FREQ_MHZ)/1000) // cnt before ARR
#define SAMPLING_POINT_DURING_TON_CNT (u16)(((u32)SAMPLING_POINT_DURING_TON * STM8_FREQ_MHZ)/1000) // cnt after ARR

u16 hDutyCntTh;
u16 hCntDeadDtime;

static const u16 hArrPwmVal = ((u16)((STM8_FREQ_MHZ * (u32)1000000)/PWM_FREQUENCY));
static const u16 hMaxDutyCnt = hArrPwmVal - (((u32)STM8_FREQ_MHZ * MINIMUM_OFF_TIME)/1000);

typedef struct 
{                 
	u8 CCMR_1; //Phase A 
	u8 CCMR_2; //Phase B
	u8 CCMR_3; //Phase C
	u8 CCER_1;
	u8 CCER_2;
} Phase_Step_s;

// CW Steps
//A-Channel1, B-Channel2, C-Channel3
//A(Hi), B(Lo), C-looking, BEMF Falling
//A(Hi), C(Lo), B-looking, BEMF Rising
//B(Hi), C(Lo), A-looking, BEMF Falling
//B(Hi), A(Lo), C-looking, BEMF Rising
//C(Hi), A(Lo), B-looking, BEMF Falling
//C(Hi), B(Lo), C-looking, BEMF Rising
const Phase_Step_s PhaseSteps_CW[ NUMBER_PHASE_STEPS ] =
{
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_ON|B_COMP),  C_OFF}, //A-HI, B-Lo, C-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_ON|B_OFF), C_COMP},  //A-HI, C-Lo, B-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_OFF|B_ON), C_COMP},  //B-HI, C-Lo, A-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_ON),  C_OFF}, //B-HI, A-Lo, C-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_OFF), C_ON},  //C-Hi, A-Lo, B-Looking
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_OFF|B_COMP), C_ON}   //C-Hi, B-Lo, A-Looking
};

const Phase_Step_s Fast_Demag_Steps_CW[ NUMBER_PHASE_STEPS ] =
{
	{CCMR_HIGHSIDE, CCMR_PWM_LS, CCMR_PWM, (A_COMP|B_ON_LS),  C_OFF}, //A-HI, B-Lo, C-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_ON|B_OFF), C_COMP},  //A-HI, C-Lo, B-Looking
	{CCMR_PWM, CCMR_HIGHSIDE, CCMR_PWM_LS, (A_OFF|B_COMP), C_ON_LS},  //B-HI, C-Lo, A-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_ON),  C_OFF}, //B-HI, A-Lo, C-Looking
	{CCMR_PWM_LS, CCMR_PWM, CCMR_HIGHSIDE, (A_ON_LS|B_OFF), C_COMP},  //C-Hi, A-Lo, B-Looking
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_OFF|B_COMP), C_ON}   //C-Hi, B-Lo, A-Looking
};

#ifdef LS_GPIO_CONTROL

	#define LS_A BIT0
	#define LS_B BIT1
	#define LS_C BIT2

	#define LS_NOSW	BIT0
	#define LS_A_B	BIT1
	#define LS_A_C	BIT2
	#define LS_B_A	BIT3
	#define LS_B_C	BIT4
	#define LS_C_A	BIT5
	#define LS_C_B	BIT6
	
	const u8 LS_Steps_CW[ NUMBER_PHASE_STEPS ] =
	{
		LS_B,
		LS_C,
		LS_C,
		LS_A,
		LS_A,
		LS_B
	};

	const u8 LS_Steps_SW_CW[ NUMBER_PHASE_STEPS ] =
	{
		LS_NOSW,
		LS_B_C,
		LS_NOSW,
		LS_C_A,
		LS_NOSW,
		LS_A_B
	};
	
	const u8 LS_Steps_CCW[ NUMBER_PHASE_STEPS ] =
	{
		LS_B,
		LS_B,
		LS_A,
		LS_A,
		LS_C,
		LS_C
	};

	const u8 LS_Steps_SW_CCW[ NUMBER_PHASE_STEPS ] =
	{
		LS_C_B,
		LS_NOSW,
		LS_B_A,
		LS_NOSW,
		LS_A_C,
		LS_NOSW
	};
	
	u8* LS_Steps = LS_Steps_CW;
	u8* LS_Steps_SW = LS_Steps_SW_CW;
#endif

Phase_Step_s* PhaseSteps = PhaseSteps_CW;
Phase_Step_s* Fast_Demag_Steps = Fast_Demag_Steps_CW;

// CCW Steps
//A-Channel1, B-Channel2, C-Channel3
//A(Hi), B(Lo), C-looking, BEMF Rising
//C(Hi), B(Lo), A-looking, BEMF Falling
//C(Hi), A(Lo), B-looking, BEMF Rising
//B(Hi), A(Lo), C-looking, BEMF Falling
//B(Hi), C(Lo), A-looking, BEMF Rising
//A(Hi), C(Lo), B-looking, BEMF Falling
const Phase_Step_s PhaseSteps_CCW[ NUMBER_PHASE_STEPS ] =
{
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_ON|B_COMP),  C_OFF}, //A-Hi, B-Lo, C-Looking
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_OFF|B_COMP), C_ON},  //C-Hi, B-Lo, A-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_OFF), C_ON},  //C-Hi, A-Lo, B-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_ON),  C_OFF}, //B-Hi, A-Lo, C-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_OFF|B_ON), C_COMP},  //B-Hi, C-Lo, A-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_ON|B_OFF), C_COMP}   //A-Hi, C-Lo, B-Looking
};

const Phase_Step_s Fast_Demag_Steps_CCW[ NUMBER_PHASE_STEPS ] =
{
	{CCMR_HIGHSIDE, CCMR_PWM_LS, CCMR_PWM, (A_COMP|B_ON_LS),  C_OFF},	//A-HI, B-Lo, C-Looking
	{CCMR_PWM, CCMR_LOWSIDE, CCMR_PWM, (A_OFF|B_COMP), C_ON},			//C-HI, B-Lo, A-Looking
	{CCMR_PWM_LS, CCMR_PWM, CCMR_HIGHSIDE, (A_ON_LS|B_OFF), C_COMP},	//C-HI, A-Lo, B-Looking
	{CCMR_LOWSIDE, CCMR_PWM, CCMR_PWM, (A_COMP|B_ON),  C_OFF}, 			//B-HI, A-Lo, C-Looking
	{CCMR_PWM, CCMR_HIGHSIDE, CCMR_PWM_LS, (A_OFF|B_COMP), C_ON_LS},	//B-Hi, C-Lo, A-Looking
	{CCMR_PWM, CCMR_PWM, CCMR_LOWSIDE, (A_ON|B_OFF), C_COMP} 			//A-Hi, C-Lo, B-Looking
};

typedef struct
{
	u8 BEMF_Level;
	u8 ADC_Channel;
} BEMF_Step_s;

// CW Steps
const BEMF_Step_s BEMFSteps_CW[ NUMBER_PHASE_STEPS ] =
{
	{BEMF_FALLING, PHASE_C_BEMF_ADC_CHAN},
	{BEMF_RISING,  PHASE_B_BEMF_ADC_CHAN},
	{BEMF_FALLING, PHASE_A_BEMF_ADC_CHAN},
	{BEMF_RISING,  PHASE_C_BEMF_ADC_CHAN},
	{BEMF_FALLING, PHASE_B_BEMF_ADC_CHAN},
	{BEMF_RISING,  PHASE_A_BEMF_ADC_CHAN}
};

BEMF_Step_s* BEMFSteps = BEMFSteps_CW;

// CCW Steps
const BEMF_Step_s BEMFSteps_CCW[ NUMBER_PHASE_STEPS ] =
{
	{BEMF_RISING, PHASE_C_BEMF_ADC_CHAN},
	{BEMF_FALLING,  PHASE_A_BEMF_ADC_CHAN},
	{BEMF_RISING, PHASE_B_BEMF_ADC_CHAN},
	{BEMF_FALLING,  PHASE_C_BEMF_ADC_CHAN},
	{BEMF_RISING, PHASE_A_BEMF_ADC_CHAN},
	{BEMF_FALLING,  PHASE_B_BEMF_ADC_CHAN}
};

u8 Current_Step;
u8 Current_BEMF;
u8 Current_BEMF_Channel;

u8 MTC_Status;
#define MTC_STEP_MODE         BIT0
#define MTC_STARTUP_FAILED    BIT1
#define MTC_OVER_CURRENT_FAIL BIT2
#define MTC_LAST_FORCED_STEP  BIT3
#define MTC_MOTOR_STALLED     BIT4

u8 Phase_State;
#define PHASE_COMM  0x00
#define PHASE_DEMAG 0x01
#define PHASE_ZERO  0x02

u16 Commutation_Time;
u16 Demag_Time;
u16 Zero_Cross_Time;
u16 Previous_Zero_Cross_Time;
u16 Average_Zero_Cross_Time;
u16 LastSwitchedCom;

u16 CurrentLimitCnt;

u8 Ramp_Step;

u8 Zero_Cross_Count;
u8 Last_Zero_Cross_Count;
#define MINIMUM_CONSECTIVE_ZERO_CROSS 12

u8 BEMF_Sample_Debounce;

u8 Z_Detection_Type;
#define Z_DETECT_PWM_OFF 0
#define Z_DETECT_PWM_ON  1

const u16 RAMP_TABLE[ STEP_RAMP_SIZE ] = 
{
	RAMP_VALUE0,
	RAMP_VALUE1,
	RAMP_VALUE2,
	RAMP_VALUE3,
	RAMP_VALUE4,
	RAMP_VALUE5,
	RAMP_VALUE6,
	RAMP_VALUE7,
	RAMP_VALUE8,
	RAMP_VALUE9,
	RAMP_VALUE10,
	RAMP_VALUE11,
	RAMP_VALUE12,
	RAMP_VALUE13,
	RAMP_VALUE14,
	RAMP_VALUE15,
	RAMP_VALUE16,
	RAMP_VALUE17,
	RAMP_VALUE18,
	RAMP_VALUE19,
	RAMP_VALUE20,
	RAMP_VALUE21,
	RAMP_VALUE22,
	RAMP_VALUE23,
	RAMP_VALUE24,
	RAMP_VALUE25,
	RAMP_VALUE26,
	RAMP_VALUE27,
	RAMP_VALUE28,
	RAMP_VALUE29,
	RAMP_VALUE30,
	RAMP_VALUE31,
	RAMP_VALUE32,
	RAMP_VALUE33,
	RAMP_VALUE34,
	RAMP_VALUE35,
	RAMP_VALUE36,
	RAMP_VALUE37,
	RAMP_VALUE38,
	RAMP_VALUE39,
	RAMP_VALUE40,
	RAMP_VALUE41,
	RAMP_VALUE42,
	RAMP_VALUE43,
	RAMP_VALUE44,
	RAMP_VALUE45,
	RAMP_VALUE46,
	RAMP_VALUE47,
	RAMP_VALUE48,
	RAMP_VALUE49,
	RAMP_VALUE50,
	RAMP_VALUE51,
	RAMP_VALUE52,
	RAMP_VALUE53,
	RAMP_VALUE54,
	RAMP_VALUE55,
	RAMP_VALUE56,
	RAMP_VALUE57,
	RAMP_VALUE58,
	RAMP_VALUE59,
	RAMP_VALUE60,
	RAMP_VALUE61,
	RAMP_VALUE62,
	RAMP_VALUE63
};

u8 Align_State;
#define ALIGN_IDLE 0x00
#define ALIGN_RAMP 0x01
#define ALIGN_DONE 0x02

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

u8 Align_Target;
u8 Align_Index;

#define CAP_STEP_NUM 6 // Do not change this value
u16 cap_val = 0;

⌨️ 快捷键说明

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