int ReplyDataCom( void *Data, int size ) { int len; char *data, *Pchar; data = (char *)Data; Pchar = (char *)(DHO.Cmd.Command); Swapb( Pchar[0], Pchar[3] ); Swapb( Pchar[1], Pchar[2] ); DHO.FrameNumber = 0; DHO.Status &= (~stPacketDone); DHO.mbRead = size; while( size > 0 ) { if( size > MaxComPacket ) len = MaxComPacket; else len = size; if( (size-len) <= 0 ) DHO.Status |= stPacketDone; DHO.LenData = len; SendUart( &DHO, -sizeof( TMessageHeader) ); SendUart( data, len ); size -= len; data += len; DHO.FrameNumber++; } DHO.Status = 0; return 0; }
//############################################################################ //启动代码,pwm为启动时的占空比 char Anwerfen(unsigned char pwm) //############################################################################ { unsigned long timer = 300,i; DISABLE_SENSE_INT; //关掉模拟比较器中断 PWM = 5; SetPWM(); Manuell(); // Delay_ms(200); MinUpmPulse = SetDelay(300); /* * 延时300ms,期间不断检测电流,如果电流大于12A,关掉所有MOSFET,红灯闪10下 */ while(!CheckDelay(MinUpmPulse)) { FastADConvert(); if(Strom > 120) { STEUER_OFF; // Abschalten wegen Kurzschluss RotBlink(10); return(0); // 启动失败 } } PWM = pwm; // pwm = 10 while(1) // main starup program { for(i=0;i<timer; i++) // timer = 300 { if(!UebertragungAbgeschlossen) SendUart(); //UebertragungAbgeschlossen用来表示串口当前是否正忙,0不忙,1忙 else DatenUebertragung(); Wait(100); // wait 100us } DebugAusgaben(); //将一些当前信息写到调试结构中去 FastADConvert(); if(Strom > 60) { STEUER_OFF; // Abschalten wegen Kurzschluss RotBlink(10); return(0); } timer-= timer/15+1; // actually, 14/15 of timer if(timer < 25) { if(TEST_MANUELL) timer = 25; else return(1); } // timer is going to converge, utiil it is less than 25, it stops. Manuell(); Phase++; Phase %= 6; AdConvert(); //检测shunt上电流 PWM = pwm; SetPWM(); if(SENSE) //若模拟比较器中断位置标志,则此表达式为非零 { PORTD ^= GRUEN; } } }
int SendDataCom( void *Data, int size, int command, int commandEx, int param1, int param2 ) { int len; char *data, *Pchar; data = (char *)Data; DHO.Cmd.Command[0] = command; DHO.Cmd.Command[1] = commandEx; Pchar = (char *)(DHO.Cmd.Command); Swapb( Pchar[0], Pchar[1] ); Swapb( Pchar[2], Pchar[3] ); DHO.FrameNumber = 0; DHO.WParam[0] = param1; DHO.WParam[1] = param2; DHO.Status &= (~stPacketDone); DHO.mbRead = size; if( size > MaxComPacket ) DHO.UnicalNumber = Unical++; else DHO.UnicalNumber = 0; while( size > 0 ) { if( size > MaxComPacket ) len = MaxComPacket; else len = size; if( (size-len) <= 0 ) DHO.Status |= stPacketDone; DHO.LenData = len; SendUart( &DHO, -sizeof( TMessageHeader) ); SendUart( data, len ); size -= len; data += len; DHO.FrameNumber++; } DHO.Status = 0; return 0; }
//############################################################################ //Hauptprogramm int main (void) //############################################################################ { char altPhase = 0; int test = 0; unsigned int Blink,TestschubTimer; unsigned int Blink2,MittelstromTimer,DrehzahlMessTimer,MotorGestopptTimer; DDRC = 0x08; //PC3输出,控制红色led 端口C 数据方向寄存器 PORTC = 0x08; //PC3输出高电平,红色led亮 DDRD = 0x3A; //10111010A-B-C-配置为输出,TXD,LED_GRN(PD7)配置为输出,MITTEL/RXD/INTO为输入 PORTD = 0x00; DDRB = 0x0E; PORTB = 0x31; #if (MOTORADRESSE == 0) PORTB |= (ADR1 + ADR2); // Pullups für Adresswahl for(test=0;test<500;test++); if(PINB & ADR1) { if (PINB & ADR2) MotorAdresse = 1; else MotorAdresse = 2; } else { if (PINB & ADR2) MotorAdresse = 3; else MotorAdresse = 4; } HwVersion = 11; #else MotorAdresse = MOTORADRESSE; HwVersion = 10; #endif if(PIND & 0x80) {HwVersion = 12; IntRef = 0xc0;} //为1.2版本 DDRD = 0xBA; UART_Init(); Timer0_Init(); sei();//Globale Interrupts Einschalten // Am Blinken erkennt man die richtige Motoradresse /* for(test=0;test<5;test++) { if(test == MotorAdresse) PORTD |= GRUEN; Delay_ms(150); PORTD &= ~GRUEN; Delay_ms(250); } Delay_ms(500); */ // UART_Init(); // war doppelt PWM_Init(); InitIC2_Slave(0x50); InitPPM(); Blink = SetDelay(101); Blink2 = SetDelay(102); MinUpmPulse = SetDelay(103); MittelstromTimer = SetDelay(254); DrehzahlMessTimer = SetDelay(1005); TestschubTimer = SetDelay(1006); while(!CheckDelay(MinUpmPulse)) { if(SollwertErmittlung()) break; // 一旦发现有信号,立刻停止延时 } GRN_ON; PWM = 0; SetPWM(); SFIOR = 0x08; // Analog Comperator ein ADMUX = 1; MinUpmPulse = SetDelay(10); DebugOut.Analog[1] = 1; // 填写一些调试信号 PPM_Signal = 0; if(!SollwertErmittlung()) MotorTon(); //MotorTon(); PORTB = 0x31; // Pullups wieder einschalten // zum Test der Hardware; Motor dreht mit konstanter Drehzahl ohne Regelung if(TEST_MANUELL) Anwerfen(TEST_MANUELL); // kommt von dort nicht wieder while (1) { //ShowSense(); if(!TEST_SCHUB) PWM = SollwertErmittlung(); //I2C_TXBuffer = PWM; // Antwort über I2C-Bus if(MANUELL_PWM) PWM = MANUELL_PWM; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if(Phase != altPhase) // es gab eine Kommutierung im Interrupt { MotorGestoppt = 0; ZeitFuerBerechnungen = 0; // direkt nach einer Kommutierung ist Zeit MinUpmPulse = SetDelay(250); // Timeout, falls ein Motor stehen bleibt altPhase = Phase; // 旧相位 = 新相位 } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if(!PWM) // Sollwert == 0 在开机后主控板静默,并没有发任何I2C信号过来 { MotorAnwerfen = 0; // kein Startversuch MotorAnwerfen means motor start ZeitFuerBerechnungen = 0; // 指使一些操作的优先级用 // nach 1,5 Sekunden den Motor als gestoppt betrachten if(CheckDelay(MotorGestopptTimer)) { DISABLE_SENSE_INT; MotorGestoppt = 1; STEUER_OFF; } } else { if(MotorGestoppt) MotorAnwerfen = 1; // Startversuch MotorGestopptTimer = SetDelay(1500); } if(MotorGestoppt && !TEST_SCHUB) PWM = 0; //TEST_SCHUB 1为测试模式,0为正常模式 SetPWM(); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if(!ZeitFuerBerechnungen++) //先!,后++ { if(MotorGestoppt) // 马达停止 { GRN_ON; FastADConvert(); } if(SIO_DEBUG) { DebugAusgaben(); // welche Werte sollen angezeigt werden? if(!UebertragungAbgeschlossen) SendUart(); else DatenUebertragung(); } // Berechnen des Mittleren Stroms zur (langsamen) Strombegrenzung if(CheckDelay(MittelstromTimer)) //254ms { MittelstromTimer = SetDelay(50); // alle 50ms if(Mittelstrom < Strom) Mittelstrom++;// Mittelwert des Stroms bilden 将mittelstorm平缓化 else if(Mittelstrom > Strom) Mittelstrom--; if(Strom > MAX_STROM) MaxPWM -= MaxPWM / 32; //为什么电流大于最大电流的时候,PWM最大值要减小? if((Mittelstrom > LIMIT_STROM))// Strom am Limit? 动态调整MaxPWM的值 { if(MaxPWM) MaxPWM--;// dann die Maximale PWM herunterfahren PORTC |= ROT; } else { if(MaxPWM < MAX_PWM) MaxPWM++; } } if(CheckDelay(DrehzahlMessTimer)) // Ist-Drehzahl bestimmen 1005ms { DrehzahlMessTimer = SetDelay(10); SIO_Drehzahl = CntKommutierungen;//(6 * CntKommutierungen) / (POLANZAHL / 2); CntKommutierungen = 0; // if(PPM_Timeout == 0) // keine PPM-Signale ZeitZumAdWandeln = 1; } #if TEST_SCHUB == 1 { if(CheckDelay(TestschubTimer)) { TestschubTimer = SetDelay(1500); switch(test) { case 0: PWM = 50; test++; break; case 1: PWM = 130; test++; break; case 2: PWM = 60; test++; break; case 3: PWM = 140; test++; break; case 4: PWM = 150; test = 0; break; default: test = 0; } } } #endif // Motor Stehen geblieben if((CheckDelay(MinUpmPulse) && SIO_Drehzahl == 0) || MotorAnwerfen) // SIO_Drehzahl 为当前转速值 前面为判断意外停机 { /* 下面三行代码给电机意外停转用*/ MotorGestoppt = 1; DISABLE_SENSE_INT; // 取消比较中断 MinUpmPulse = SetDelay(100); if(MotorAnwerfen) { PORTC &= ~ROT; //switch off red led Strom_max = 0; MotorAnwerfen = 0; if(Anwerfen(10)) // 以PMW = 10触发启动程序,期间要换相32次,成功返回1 { GRN_ON; //绿灯打开 MotorGestoppt = 0; // Phase--; // Phase = 1 PWM = 1; SetPWM(); SENSE_TOGGLE_INT; // ????? ENABLE_SENSE_INT; // ????? 使能比较器中断 MinUpmPulse = SetDelay(20); while(!CheckDelay(MinUpmPulse)); // kurz Synchronisieren PWM = 15; SetPWM(); MinUpmPulse = SetDelay(300); while(!CheckDelay(MinUpmPulse)) // kurz Durchstarten { if(Strom > LIMIT_STROM/2) { STEUER_OFF; // Abschalten wegen Kurzschluss RotBlink(10); MotorAnwerfen = 1; } } // Drehzahlmessung wieder aufsetzen DrehzahlMessTimer = SetDelay(50); altPhase = 7; } else if(SollwertErmittlung()) MotorAnwerfen = 1; } } } // ZeitFuerBerechnungen } // while(1) - Hauptschleife }