Hallo!
Ich habe mittlerweile mein Programm theoretisch soweit, dass es macht
was es machen soll -> nur wie immer kommt es immer anders als man denkt.
Die Programmteile einzeln (ADC-Auswertung (Interrupt);
Frequenzauswertung (Interrupt); Menü, Ausgabe) funktionieren, dies hab
ich getestet.
Nur beim Zusammenspiel hapert es, wenn die beiden Interruptroutinen
gleichzeitig im Programmablauf vorhanden sind.
Prinzipieller Programmablauf ist folgender:
(endlosschleife)
wenn adc mehr als 8 mal ausgewertet wurde -> auswertung
vornehmen,variable setzen, damit erst wieder Interrupt durchlaufen wird,
wenn Ausgabe erfolgt ist und "Erlaubnis" für Display geben;
wenn Frequenzmessung beendet -> auswertung vornehmen,variable setzen,
damit erst wieder Interrupt durchlaufen wird, wenn Ausgabe erfolgt ist
und "Erlaubnis" für Display geben;
wenn Ausgabe erlaubt -> Schreibe werte auf Display, setze
Interruptvariablen zurück;
(ende)
So als kurzer Auszug.(Teil des Quellcodes ist oben angehängt.)
Mein Poblem ist jetzt, dass bei der Frequenzmessung ca. jedes 3. mal
extrem falsche werte vorhanden sind -> und ich hab keine Ahnung warum?
Wäre super wenn sich dasjemand mal ansehen könnte.
MFG
P.S. Die Variablen die nicht lokal in der main() deklariert sind, sidn
alle global deklariert (ja, mit volatile)
Code:ISR(ADC_vect){ if (adcbesch == 1){ return; } else{ adczaehler++; adcspeicher += ADC; } } //------------------------------------------------------- ISR(TIMER1_CAPT_vect) { if( UpdateDisplay == 1 ) //auf vorherige Messung warten return; if (x == 0) // 1.High Flanke { ic_zp_A = ICR1; overflow = 0; x = 1; } else // 2.High Flanke { ic_zp_B = ICR1; // Messung ist fertig, Display kann neu geschrieben werden UpdateDisplay = 1; x = 0; } } //------------------------------------------------------- ISR(TIMER1_OVF_vect) { overflow++; } int main(void){ verz(20); //------------------------------------------------------- float drehzahlwert = 0; //Speicherwert für Drehzahlwert float leistung = 0; long adcergebnis = 0; Start_EEPROMLesen(); //Werte aus EEPROM lesen und in Variablen schreiben LCD_Init(0); //Initialisierung des Displays LCD_Clr(); //Display löschen verz(4); //Pause fürs Display Init(); //Taster-Initialisierung, ADC-Initialisierung, RS232- Initialisierung Zaehler_EEPROM(); //Überprüfen der EEPROM Schreibzugriffe TCCR1B = (1<<ICES1) | (1<<CS10) ; // Input Capture Edge, kein PreScale ->Taktfrequenz: 8MHz externer Quarz TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow DDRD = 0x00; verz(1); sei(); drehmomentwert = drehmomentberechnung(700); while(1) { if (adczaehler >= 8){ adcbesch = 1; adcergebnis = adcspeicher/adczaehler; drehmomentwert = drehmomentberechnung(adcergebnis); adczaehler = 0; adcspeicher = 0; write = 1; //Display soll beschrieben werden //UpdateDisplay = 1; } if( UpdateDisplay == 1 ) { zw_Erg = ((overflow*65536) + ic_zp_B - ic_zp_A); // Overflow berücksichtigen Erg = 8000000 / zw_Erg; //8MHz Quarz drehzahlwert = drehzahlberechnung(Erg); write = 1; //Display soll bechrieben werden } if ( write == 1){ //Ausgabe der Werte, je nachdem ob write gesetzt oder nicht if ( ausgabemodus == 1){ //Ausgabe der Werte über LCD + RS232 leistung = leistungsberechnung(drehmomentwert,drehzahlwert); Ausgabe_LCD(); } else if (ausgabemodus == 2){ //Ausgabe der Werte nur über RS232 -> schnell !!Achtung!! Keine Leistungsberechnung/ausgabe if (lcdbeschr == 0){ LCD_Clr(); verz(3); LCD_WritePosString(0, 0,"RS232-Modus aktiv", 1); LCD_WritePosString(1, 0,"Displayausgabe", 1); LCD_WritePosString(2, 0,"ausgeschaltet", 1); lcdbeschr = 1; } else if (lcdbeschr == 1){ Ausgabe_RS232(); } } write = 0; adcbesch = 0; UpdateDisplay = 0; } if (PIND &(1 << MENUETASTE)){ //Bedingung für Menüaufruf -> Messung wird gestoppt!! cli(); verz(8); men(); sei(); } if (PIND &(1 << UEBERSICHTTASTE)){ //Bedingung für Aufruf der Übersicht -> Messung wird gestoppt!! cli(); verz(8); uebersicht(); sei(); } } return 0; }







Zitieren

Lesezeichen