/********************************************************************
** File: SensoredBLDC.c
** Written By:MikeDu
**
** The following files should be included in the MPLAB project:
** SensoredBLDC.c -- Main source code file
** Interrupts.c
** Init.c
** SensoredBLDC.h -- Header file
** p33FJ32MC204.gld -- Linker script file
**
** Revision History
**
********************************************************************/
#include "p33fxxxx.h"
#include "SensoredBLDC.h"
unsigned int StateTableFwd[] = {0x0000, 0x0810, 0x0204, 0x0210,
0x2001, 0x0801, 0x2004, 0x0000};
/******************************************************************************/
/* Configuration bits */
/******************************************************************************/
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & POSCMD_XT);
_FBS (BSS_NO_FLASH & BWRP_WRPROTECT_OFF);
_FWDT (FWDTEN_OFF & WDTPOST_PS1024 & WDTPRE_PR32);
_FGS (GSS_OFF & GCP_OFF & GWRP_OFF);
_FPOR (PWMPIN_ON & HPOL_ON & LPOL_ON & FPWRT_PWR128);
_FICD (ICS_PGD1 & JTAGEN_OFF);
char FlagHalfSec = 0,FlagHallErr = 0,FlagPowerErr = 0,FlagAnalogLowStop = 0,FlagLowSpeedCheck = 0,FlagOverTemp = 0;
char FlagLowSpeed = 0,FlagOverSpeed = 0;
char FlagLowSpeedStop = 0,FlagOverSpeedStop = 0,FlagOverCurStop = 0,SpeedErrStopNum = 0,CurErrStopNum = 0;
char OverSpeedTime = 0,LowSpeedTime = 0;
char FlagSpeedErr = 0,FlagCheckCur = 0;
char HalErr = 0;
char LowSpeedErrStopNum = 0,OverSpeedErrStopNum = 0;
int FlagSpeedStop = 0,HalNum = 0;
unsigned int HallValue;
unsigned int HallNum[6]={2,3,1,5,4,6};
unsigned int BldcCur[3];
int DutyNum = STARTDUTYNUM;
int LastCur,NewCur,LastTime,NewTime;
unsigned long AverageSpeed = 0;
unsigned long CurrAverNum;
char LowSpeedCheckTime = 0;
char HallErrNum = 0;
extern char FlagStop;
extern int ActualSpeed;
extern int MsCountNum;
extern long SpeedIntegral;
extern long SpeedIntegral_n_1;
extern unsigned int timer3value;
/***********************************************
重新打开电机并开启PID运算,
缓启动结束后检测失速异常
************************************************/
void MotorReset(void)
{
PDC1 = STARTDUTYNUM;
PDC2 = STARTDUTYNUM;
PDC3 = STARTDUTYNUM;
PidDesiredSpeed = 0;
timer3value = 0;
SpeedIntegral = 0;
SpeedIntegral_n_1 = 0;
FlagStop = 0;
FlagLowSpeedCheck = 0;
LowSpeedCheckTime = 22;
MotorStart();
SlowStart();
}
/********************************************
霍尔异常检测
*********************************************/
#if 0
void HallErrCheck(void)
{
if((HallValue == 0) || (HallValue == 7))
HalErr++;
else
HalErr = 0;
if(HalErr >= 10)
{
MotorStop();
HalErr = 10;
}
}
#endif
void HallErrCheck(void)
{
char i=0,UpahTotal=0,VpahTotal=0,WpahTotal=0;
for(i=0;i<6;i++)
{
UpahTotal += (HallNum[i] & 0x01);
VpahTotal += ((HallNum[i]>>1) & 0x01);
WpahTotal += ((HallNum[i]>>2) & 0x01);
}
if(((UpahTotal == 0) || (UpahTotal == 6)) || \
((VpahTotal == 0) || (VpahTotal == 6)) || \
((WpahTotal == 0) || (WpahTotal == 6)))
{
HallErrNum++;
}
else
{
HallErrNum = 0;
}
if(HallErrNum == 10)
{
HallErrNum = 0;
MotorStop();
}
}
/********************************************
过速异常检测
*********************************************/
void OverSpeedErrCheck(void)
{
int num = OVERSPEEDTIME;
while(ActualSpeed > OVERSPEEDNUM)
{
num--;
DelayNmSec(1);
if(num == 0)
{
MotorStop();
ActualSpeed = 0;
FlagOverSpeedStop = 1;
FlagSpeedErr = 1;
OverSpeedErrStopNum = 20;
break;
}
}
}
/********************************************
失速异常检测
*********************************************/
void LowSpeedErrCheck(void)
{
int num = LOWSPEEDTIME;
while((ActualSpeed < LOWSPEEDNUM) && (FlagStop == 0))
{
num--;
DelayNmSec(1);
if(num == 0)
{
MotorStop();
FlagLowSpeedStop = 1;
FlagLowSpeedCheck = 0;
FlagSpeedErr = 1;
LowSpeedErrStopNum = 20;
break;
}
}
}
int main(void)
{
/* Pll + Osc Configuration */
PllOscConfig();
/* Pin Configuration */
PortConfig();
/*
AN0:Vcc Input Channel0
AN1:Temperature Input Channel0
AN4:Vanalog Input Channel2
AN5:Current Input Channel3
*/
InitADC10();
/* 每隔1ms读取一次转速,并执行PID运算 */
InitTMR1();
/* 打开看门狗*/
RCONbits.SWDTEN = 1;
/* 用于计算电机转速 */
InitTMR3();
/* Freq:39kHz,三相独立输出*/
InitMCPWM();
/* 捕获配置,用于检测霍尔信号 */
InitIC();
DelayNmSec(100);
/* 检测电源电压 */
PowerOnCheck();
/* 打开TIM3 */
T3CONbits.TON = 1;
/* 读取当前霍尔信号,打开PWM输出 */
while(1)
{
/* 根据模拟输入电压设定转速 */
VanalogConSpeed();
if(DesiredSpeed >= MINSPEED1000RPM)
{
MotorStart();
break;
}
}
/*缓启动*/
SlowStart();
while(1)
{
PidDesiredSpeed = DesiredSpeed;
/* 模拟电压调速*/
VanalogConSpeed();
/* 过流检测 */
OverCurCheck();
/* 电源电压检测*/
PowerCheck();
/* 200ms检测一次hall信号,连续两次出错认为异常 */
if((MsCountNum % 200) == 0)
{
HallErrCheck();
}
/* 每隔10ms检测一次温度 */
if((MsCountNum % 10) == 0)
{
TempCheck();
}
/*过/失速异常检测*/
if(FlagLowSpeedCheck == 1)
{
LowSpeedErrCheck();
}
OverSpeedErrCheck();
/* 检测到失速异常后10秒,重新打开点击 */
if((LowSpeedErrStopNum == 0) && (FlagLowSpeedStop == 1))
{
FlagLowSpeedStop = 0;
MotorReset();
}
/* 检测到过速异常后10秒,重新打开点击 */
if((OverSpeedErrStopNum == 0) && (FlagOverSpeedStop == 1))
{
FlagOverSpeedStop = 0;
MotorReset();
}
/* 检测到过流异常后10秒,重新打开电机 */
if((CurErrStopNum == 0) && (FlagOverCurStop == 1))
{
FlagOverCurStop = 0;
MotorReset();
}
}
return 0;
}
void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
for(j=0;j < 1000;j++);
}
/***********************************************************************************
* Function: lockIO
* Overview: This executes the necessary process to set the IOLOCK bit to lock
* I/O mapping from being modified.
*****************************************************************************/
void lockIO(void)
{
asm volatile ("mov #OSCCON,w1 \n"
"mov #0x46, w2 \n"
"mov #0x57, w3 \n"
"mov.b w2,[w1] \n"
"mov.b w3,[w1] \n"
"bset OSCCON, #6");
}
/*****************************************************************************
* Function: unlockIO
* Overview: This executes the necessary process to clear the IOLOCK bit to
* allow I/O mapping to be modified.
*****************************************************************************/
void unlockIO(void)
{
asm volatile ("mov #OSCCON,w1 \n"
"mov #0x46, w2 \n"
"mov #0x57, w3 \n"
"mov.b w2,[w1] \n"
"mov.b w3,[w1] \n"
"bclr OSCCON, #6");
}
/*****************************************************************
Fosc=Fin * M/(N1*N2)
M:PLL 反馈倍频比(28+2)
N1:预分频因子(2)
N2:后分频因子(2)
控制板使用的是8M晶振,因此Fosc = 8M*30/(2*2)=60M
器件工作频率Fcy=Fosc/2=30M
******************************************************************/
void PllOscConfig(void)
{
PLLFBD = 28;
CLKDIVbits.PLLPOST = 0;
CLKDIVbits.PLLPRE = 0;
__builtin_write_OSCCONH(0x03);
__builtin_write_OSCCONL(0x01);
while(OSCCONbits.COSC != 0b011);
/* Wait for PLL to lock */
while(OSCCONbits.LOCK != 1);
}
void PortConfig(void)
{
/*控制15V电源输出*/
LATBbits.LATB4 = 0;
TRI