|
发表于 2009-12-3 10:32:28
|
显示全部楼层
德国程序很复杂,看看我自己写的M48程序——
int i2c_cmd=127; //设置接口变量,将"twislave.c"里的i2c油门型号引用到"main.c"里面
unsigned char bldc_rpm=0; //定义从机当前转速以便传递给主机。
int count_rpm=0; //用于记录霍尔变化的次数,与时间片计算出即时转速。
int count_time=0; //用于累计定时器溢出的中断次数,从而得到一个时间片段。
unsigned char PWM_UP=0;
unsigned char PWM_LOW=0;
char dir = 1;
int adj_cmd=0;
char flag=1;
void PORT_Init(void) //端口初始化。
{
PORTB = 0X00;
DDRB = 0X01; //PB0-LED;PB1-OC1A;PB2-OC1B;PB3-OC2A
PORTD = 0X00;
DDRD = 0X80; //PD3-OC2B;PD5-OC0B;PD6-OC0A;PD0-PD1-PD2霍尔输入;PD7故障指示。
}
void Timer0_Init(void) //定时器0初始化。
{
TCNT0 = 0x00;
TCCR0B = 0X01;
TIMSK0 = 0x01; //timer 0 overflow interrupt sources,中断初始化定时器0
OCR0A = 0; //*****无指令时输出o********
OCR0B = 0; //*****无指令时输出o********
}
void Timer1_Init(void) //定时器1初始化。
{
TCNT1 = 0x00;
TCCR1B = 0X01;
OCR1A = 0; //*****无指令时输出o********
OCR1B = 0; //*****无指令时输出o********
}
void Timer2_Init(void) //定时器2初始化。
{
TCNT2 = 0x00;
TCCR2B = 0X01;
OCR2A = 0; //*****无指令时输出o********
OCR2B = 0; //*****无指令时输出o********
}
void run(void) //运行函数,用于旋转方向选择和换相表调用。
{
//change_phase_function_CCW();
if(dir==1) change_phase_function_CW();
else if(dir==0)change_phase_function_CCW();
}
//绝对值函数
int ABS(int val)
{
if(val>=0) return val;
else return (-val);
}
void pwm(int pwm_cmd) //PWM宽度产生函数,将i2c_cmd指令变化为定时器的脉冲宽度。并生成方向标志。
{
pwm_cmd=pwm_cmd-127;//计算与过渡点的差值。
if(pwm_cmd<0) //
{
dir=0; //计算出正反转的方向标志,127为正反转过渡点。
PORTD&=0b01111111; //PD7为方向指示灯,将其关闭。
}
else if(pwm_cmd>0)
{
dir=1;
PORTD|=0b10000000; //PD7为方向指示灯,将其点亮。
}
pwm_cmd=ABS(pwm_cmd);//计算与过渡点的差值的绝对值。
pwm_cmd=255-(pwm_cmd*2);//还原转速指令,255最大。
if(adj_cmd<pwm_cmd) adj_cmd++;//pwm有变化时才赋值定时器匹配值。
else adj_cmd--;
//bldc_rpm=pwm_cmd;
PWM_UP= adj_cmd;
PWM_LOW= adj_cmd+1;
if(PWM_UP>=253)PWM_UP = 253; //封顶高端管pwm
if(PWM_LOW>=254)PWM_LOW = 254; //封顶低端管pwm
OCR0A = PWM_UP;
OCR0B = PWM_LOW;
OCR1A = PWM_UP;
OCR1B = PWM_LOW;
OCR2A = PWM_UP;
OCR2B = PWM_LOW;
//last_cmd=pwm_cmd;
}
/*******************************************/
/*霍尔信号电平变化中断*/
/*******************************************/
SIGNAL(SIG_PIN_CHANGE2)
{
//TCNT0 = 0x00;
//TCNT1 = 0x00;
//TCNT2 = 0x00;
//count_rpm++; //累计转速
//close_drive_function(); //捕捉换向后,首选关闭输出。
PORTB^=0b00000001; //霍尔信号变化,则工作指示灯不断闪
run(); //运转bldc
flag=1;
}
//定时器0溢出中断函数
SIGNAL(SIG_OVERFLOW0)
{
//pwm(i2c_cmd); //调用pwm函数将I2C指令转速赋值给定时器,以产生需要的脉冲宽度。
count_time++; //累计时间片
if(count_time>=9)
{
flag=0;
count_time=0;
}
//if (count_time>=900) //16khz的pwm周期大约为60us,900个周期为50ms,功率管堵转保护。
{
//if(PWM_UP!=0&&count_rpm<3) //大约每分钟15转,小于则堵转保护。
{
//close_drive_function(); //堵转保护,关闭输出。
//PORTD^=0b10000000; //故障时,则工作指示灯不断闪
//PWM_UP=0;
}
//else PORTD&=0b01111111; //故障恢复,则工作指示灯停止闪
//bldc_rpm=(count_rpm)/126*20; //计算出RPM,21极bldc,每转产生21×6=126个状态。
//count_time=0;
//count_rpm=0;
}
}
int main(void)
{
PORT_Init();
Timer0_Init();
Timer1_Init();
Timer2_Init();
PCICR=0b00000100; //使能第二组引脚中断。
PCMSK2=0b0000111; //使能PCINT16,PCINT17和PCINT18的引脚电平变化中断,以捕获霍尔信号
SREG|=0b10000000; //开总中断
//_delay_ms(30); //大约延时30ms
pwm(i2c_cmd); //调用pwm函数将I2C指令转速赋值给定时器,以产生需要的脉冲宽度。
run(); //启动后进行霍尔状态的一次识别。
InitIC2_Slave(0x50); //设置I2C地址,并启动I2C总线。
while(1)
{
if (flag==1) //换相补偿,换相后由于感性负载电流滞后,将前9个脉冲宽度加大,
{ //以使换相后电流快速上升到换相前水平。
OCR0A = 255-5*count_time;
OCR0B = 255-5*count_time;
OCR1A = 255-5*count_time;
OCR1B = 255-5*count_time;
OCR2A = 255-5*count_time;
OCR2B = 255-5*count_time;
}
else pwm(i2c_cmd); //调用pwm函数将I2C指令转速赋值给定时器,以产生需要的脉冲宽度。
; }
} |
|