本帖最后由 Angus 于 2018-11-4 20:06 编辑
CPU 控制 BLDC 转动的过程是检过零与换相轮流做,如下图, 鼠标左击看大图。
看上图,黑块时间是检测过零时间,约占用了 CPU 的 1/4 时间。
这里说一下 Mini51 D版芯片的自动换相功能:
每次换相后,要改变驱动 上MOS 的 PWM 输出引脚,改变驱动 下MOS 的 GPIO 输出 0 或 1 的状态,还要改变比较器的输入脚——换一相检测过 0 了。 Mini51 系列有个 换相寄存器:PWM-> PHCHG——phase change 之意, 写这一个寄存器,完成上面三件事。
还有一个下一相寄存器:PWM-> PHCHGNXT,这个寄存器定义与上述寄存器相同,Timer0 溢出时,PWM-> PHCHGNXT 的值会自动写入换相寄存器 PWM-> PHCHG 中。在 Timer1 中断代码里,检到过 0 时,就准备好下一相数据 PWM-> PHCHGNXT,并写好 Timer0 的溢出时间——换相时刻点。
Mini51 A 版芯片无此功能,购买芯片要问清楚,要买 D 版芯片。
void TMR1_IRQHandler(void)
{
TIMER0->CMPR = ~0 ; // 拉长 Timer0 时间,防止检过 0 时 Timer0 自动换相了
TIMER1->ISR = ~0 ; // 清中断标志
DeadLine_Detec = PeriodNow << 1 ; // 检过 0 超时时间, 防止中断内死等
do{
if((*pPhase) & DetectUpBit){
if(ACMP->SR & AcmpOutBit){ ++StepCount; break; } // 检到上过 0
}
else{
if((ACMP->SR & AcmpOutBit)==0){ ++StepCount; break;} // 检到下过 0
}
}while(TIMER0->DR < DeadLine_Detec) ;
PeriodLast = (TIMER1->DR - ZeroTick) & 0xFFFFFF ; // 两次过 0 时刻相减,得当前周期。
ZeroTick = TIMER1->DR ; // 本次过 0 时刻,下次计算周期用
PeriodNow = (PeriodNow + PeriodLast)>>1 ; // 软件滤波
if(PeriodNow > Period_Max) PeriodNow = Period_Max ;
TIMER0->CMPR = TIMER0->DR + (PeriodNow >> 1) ; // 延时周期的 1/2 时间后,换相
TIMER1->CMPR = TIMER1->DR + ((PeriodNow*3)>>2) ; // 延时周期的 3/4 时间后, Timer1 再次中断检过 0
if(++pPhase > pPhaseEnd) pPhase -= 6 ;
PWM-> PHCHGNXT = *pPhase ; // 这是下一相数据, Timer0 计数到 CMPR 时会自动写入PWM-> PHCHG 改变输出
}
改变导通角:
改变 TIMER0 的定时即可,比如写成 TIMER0->CMPR = TIMER0->DR + (PeriodNow >> 2) ; 过 0 后 1/4 周期换相,就等于换相超前了 15 度。
正反转:
转向由指针 pPhase 指向的数组决定。指向不同的数组,不仅可以实现正反转,还可改变上 MOS 或下 MOS 做 PWM等功能。
150 度方波:
Timer1 中断返回时刚好是过 0 时刻,这时立即换成两相同时输出,Timer0 定时到会自动变成下一相输出,这样就成了 150度方波 。
下载 Mini51 电调全部代码,请到"航模电调 DIY——第3季 Mini51ZDE 电调代码: http://www.nuvoton-mcu.com/forum.php?mod=viewthread&tid=1459&extra=page%3D1
|