Jericho_one
28.02.2007, 15:22
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 ;-) )
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;
}
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 ;-) )
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;
}