先了解一下FU6832的相关性能与一些配置,具体如下:
FU6832系列电机驱动专用芯片集成了电机控制引擎(ME)和8051内核,为电机控制提供了高性能的解决方案。这款芯片特别适用于无刷直流电机(BLDC)和永磁同步电机(PMSM)的驱动控制,支持方波、空间矢量脉宽调制(SVPWM)/正弦脉宽调制(SPWM)以及磁场定向控制(FOC)等多种控制策略。
主要特性:
双核并行工作:ME引擎负责电机控制的复杂运算,而8051内核则用于参数配置和日常事务处理,提高了整体性能和响应速度。 高速指令执行:8051内核大部分指令周期为1T或2T,保证了快速的数据处理和参数更新。
集成的硬件模块:FOC、MDU、LPF、PI、SVPWM/SPWM等硬件模块可自动完成电机控制的核心运算,简化了软件开发的复杂性。
核心组成:FU6832L芯片集成了电机控制引擎(ME)和8051内核,实现了双核并行工作。 8051内核:大部分指令周期为1T或2T,支持高速的数据处理和参数配置。
ME特性:集成有FOC(磁场定向控制)、MDU(电机驱动单元)、LPF(低通滤波器)、PI(比例积分控制器)、SVPWM/SPWM(空间矢量脉宽调制/正弦脉宽调制)等硬件模块,可自动完成电机FOC/BLDC运算控制。 多种通信接口:CRC、SPI、I2C、UART、LIN等通信接口使得芯片能够方便地与其他设备进行数据交换。
内置功能丰富:芯片内部集成了高速运算放大器、比较器、Pre-driver、高速ADC、高速乘/除法器等,为电机控制提供了强大的硬件支持。 无感运行FOC驱动:有感启动后,可切换至无感运行状态,降低了对传感器的依赖,提高了系统的可靠性。
有感启动无感运行FOC驱动的使用方法: 初始化配置:使用8051内核对芯片进行初始化配置,包括设置通信接口、配置电机参数、选择控制模式等。 无感运行:当电机达到稳定运行状态后,可切换至无感运行模式,此时不再依赖传感器提供的位置和速度信息,而是通过ME引擎根据电机的电气参数进行估算和控制。 实时调整:在电机运行过程中,8051内核可以根据需要实时调整控制参数,电流、速度、转矩等,以满足不同的应用需求。
以上是对FU6832L_V3开发板的具体介绍,下面开始对BLDC电机驱动详细说明:
1、原理图:

MOS管在BLDC电机驱动电路中的主要作用是作为开关元件,通过控制其通断来驱动电机三相绕组的电流。
- 通过精确控制MOS管的开关状态,可以实现电机的高效率、高精度驱动。
- 在选择适用于BLDC电机驱动的MOS管时,需要考虑多个参数,输入电压、输出电压、电源电压范围、静态功耗、动态功耗、频率响应、输入电阻和输出电阻以及电机工作电压等。
- 这些参数的选择需要根据电机的具体需求和驱动电路的设计来确定。BLDC电机驱动电路通常采用三相全桥结构,其中每一相都包含两个MOS管(一个上桥臂和一个下桥臂)上图所示。
- 通过控制这三个上桥臂和三个下桥臂的MOS管开关状态,可以实现电机三相绕组的电流控制。
霍尔检测电路接口
保护电路:防止电压超过霍尔传感器的工作电压范围。
上拉电阻(R12/14/15):确保在没有磁场作用时,霍尔传感器的输出处于确定状态。
限流电阻(R22/19/16):限制通过霍尔传感器的电流,以保护其免受损坏。
滤波电容(C2/19/17):滤除噪声和杂散信号,提高测量的准确性和稳定性。

测量电路:接收霍尔电势差并进行放大和测量,最终得到与磁场强度成正比的电压信号。
主控:

BLDC电机FU6832L主控是一款高性能的电机驱动专用芯片,专为BLDC(Brushless Direct Current,无刷直流)电机控制而设计。
代码:
电机控制状态机 , 电机的状态只能在电机状态控制中切换,禁止在其他地方切换电机状态
void MC_Control(void)
{
// 根据mcState的值来决定执行哪个case
switch (mcState)
{
case mcReady: // 如果当前状态是mcReady
Motor_Ready(); // 执行电机就绪操作
// 如果存在故障源(mcFaultSource不等于FaultNoSource)
if (mcFaultSource != FaultNoSource)
{
// 将状态设置为mcFault
mcState = mcFault;
}
// 如果电流偏移标志被设置(OffsetFlag为1),并且控制电源已开启(isCtrlPowOn为true)
// 并且直流母线电压在恢复阈值范围内(mcDcbusFlt在OVER_VOLTAGE_RECOVER和UNDER_VOLTAGE_RECOVER之间)
else if ((mcCurOffset.OffsetFlag == 1) && (isCtrlPowOn == true) &&
(mcFocCtrl.mcDcbusFlt < OVER_VOLTAGE_RECOVER) &&
(mcFocCtrl.mcDcbusFlt > UNDER_VOLTAGE_RECOVER))
{
// 将状态设置为mcInit,并重置电流偏移标志和计数
mcState = mcInit;
mcCurOffset.OffsetFlag = 0;
mcCurOffset.OffsetCount = 0;
}
break; // 结束mcReady的case
case mcInit: // 如果当前状态是mcInit
// 如果存在故障源(mcFaultSource不等于FaultNoSource)
if (mcFaultSource != FaultNoSource)
{
// 将状态设置为mcFault
mcState = mcFault;
}
// 如果控制电源已关闭(isCtrlPowOn为false)
else if (isCtrlPowOn == false)
{
// 将状态设置为mcStop
mcState = mcStop;
}
else
{
// 执行电机初始化操作
Motor_Init();
#if (CHARGE_EN == Enable)
mcFocCtrl.State_Count = CHARGE_TIME;
mcState = mcCharge; // 跳入mcCharge状态
#else
#if (TAILWIND_MODE == NoTailWind)
#if (PosCheckEnable == Enable)
mcState = mcPosiCheck;
McStaSet.SetFlag.PosiCheckSetFlag = 0;
mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值
#elif (ALIGN_MOME != ALIGN_DSIABLE)
mcFocCtrl.mcPosCheckAngle = Align_Angle;
mcState = mcAlign;
mcFocCtrl.State_Count = Align_Time;
#else
mcState = mcStart;
#endif
#else
mcFocCtrl.State_Count = TAILWIND_TIME; //顺逆风判断时间
mcState = mcTailWind;
#endif
#endif
}
break;
case mcCharge:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (isCtrlPowOn == false)
{
mcState = mcStop;
}
else
{
Motor_Charge();
if (mcFocCtrl.State_Count == 0)
{
MOE = 0; // 关闭输出
#if (TAILWIND_MODE == NoTailWind)
#if (PosCheckEnable == Enable)
mcState = mcPosiCheck;
McStaSet.SetFlag.PosiCheckSetFlag = 0;
mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值
#elif (ALIGN_MOME != ALIGN_DSIABLE)
mcFocCtrl.mcPosCheckAngle = Align_Angle;
mcState = mcAlign;
mcFocCtrl.State_Count = Align_Time;
#else
mcState = mcStart;
#endif
#else
mcFocCtrl.State_Count = TAILWIND_TIME; //顺逆风判断时间
mcState = mcTailWind;
#endif
}
}
break;
#if (TAILWIND_MODE != NoTailWind)
case mcTailWind:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (isCtrlPowOn == false)
{
mcState = mcStop;
}
else
{
if (McStaSet.SetFlag.TailWindSetFlag == 0) //初始化
{
SetBit(DRV_CR , DRVEN); // 计数器使能 0-->Disable 1-->Enable
McStaSet.SetFlag.TailWindSetFlag = 1;
#if (TAILWIND_MODE == RSDMethod)
RSDDetectInit();
#elif (TAILWIND_MODE == BEMFMethod)
BEMFDetectInit();
#endif
}
#if (TAILWIND_MODE == RSDMethod)
if (mcFocCtrl.State_Count > 0) // 顺逆风检测时间结束前判断转速
{
mcState = RSDStartProcess();
}
else // 时间结束 还未检测到有效转速 则当做静止启动
{
ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
mcFocCtrl.Start_Mode = STATIC_START;
#if (PosCheckEnable == Enable)
mcState = mcPosiCheck;
McStaSet.SetFlag.PosiCheckSetFlag = 0;
mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值
#elif (ALIGN_MOME != ALIGN_DSIABLE)
mcFocCtrl.mcPosCheckAngle = Align_Angle;
mcState = mcAlign;
mcFocCtrl.State_Count = Align_Time;
#else
mcState = mcStart;
#endif
}
#elif (TAILWIND_MODE == BEMFMethod)
if (mcFocCtrl.State_Count > 0) // 顺逆风检测时间结束前判断转速
{
mcState = Bemf_Start_Process();
}
else // 时间结束 还未检测到有效转速 则当做静止启动
{
ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
ClrBit(TIM1_CR0, T1BCEN); // 关闭定时器
mcFocCtrl.Start_Mode = STATIC_START;
#if (PosCheckEnable == Enable)
mcState = mcPosiCheck;
McStaSet.SetFlag.PosiCheckSetFlag = 0;
mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值
#elif (ALIGN_MOME != ALIGN_DSIABLE)
mcFocCtrl.mcPosCheckAngle = Align_Angle;
mcState = mcAlign;
mcFocCtrl.State_Count = Align_Time;
#else
mcState = mcStart;
#endif
}
#endif
}
break;
#endif
#if (PosCheckEnable == Enable)
case mcPosiCheck:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (isCtrlPowOn == false)
{
mcState = mcStop;
}
else
{
if (mcFocCtrl.State_Count == 0)
{
mcFocCtrl.mcPosCheckAngle = 0;
mcState = mcAlign;
mcFocCtrl.State_Count = Align_Time;
}
}
break;
#endif
#if (ALIGN_MOME != ALIGN_DSIABLE)
case mcAlign:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (isCtrlPowOn == false)
{
mcState = mcStop;
}
else
{
Motor_Align();
#if (ALIGN_MOME == ALIGN_TEST)
while (1);
#else
if (mcFocCtrl.State_Count == 0)
{
mcState = mcStart;
}
#endif
}
break;
#endif
case mcStart:
if (mcFocCtrl.Start_Mode == TAILWIND_START) // 顺风启动
{
#if (TAILWIND_MODE == BEMFMethod)
mcState = mcRun;
#elif (TAILWIND_MODE == RSDMethod)
mcState = mcRun;
#endif
}
else if (mcFocCtrl.Start_Mode == HEADWIND_START) // 逆风启动
{
if(mcFocCtrl.State_Count > 0) // 逆风启动刹车过程
{
// 配置刹车代码
MC_Break();
}
else
{
mcFocCtrl.State_Count =100; // 顺逆风判断时间
mcState = mcReady; // 刹车结束 切回顺逆风检测
}
}
else // 静止启动
{
Motor_Static_Open();
mcState = mcRun;
}
break;
case mcRun:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (isCtrlPowOn == false)
{
mcState = mcStop;
mcFocCtrl.State_Count = 10; //单位:1ms
}
break;
case mcStop:
// if (mcFaultSource != FaultNoSource)
// {
// mcState = mcFault;
// }
// else
// {
if (( mcFocCtrl.PowerFlt < Motor_Max_Power) || (mcFocCtrl.State_Count == 0))
{
if (StopBrakeFlag == 0)
{
mcState = mcReady;
// MOE = 0;
FOC_CR0 = 0x00;
ClrBit(DRV_CR, FOCEN);
}
else
{
// if (mcFocCtrl.SpeedFlt < Stop_MOTOR_SPEED_RPM)
// {
MOE = 0;
MC_Break(); // 配置刹车代码
mcState = mcBrake;
mcFocCtrl.State_Count = StopWaitTime;
// }
}
}
// }
break;
case mcBrake:
if (mcFaultSource != FaultNoSource)
{
mcState = mcFault;
}
else if (mcFocCtrl.State_Count == 0)
{
MOE = 0;
ClrBit(DRV_CR, FOCEN);
mcState = mcReady;
}
break;
case mcFault:
if (mcFaultSource == FaultNoSource) //保护清零后关闭输出,软件重新运行
{
mcState = mcReady;
}
else
{
Pdelay_OFF;
ClrBit(DRV_CR, FOCEN); //FOC Disable
MOE = 0;
}
break;
default:
mcState = mcReady;
break;
}
}
void TailWindSpeedDetect(void)
{
static int16 LatestTheta;
if (mcState == mcTailWind)
{
//顺风检测过程由于FOC内部根据电流估算角度,故直接对FOC_ETHETA进行处理
if (TailWindDetect.MotorTailWindState == NormalTailWind)
{
LatestTheta = FOC__ETHETA;
//旋转方向判断在 <-170度 <10 >-10 >170度三个状态切换的时间
if (LatestTheta < -30946)
{
//计数器未清零或从状态3跳到状态1时清零
if ((TailWindDetect.SpeedTimerClearStatus == 0) || (TailWindDetect.AngleState == 3))
{
TailWindDetect.SpeedCountTimer = 0;
TailWindDetect.SpeedTimerClearStatus = 1;
if (TailWindDetect.AngleState == 3)
{
TailWindDetect.ShakeTimes ++; //来回1和3之间抖动,抖动次数加1
}
}
//<-170度 时设置状态为1,并清零SpeedCountTimer在TIM5中计时
TailWindDetect.AngleState = 1;
}
else if ((LatestTheta > -1820) && (LatestTheta < 1820)) //<10 >-10
{
//状态1或状态3切换到状态2时保存当前转速时间至TailWindDetect.SpeedCount[SpeedStoreNum]
if ((TailWindDetect.AngleState == 1) || (TailWindDetect.AngleState == 3))
{
//计算当前转速,RPM
TailWindDetect.SpeedCountTimer += 1;//防止为0
DivQ_L_MDU(((TailWindDetect.TempThailWindSpeedBase) >> 16), TailWindDetect.TempThailWindSpeedBase, TailWindDetect.SpeedCountTimer, TailWindDetect.TailWindSpeed);
TailWindDetect.SpeedStoreNum ++;
//用于SpeedCountTimer清零
if (TailWindDetect.SpeedTimerClearStatus == 1)
{
TailWindDetect.SpeedTimerClearStatus = 0;
}
//有1状态切换到2状态说明角度递增旋转方向为CW,3->2则为CCW
if (TailWindDetect.AngleState == 1)
{
TailWindDetect.MotorDir = CW;
}
else if (TailWindDetect.AngleState == 3)
{
TailWindDetect.MotorDir = CCW;
}
TailWindDetect.ShakeTimes = 0;//清除来回抖动的计数
}
TailWindDetect.AngleState = 2;
}
//>170度时
else if (LatestTheta > 30946)
{
//计数器未清零或从状态1跳到状态3时清零
if ((TailWindDetect.SpeedTimerClearStatus == 0) || (TailWindDetect.AngleState == 1))
{
TailWindDetect.SpeedCountTimer = 0;
TailWindDetect.SpeedTimerClearStatus = 1;
if (TailWindDetect.AngleState == 1)
{
TailWindDetect.ShakeTimes ++; //来回1和3之间抖动
}
}
TailWindDetect.AngleState = 3;
}
}
}
}
主函数:
uint32 PowerUpCnt = 0;
/* ----- 上电空指令延时 等待系统稳定 ----- */
for (PowerUpCnt = 0; PowerUpCnt < SystemPowerUpTime; PowerUpCnt++);
/* ----- 部分变量初始化 ----- */
SoftwareInit();
/* ----- 硬件初始化,配置MCU外设 ----- */
HardwareInit();
/* ----- 等待硬件初始化稳定 ----- */
for (PowerUpCnt = 0; PowerUpCnt < SystemPowerUpTime; PowerUpCnt++);
// #if (DBG_MODE != DBG_DISABLE) // 调试小工具
// /* -----debug配置(SPI调试),量产程序可以删除----- */
// DebugSet();
// #endif
// SetReg(CMP_CR3, DBGSEL1 | DBGSEL0, DBGSEL1); // ADC trig
while (1)
{
/* -----获取电流采样偏置电压----- */
if (!mcCurOffset.OffsetFlag)
{
GetCurrentOffset();
}
else
{
/* -----电机控制状态机----- */
MC_Control();
mcFocCtrl.mcUqvlue = FOC__UQ;
mcFocCtrl.mcUdvlue = FOC__UD;
if (g_1mTick)
{
TickCycle_1ms();
g_1mTick = 0;
}
}
}
}
视频:
实际波形:




全部评论