| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- /**
- * @copyright None
- * @file BEMFDetect.c
- * @author Comment Vivre
- * @date 2024-08-28
- * @brief None
- */
- #include <MyProject.h>
- uint8 code table_Bemf_CWNext[6] = {3, 6, 2, 5, 1, 4};
- uint8 code table_Bemf_CWPre[6] = {5, 3, 1, 6, 4, 2};
- BEMFDetect_TypeDef xdata mcBemf;
- #if (TAILWIND_MODE == BEMFMethod)
- static void Cmp_Bemf_Init(void);
- static uint8 FR_Detect(uint8 bemfStatus, uint8 setFr);
- static void BEMFTailWindStart(void);
- /**
- @brief Bemf的顺逆风检测,比较器硬件初始化,注意需要核对IO是否对应
- @date 2022-07-09
- */
- static void Cmp_Bemf_Init(void)
- {
- /* -------------------------------------------------------------------------------------------------
- CMP Input Pin Mode
- 0: GPIO Mode, P1.4--CMP0_IN+, P1.6--CMP1_IN+, P2.1--CMP2_IN+
- P1.5--CMP0_IN-, P1.7--CMP1_IN-, P2.2--CMP2_IN-
- 1: BEMF Mode, 比较器正端连接到内部星型连接电阻U、V、W的BMEF采样点,
- 比较器负端连接到内部星型连接电阻的虚拟中性点
- 比较器负端与P1.5/P1.7/P2.2断开,这三个GPIO可做其他用途
- -------------------------------------------------------------------------------------------------*/
- SetBit(P1_AN, P14 | P16); // CMP0/1 Pin设置为模拟模式 +
- SetBit(P2_AN, P21); // CMP2 Pin设置为模拟模式 +
- ClrBit(P1_PU, P14); // P14上拉关闭
- /* -------------------------------------------------------------------------------------------------
- CMP0_MOD:
- 00: 无内置虚拟中心点电阻的BEMF模式
- 01: 内置虚拟中心点电阻的BEMF模式
- 10: 3差分比较器模式
- 11: 2比较器模式
- -------------------------------------------------------------------------------------------------*/
- SetReg(CMP_CR2, CMP0MOD0 | CMP0MOD1, CMP0MOD0);
- /* -------------------------------------------------------------------------------------------------
- 比较器输出选择配置,与CMP0_MOD配合使用
- CMP0_SEL[1:0]=00,比较器0工作在3比较器轮询模式,正端在CMP0P、CMP1P、CMP2P之间自动轮流选择,
- 负端固定接内置BEMF电阻的中心点,其输出结果分别送至CMP0_OUT、CMP1_OUT、CMP2_OUT
- CMP0_SEL[1:0]=01,比较器0选择CMP0对应的端口组合,正端接CMP0P,负端接内置BEMF电阻的中心点,输出接CMP0_OUT
- CMP0_SEL[1:0]=10,比较器0选择CMP1对应的端口组合,正端接CMP1P,负端接内置BEMF电阻的中心点,输出接CMP1_OUT
- CMP0_SEL[1:0]=11,比较器0选择CMP2对应的端口组合,正端接CMP2P,负端接内置BEMF电阻的中心点,输出接CMP2_OUT
- -----------------------------------------------------------------------------*/
- SetReg(CMP_CR2, CMP0SEL0 | CMP0SEL1, 0x00);
- /* -------------------------------------------------------------------------------------------------
- 比较器迟滞电压选择
- 000: 无迟滞 001: ±2.5mV 010: -5mV 011: +5mV
- 100: +-5mV 101: -10mV 110: +10mV 111: +-10mV
- -------------------------------------------------------------------------------------------------*/
- SetReg(CMP_CR1, CMP0HYS0 | CMP0HYS1 | CMP0HYS2, CMP0HYS0);
- /* -------------------------------------------------------------------------------------------------
- CMP0的轮询时间设置
- -------------------------------------------------------------------------------------------------*/
- SetReg(CMP_CR2, CMP0CSEL1 | CMP0CSEL0, 0x00);
- /* -------------------------------------------------------------------------------------------------
- 比较器中断模式配置 CMP_CR0[CMP2IM1], CMP_CR0[CMP2IM0]
- 00: 不产生中断 01: 上升沿产生中断 10: 下降沿产生中断 11: 上升/下降沿产生中断
- -------------------------------------------------------------------------------------------------*/
- SetReg(CMP_CR0, CMP2IM0 | CMP2IM1, CMP2IM0 | CMP2IM1);
- SetReg(CMP_CR0, CMP1IM0 | CMP1IM1, CMP1IM0 | CMP1IM1);
- SetReg(CMP_CR0, CMP0IM0 | CMP0IM1, CMP0IM0 | CMP0IM1);
- ClrBit(CMP_CR4, CMP0_FS); //CMP1/2功能转移 仅CMP0_MOD=01时有效
- SetBit(CMP_CR2, CMP0EN); //开三个比较器
- }
- /**
- @brief Timer2 初始化函数
- @date 2022-07-09
- */
- static void Time2_Bemf_Init(void)
- {
- /* -------------------------------------------------------------------------------------------------
- 先停止计数,配置完寄存器后,最后启动计数
- -------------------------------------------------------------------------------------------------*/
- ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
- /* -------------------------------------------------------------------------------------------------
- 时钟分频设置(T2PSC)
- 000:cpuclk(24MHz) 001:cpuclk/2^1(12MHz) 010:cpuclk/2^2(6MHz) 011:cpuclk/2^3(3MHz)
- 100:cpuclk/2^4(1.5MHz) 101:cpuclk/2^5(750KHz) 110:cpuclk/2^6(375KHz) 111:cpuclk/2^7(187.5KHz)
- -------------------------------------------------------------------------------------------------*/
- SetReg(TIM2_CR0, T2PSC0 | T2PSC1 | T2PSC2, T2PSC0 | T2PSC1 | T2PSC2);
- /* -------------------------------------------------------------------------------------------------
- /模式选择
- T2MODE1,T2MODE0
- 00--输入Timer模式;01--输出模式
- 10--输入Count模式;11--QEP或者ISD模式
- -------------------------------------------------------------------------------------------------*/
- SetReg(TIM2_CR0, T2MOD0 | T2MOD1, T2MOD0);
- /* -------------------------------------------------------------------------------------------------
- 清除中断标志位
- 禁止PWM周期检测中断使能
- -------------------------------------------------------------------------------------------------*/
- ClrBit(TIM2_CR0, T2CES); // 清零脉冲计数器不使能
- SetBit(TIM2_CR1, T2IFE); // 溢出中断使能
- ClrBit(TIM2_CR1, T2IR | T2IF | T2IP); // 清零中断标志位
- /* -------------------------------------------------------------------------------------------------
- 配置周期值、比较值、计数值
- 禁止PWM周期检测中断使能
- 使能计数器上溢中断使能
- -------------------------------------------------------------------------------------------------*/
- TIM2__ARR = 60000; // TIM2 Period = 0.32s
- TIM2__DR = TIM2__ARR;
- TIM2__CNTR = 0;
- /*-----------启动计数------------------------------------------------*/
- SetBit(TIM2_CR1, T2CEN); //启动计数
- }
- /**
- @brief 基于Bemf的顺逆风检测初始化函数,电机状态切入 顺逆风检测状态时 运行一次
- @date 2022-07-09
- */
- void BEMFDetectInit(void)
- {
- //BEMF检测前关闭mos输出
- mcBemf.BEMFSpeed = 0;
- mcBemf.BEMFSpeedBase = 0;
- mcBemf.Status = 0;
- mcBemf.FR = BEMF_FR_ERR;
- mcBemf.FRPre = BEMF_FR_ERR;
- mcBemf.SpeedUpdate = 0;
- mcBemf.BEMFSpeedBase = BEMFSpeedCalBase;
- mcBemf.HighSpdStart = 0;
- mcBemf.FR_SET = mcFocCtrl.FR;
- /* -----使能比较器----- */
- Cmp_Bemf_Init();
- /* -----使能定时器1用于检测时间----- */
- Time2_Bemf_Init();
- }
- /**
- @brief bemf顺序为 5,1,3,2,6,4
- @param bemfStatus 当前bemf状态
- @return BEMF_FR_CCW 反转
- @return BEMF_FR_CW 正转
- @return BEMF_FR_ERR 错误
- @date 2022-07-09
- */
- static uint8 FR_Detect(uint8 bemfStatus, uint8 setFr)
- {
- static uint8 temp_FR = 0;
- static uint8 temp_bemfStatusPre = 0;
-
- if (temp_bemfStatusPre == 0)
- {
- temp_bemfStatusPre = bemfStatus;
- temp_FR = BEMF_FR_ERR;
- }
-
- if (temp_bemfStatusPre != bemfStatus)
- {
- if (temp_bemfStatusPre == table_Bemf_CWPre[bemfStatus - 1])
- {
- if (setFr == CW) ///< 转向设置
- {
- temp_FR = BEMF_FR_CW;
- }
- else
- {
- temp_FR = BEMF_FR_CCW;
- }
- }
- else if (temp_bemfStatusPre == table_Bemf_CWNext[bemfStatus - 1])
- {
- if (setFr == CW) ///< 转向设置
- {
- temp_FR = BEMF_FR_CCW;
- }
- else
- {
- temp_FR = BEMF_FR_CW;
- }
- }
- else
- {
- temp_FR = BEMF_FR_ERR;
- }
-
- temp_bemfStatusPre = bemfStatus;
- }
-
- return temp_FR;
- }
- /**
- @brief void BemfProcess(void)基于Bemf的顺逆风检测,运行于Bemf检测比较器中断
- @date 2022-07-09
- */
- void BemfProcess(void)
- {
- static uint8 temp_Cnt = 0;
- static uint8 temp_SumCnt = 0;
- uint16 temp_Sum = 0;
- int16 temp_speedCal;
- mcBemf.FRPre = mcBemf.FR; // 获取上一次的转向
- mcBemf.FR = FR_Detect(CMP_SR & 0x07, mcBemf.FR_SET); // 获取当前转向
-
- if (mcBemf.FR == BEMF_FR_CW) // 当前为正转
- {
- if (mcBemf.FRPre == mcBemf.FR)
- {
- if (temp_Cnt > 5) // 防溢出越界
- {
- temp_Cnt = 0;
- }
-
- mcBemf.SectorTime[temp_Cnt++] = TIM2__CNTR;
-
- if (mcBemf.FRCount < 100)
- {
- mcBemf.FRCount++; // 连续两次均为正转则 正转计数+1
- }
-
- if (mcBemf.FRCount > 12)
- {
- temp_Sum = 0;
-
- for (temp_SumCnt = 0; temp_SumCnt < 6; temp_SumCnt++)
- {
- temp_Sum += (mcBemf.SectorTime[temp_SumCnt] >> 3); // 防止溢出
- }
-
- mcBemf.PeriodTime = temp_Sum;
- mcBemf.Status = BEMF_FORWARD; // 连续12次均为正向转动,则bemf状态切换为 BEMF_FORWARD
- }
- }
- else
- {
- mcBemf.FRCount = 0;
- mcBemf.Status = BEMF_DETECTING;
- }
- }
- else if (mcBemf.FR == BEMF_FR_CCW)
- {
- if (mcBemf.FRPre == mcBemf.FR)
- {
- if (temp_Cnt > 5) // 防溢出越界
- {
- temp_Cnt = 0;
- }
-
- mcBemf.SectorTime[temp_Cnt++] = TIM2__CNTR;
-
- if (mcBemf.FRCount > - 100)
- {
- mcBemf.FRCount--;// 连续两次均为反转则 反转计数+1
- }
-
- if (mcBemf.FRCount < -12)
- {
- temp_Sum = 0;
-
- for (temp_SumCnt = 0; temp_SumCnt < 6; temp_SumCnt++)
- {
- temp_Sum += (mcBemf.SectorTime[temp_SumCnt] >> 3); // 防止溢出
- }
-
- mcBemf.PeriodTime = temp_Sum;
- mcBemf.Status = BEMF_REVERSE;
- }
- }
- else
- {
- mcBemf.FRCount = 0;
- mcBemf.Status = BEMF_DETECTING;
- }
- }
- else
- {
- mcBemf.FRCount = 0; // 转向检测错误则清零转向计数
- mcBemf.Status = BEMF_DETECTING;
- }
-
- TIM2__CNTR = 0;
-
- if (mcBemf.Status == BEMF_FORWARD || mcBemf.Status == BEMF_REVERSE ) // 有效转向
- {
- // if (mcBemf.SpeedUpdate == 0)
- {
- if (mcBemf.PeriodTime < BEMFSpeedCalMinPeriod)
- {
- mcBemf.PeriodTime = BEMFSpeedCalMinPeriod ; // 防止mcRsd.PeriodTime 太小导致计算出错
- }
-
- temp_speedCal = DivQ_L_MDU(mcBemf.BEMFSpeedBase >> 16, mcBemf.BEMFSpeedBase, mcBemf.PeriodTime);
-
- if (mcBemf.Status == BEMF_REVERSE)
- {
- mcBemf.BEMFSpeed = -temp_speedCal;
- }
- else
- {
- mcBemf.BEMFSpeed = temp_speedCal;
- }
-
- mcBemf.SpeedUpdate = 1;
- }
- }
-
- if (mcBemf.HighSpdStart == 1) // 高速顺风启动
- {
- if ((CMP_SR & 0x07) == 0x01) // 01状态 对应0启动
- {
- ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
- ClrBit(TIM2_CR1, T2CEN); // 关闭定时器
- BEMFTailWindStart();
- mcBemf.HighSpdStart = 2; // 启动完成
- }
- }
- }
- MotStateType Bemf_Start_Process(void)
- {
- MotStateType returnStatus;
- returnStatus = mcTailWind;
-
- if (mcBemf.SpeedUpdate == 1)
- {
- if (mcBemf.BEMFSpeed < S_Value(-100)) // 逆风
- {
- mcFocCtrl.State_Count = 3000;
- ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
- ClrBit(TIM2_CR1, T2CEN); // 关闭定时器
- returnStatus = mcStart;
- mcFocCtrl.Start_Mode = HEADWIND_START;
- }
- // else if (mcBemf.BEMFSpeed < S_Value(-50)) //正转
- // {
- // mcBemf.SpeedUpdate = 0;
- // }
- else if (mcBemf.BEMFSpeed > S_Value(100)) //正转
- {
- if (mcBemf.HighSpdStart == 2) //启动完成,切状态机
- {
- mcFocCtrl.Start_Mode = TAILWIND_START;
- returnStatus = mcStart;
- }
-
- if (mcBemf.HighSpdStart == 0)
- {
- mcBemf.HighSpdStart = 1; // 设置启动
- }
- }
- else //其他,如静止
- {
- mcFocCtrl.Start_Mode = STATIC_START;
- returnStatus = mcStart;
- ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
- ClrBit(TIM1_CR0, T1BCEN); // 关闭定时器
- #if (ALIGN_MOME != ALIGN_DSIABLE)
- mcFocCtrl.mcPosCheckAngle = Align_Angle;
- returnStatus = mcAlign;
- mcFocCtrl.State_Count = Align_Time;
- #else
- returnStatus = mcStart;
- #endif
- }
- }
-
- return returnStatus;
- }
- static void BEMFTailWindStart(void)
- {
- /* FOC初始化 */
- FOC_Init();
- /* 启动电流、KP、KI */
- FOC_IDREF = ID_RUN_CURRENT; // D轴启动电流
- FOC_IQREF = IQ_RUN_CURRENT; // Q轴启动电流
- mcFocCtrl.IqRef = IQ_RUN_CURRENT; // Q轴启动电流
- FOC_DKP = _Q12(5.0);
- FOC_DKI = _Q15(0.5);
- FOC_QKP = _Q12(5.0);
- FOC_QKI = _Q15(0.5);
- FOC_EFREQACC = 500;
- FOC_EFREQMIN = MOTOR_OMEGA_RAMP_MIN;
- FOC_EFREQHOLD = MOTOR_OMEGA_RAMP_END;
- SetBit(FOC_CR1, ANGM); // 估算模式
- ClrBit(FOC_CR1, RFAE); // 禁止强拉
- SetBit(FOC_CR1, EFAE); // 估算器强制输出
- FOC_EKP = OBSW_KP_GAIN_RUN4;
- FOC_EKI = OBSW_KI_GAIN_RUN4;
- FOC_OMEKLPF = SPEED_KLPF;
- mcFocCtrl.CtrlMode = 0;
- /* 使能输出 */
- DRV_CMR |= 0x3F; // U、V、W相输出
- MOE = 1;
- EA = 1;
- }
- #endif
|