电调,mega8控制的问题,求指教
大概设计思路如下:1、mega通过定时器的输入捕获获取主控的PPM信号(ppm信号的周期为2.2ms),计算得到对应PWM占空比从而控制电机的转速,通过输入捕获中断执行;
2、电机通过过零检测实行换相,使用的是mega8的模拟比较器,比较器正相输入端接中间电平,反相输入端接A、B、C端。通过比较器输出电平的变化进入模拟比较器的中断实行换相;
问题是:
1、对上述两个中断采取默认设置的话(既不实行中断嵌套),输入捕获进中断的周期为4.4ms(按理说其周期应同于PPM2.2ms),从而影响了电机的调速控制。我认为是模拟比较器的中断影响了输入捕获的中断。查阅datasheet,资料讲mega8一旦进入中断服务程序,则清零全局中断使能,从而所有的其他中断被挂起等待。而模拟比较器进中断的频率远高于输入捕获进中断的频率。
2、根据datasheet上讲明的,我在模拟比较器的中断服务程序一开始执行力sei指令(打开全局中断,从而其他中断可中断掉模拟比较器的中断服务程序,实现中断的嵌套),示波器测得输入捕获的中断的进入周期为2.2ms。但是接上电机后,发现电机不能正常换相了,是不是输入捕获的中断又影响了电机的换相?
3、这两者的中断该如何协调了?
还有一个问题是,我按照MK的电机启动代码进行的设置,发现了一个问题:在对电机多次进行通电、断电的实验时,前几次(大概在四次左右)电机能够顺利的进行启动转起来,后续的实验电机启动后就不能正常旋转了,需要等待一段时间再通电才能正常启动,旋转这又是为什么?
附上模块代码,希望能得到帮助:
1、启动模块代码:
//电机启动
uint8_t MotorStartUp(uint8_t pm)
{
uint16_t i, timer = 300;
DISABLE_SENSE_INT; //关闭模拟比较器的中断
DISABLE_ICP1; //关闭输入捕获的中断
PWM = 5;
SetPWM(PWM); //设定PWM的值
PWM = pm;
Phase = 0;
while(1)
{
for(i = 0; i < timer; i++)
{
delay_us(100); //Wait(100)=延时0.1ms
}
//timer每次减少1/15,若减少到一定程度则说明已经转起来了(经计算循环51次),返回1
if(timer >= 25)timer -= timer/15 + 1;
if(timer < 25)
{
return 1;
}
Manual();
Phase++;
Phase %= 6;
PWM = pm;
SetPWM(PWM);
//若比较器中断标志被置位
if(SENSE)
LEDGRN_ON;
}
return 0;
}
//根据当前的Phase值驱动相应的MOS管工作
void Manual()
{
switch(Phase)
{
case 0: //AB导通PWM
PWM_A_ON; //A相上桥臂通
MUTEX_NEG_B_ON; //B相下桥臂通
SENSE_C; //比较器反相输入端检测C相
SENSE_RISING_INT; //比较器输出上升沿检测
break;
case 1: //AC导通PWM
PWM_A_ON;
MUTEX_NEG_C_ON;
SENSE_B;
SENSE_FALLING_INT;
break;
case 2: //BC导通PWM
PWM_B_ON;
MUTEX_NEG_C_ON;
SENSE_A;
SENSE_RISING_INT;
break;
case 3: //BA导通PWM
PWM_B_ON;
MUTEX_NEG_A_ON;
SENSE_C;
SENSE_FALLING_INT;
break;
case 4: //CA导通PWM
PWM_C_ON;
MUTEX_NEG_A_ON;
SENSE_B;
SENSE_RISING_INT;
break;
case 5: //CB导通PWM
PWM_C_ON;
MUTEX_NEG_B_ON;
SENSE_A;
SENSE_FALLING_INT;
break;
}
}
//模拟比较器中断
SIGNAL(ANA_COMP_vect)
{
//sei();
uint8_t sense = 0;
do
{
if(SENSE_H) sense = 1;
else sense = 0;
switch(Phase)
{
case 0: //AB导通PWM
PWM_A_ON;
if(sense)
{
MUTEX_NEG_C_ON;
SENSE_B;
SENSE_FALLING_INT;
Phase++;
}
else
{
MUTEX_NEG_B_ON;
}
break;
case 1: //AC导通PWM
MUTEX_NEG_C_ON;
if(!sense)
{
PWM_B_ON;
SENSE_A;
SENSE_RISING_INT;
Phase++;
}
else
{
PWM_A_ON;
}
break;
case 2: //BC导通PWM
PWM_B_ON;
if(sense)
{
MUTEX_NEG_A_ON;
SENSE_C;
SENSE_FALLING_INT;
Phase++;
}
else
{
MUTEX_NEG_C_ON;
}
break;
case 3: //BA导通PWM
MUTEX_NEG_A_ON;
if(!sense)
{
PWM_C_ON;
SENSE_B;
SENSE_RISING_INT;
Phase++;
}
else
{
PWM_B_ON;
}
break;
case 4: //CA导通PWM
PWM_C_ON;
if(sense)
{
MUTEX_NEG_B_ON;
SENSE_A;
SENSE_FALLING_INT;
Phase++;
}
else
{
MUTEX_NEG_A_ON;
}
break;
case 5: //CB导通PWM
MUTEX_NEG_B_ON;
if(!sense)
{
PWM_A_ON;
SENSE_C;
SENSE_RISING_INT;
Phase=0;
}
else
{
PWM_C_ON;
}
break;
}
ACSR|=0x10;
ENABLE_SENSE_INT;
ACSR&=~0X04;
TIFR|=1<<5;
} while((SENSE_L && sense) || (SENSE_H && ! sense));
}
//输入捕获中断
SIGNAL(TIMER1_CAPT_vect)
{
if(!cnt)
{
PORTB|=0x40;
tim_alt_start=ICR1;
PPM_L;
TIFR|=1<<5;
flag_start=flag;
TimerOverflow=0;
cnt=1;
}
else
{
tim_alt_end=ICR1;
PPM_H;
TIFR|=1<<5;
flag_end=flag;
cnt=0;
switch (flag_start)
{
case 0:
switch (flag_end)
{
case 0:
if (tim_alt_start>tim_alt_end)
{
ppm=TimerOverflow*512-(tim_alt_start-tim_alt_end);
}
else
{
ppm=TimerOverflow*512+(tim_alt_end-tim_alt_start);
}
break;
case 1:
ppm=TimerOverflow*512+(255-tim_alt_start)+(255-tim_alt_end);
break;
}
break;
case 1:
switch (flag_end)
{
case 0:
ppm=TimerOverflow*512-(255-tim_alt_end)-(255-tim_alt_start);
break;
case 1:
if (tim_alt_start<tim_alt_end)
{
ppm=TimerOverflow*512-(tim_alt_end-tim_alt_start);
}
else
ppm=TimerOverflow*512+(tim_alt_start-tim_alt_end);
break;
}
}
if(ppm<1500)
ppm=1000;
if(ppm>2000)
ppm=2000;
ppm-=1000;
PPM_Signal=(PPM_Signal*47+ppm)/48;
pwm_value=(uint8_t)((double)PPM_Signal*0.255);
//SetPWM(pwm_value);
Usart_putchar(pwm_value);
PORTB&=~0x40;
}
}
已经被困惑了好几天了,希望得到帮助,谢谢!!! 顶一下, 自己顶下,求关注!!!!!!!!!!!!!!! 顶顶更健康,同时学习下
页:
[1]