- 打卡等级:初来乍到
- 打卡总天数:3
- 最近打卡:2025-10-14 07:50:57
已绑定手机
新手上路
- 积分
- 27
|
#define STARTUP_PWM 900 // 启动时的占空比 8元风扇电机, 12V-->300, 18V-->240, 24V-->200
#define STARTUP_INTERVAL 8000 // 启动时两次换向的最大间隔时间 us为单位
#define STARTUP_END_PhaseTime 12000 // 判断启动结束的换相时间us,8元风扇电机
#define COMMUNICATION_NUM 6
/******************* 强制电机启动函数 ***************************/
void PWMA_ISR(void) interrupt PWMA_VECTOR // 23.4375KHz(42.67us)中断率,用于处理启动电机,查询读取比较器结果
{
u16 i;
cmpo_state = (cmpo_state << 1) | (CMPCR1 & 1); // 读取比较器状态,放在一个字节中, 连续8次检测到相同电平才认为有效
if((cmpo_state & 0xff) == 0xff) B_cmpo = 1; //连续4个采样为1, 则比较器输出1
if((cmpo_state & 0xff) == 0x00) B_cmpo = 0; //连续4个采样为0, 则比较器输出0
if(run_mode == MOTOR_IDLE) //空闲模式
{
B_RUN = 0;
PWM_Value = 0; // 设置停止占空比
PWMA_CCR1 = PWM_Value;
PWMA_CCR2 = PWM_Value;
PWMA_CCR3 = PWM_Value;
}
else if(run_mode == MOTOR_PRE_POSITION) //预定位模式
{
if(SampleTime == 0) //刚开始, 启动前将SampleTime=0
{
step = 1;
StepMotor(); //换相一次
PWM_Value = STARTUP_PWM; // 设置启动占空比
PWMA_CCR1 = PWM_Value;
PWMA_CCR2 = PWM_Value;
PWMA_CCR3 = PWM_Value;
SampleTime = 1;
}
else if(++SampleTime >= (STARTUP_INTERVAL/43)) //预定位时间到,准备启动电机,预定位时间为最大换相时间, 43是PWM周期为43us(23.4K)
{
for(i=0; i<8; i++)
PhaseTimeTmp[i] = STARTUP_INTERVAL / 43; //初始默认最大换相时间
TimeIndex = 0;
commutation_num = 0; //启动换相次数累加
Degree30_time = 0;
SampleTime = STARTUP_INTERVAL / 43 / 4;
run_mode = MOTOR_STARTING; //下一个模式:启动模式
StepMotor(); //换相一次
SampleTime = 0; // 重置时间计数器
}
}
else if(run_mode == MOTOR_STARTING) //启动模式
{
SampleTime++;
if(Degree30_time != 0) //有30度角延时
{
if(--Degree30_time == 0) //30度角延时到,则换相
{
StepMotor(); //换相
commutation_num++; //启动换相次数累加
if ((commutation_num >= COMMUNICATION_NUM) && (PhaseTime <= 600))
{
B_startDone = 1; //已启动
B_start = 0; //已启动完成
B_RUN = 1; //已运行
run_mode = MOTOR_RUNNING;
Target_RollSpeed = Measure_RollSpeed; // 或根据 duty_run 推算
delay_us(50);
XiaoCiCnt = 0; //1:需要消磁, 2:正在消磁, 0已经消磁
if(step & 1) CMPCR1 = 0x8c + 0x20; // 比较器上升沿中断, PIE=1: 允许比较器上升沿中断, PIE=0: 禁止上升沿中断. NIE=1: 允许比较器下降沿中断, NIE=0: 禁止下降沿中断.
else CMPCR1 = 0x8c + 0x10; // 比较器下降沿中断, PIE=1: 允许比较器上升沿中断, PIE=0: 禁止上升沿中断. NIE=1: 允许比较器下降沿中断, NIE=0: 禁止下降沿中断.
}
}
}
else //检测反电动势过0
{
B_zcFound = 0;
if (step & 1)
{ // 上升沿检测
if (B_cmpo) B_zcFound = 1;
}
else
{ // 下降沿检测
if (!B_cmpo) B_zcFound = 1;
}
if (B_zcFound && (SampleTime > STARTUP_END_PhaseTime / 43 / 4)) //检测到过0事件, 换相时间过小则不换相
{
if(SampleTime > (STARTUP_INTERVAL / 43))
SampleTime = STARTUP_INTERVAL / 43; //换相过慢,
PhaseTimeTmp[TimeIndex] = SampleTime; //保存本次换相时间
SampleTime = 0;
if(++TimeIndex >= 8)
TimeIndex = 0; //索引溢出归0
for(PhaseTime8sum=0, i=0; i<8; i++)
PhaseTime8sum += PhaseTimeTmp[i]; //求8次换相时间累加和, 用于计算实时转速 = 1/(M*PhaseTime8sum*3/4) 转/秒 = 60/(M*PhaseTime8sum*3/4) 转/分,PhaseTime8sum*3/4为换相6次的时间,M为磁极对。
PhaseTime = PhaseTime8sum >> 3; //换相时间
if(PhaseTime >= 18) Degree30_time = PhaseTime / 2 - 4; //换相时间的一半, 即30度电角度, -8为修正8次采样时间
else Degree30_time = 1; //换相时间的一半, 即30度电角度
}
else if(SampleTime >= 1500) //超时重新预定位启动
{
SampleTime = 0;
run_mode = MOTOR_PRE_POSITION; //超时则重新 预定位启动
StepMotor(); //换相一次
}
}
}
if(B_RUN) PWMA_IER = 0; //如果电机已启动运行,则禁止PWMA中断
if(run_mode == MOTOR_IDLE) PWMA_IER = 0;
PWMA_SR1 = 0; //清除标志
}
|
|