Hallo, ich habe eine globale volatile variable die ich in der ISR des adcs verändere. Jetzt benötige ich den Wert in einer anderen ISR aber das funktioniert nicht. Ausser halb der ISR ist die Variable aber OK. Ist das normal? Gruß Florian
Meine Glaskugel sagt, du hast einen Fehler in Zeile 42. Zeige Code!
globale.h volatile unsigned short adc_ergebnis[8]; volatile unsigned char adc_kanal[8]; volatile unsigned short kanal_index; Separate datei SIGNAL(SIG_OVERFLOW0) { //pos = adc_ergebnis[2]; f2 = f1; f1 = f0; f0 = (float)(pos-des_pos)/(float)1024.0; Ua = Ua + (Kp+Ki*T_cnt0+Kd/T_cnt0) * f0 + (-Kp-Kd/T_cnt0) * f1 + (Kd/T_cnt0) * f2; if((pos-des_pos)<max_fehler || (des_pos-pos)<max_fehler) { //pwm_stop(); //return; } PORTD |= _BV(PD7); /* if(pos-des_pos>0) */ init_pwm_oc1a(); /* else */ /* init_pwm_oc1b() */; Te = ((float)Ua/(float)Vcc); /* Tein des PWM Signals */ int c = ((float)Te * (float)TOP); setze_tastverhaeltnis(adc_ergebnis[2]); //setze_tastverhaeltnis(Te * TOP / T_pwm); PORTD &= ~_BV(PD7); } Separate Datei: SIGNAL(SIG_ADC) //interrupte sind in ISR automatisch ausgeschaltet { adc_ergebnis[kanal_index] = ADCL; //erst ADCL dann ADCH um sicherzustellen // das Werte aus einer Wandlung stammen; adc_ergebnis[kanal_index] += (ADCH<<8); kanal_index++; if(kanal_index==3) kanal_index=0; ADMUX = adc_kanal[kanal_index]; /* ca. 100 Zyklen seit der Interrup ausgelöst wurde */ /*wir können also den mux neu muxen */ ADCSRA |= _BV(ADSC); } Es geht um adc_ergebnis[x]
>wie heisst die Quelldatei?
main.c
Wenn dem nicht so sein sollte, liegt der Fehler woanders.
Schön. Aber den Code kann ich nicht in AVR-Studio kopieren und laufen lassen um nachzusehen was da wirklich passiert.
Ahh hallo, nichts für ungut. Ich bin ja kein Baby mehr. Abgesehen davon dürfte das wohl einige arbeit werden das ins avrstudio zu bringen. Aber bitte im anhang ist das projekt. Ich dachte nur ob jemand etwas in dem Zusammen hang weiss. Ich habe es jetzt anders gemacht. Und zwar habe ich noch einen zeiger auf adc_ergebnis erstellt. diesen benutze ich jetzt in der ISR. Ich habs mal angehangen. Es ist ein PWM Servotreiber. fall jemand interesse an der Elektronik hat, ich bin unter florian.hillen@web.de zu erreichen oder gleich hier. Frohes neues Jahr!
> Abgesehen davon dürfte das > wohl einige arbeit werden das ins avrstudio zu bringen. Halb so wild. Eine ANgabe brauch ich noch. Wie stellst du fest, dass da was mit den volatile Variablen nicht stimmt? Hast dus im Debugger gesehen oder ist das nur eine Vermutung?
Florian wrote: > Abgesehen davon dürfte das > wohl einige arbeit werden das ins avrstudio zu bringen. Stimmt, .tar.gz is nich so mein Ding. XP kann von Haus aus nur .zip Peter
Das einzige was ich bis jetzt im Debugger gesehen habe ist, dass dein Overflow Interrupt zuviel Zeit braucht. Der Prozessor arbeitet praktisch nur da drinnen. Sobald die ISR fertig ist, beginnt auch schon der nächste ISR, weil der Timer in der Zwischenzeit den nächsten Überlauf produziert hat. Setzt mal den Vorteiler etwas höher.
Ansonsten klappt bei mir im Debugger der Zugriff auf das Array einwandfrei. Ich wüsste auch keinen Grund warum das nicht so sein sollte. Ich habe mal den Vorteiler um eine Stufe erhöht. Seitdem werden zwischendurch auch wieder Werte vom ADC abgeholt :-)
aha das werde ich einmal Probieren. Ich habe festgestellt das da was nicht stimmt weil ich an meiner Leistungselektronik einen Motor habe und der immer nur nach dem ersten ADC Wert ging. Ich probies direkt mal aus und meld mich nochmal. Vielen dank auch! Florian
Also wars doch ganz gut das vollständige Projekt zu posten :-) Merke: Wenn jemand glaubt dass er einen Compilerfehler entdeckt hat, dann hat er zu 99% ein anderes Problem im Programm. Natürlich haben auch Compiler so ihre Fehler. Aber nicht bei einem simplen Variablenzugriff.
So eine Schmach. Aber wahrscheinlich hast du auch da recht.
Auch wenn man überzeugter GNUler ist muss man trotzdem erstmal vertrauen in die Werkzeuge gewinnen!
Möchte nur mal vorsichtshalber darauf hinweisen, dass volatile unsigned short x; ISR(suchesdiraus) { x = irgendwas; } main() { while(1) tu_irgendwas_mit(x); } auf AVRs zwar 999 von 1000 mal wunderbar funktionieren wird, aber ab und zu Schrott rauskommt. Siehe http://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff.
> auf AVRs zwar 999 von 1000 mal wunderbar funktionieren wird, > aber ab und zu Schrott rauskommt. Nun, der Schrott macht aber nicht der Compiler, sondern der Programmierer, wie üblich. Die Lösung des Problems lautet: volatile unsigned short x; ISR(suchesdiraus) { x = irgendwas; } main() { unsigned short x_copy; while(1) { cli(); x_copy = x; sei(); tu_irgendwas_mit(x_copy); } }
Sollte die Funktion von cli(); und sei(); nicht der Grund sein, warum man die Variable als volatile deklariert (mehr als 1 Byte zum Lesen)? Sollte eigentlich automatisch vom Compiler erledigt werden.
Nein. "volatile" sorgt dafür, dass die tatsächlich durchgeführten Zugriffe denen im Quelltext entsprechen, d.h. dass da nichts wegoptimiert oder umsortiert wird. Atomar werden die Zugriffe mit "volatile" jedoch nicht.
"Nun, der Schrott macht aber nicht der Compiler" Wollte ich damit auch nicht ausdrücken. Ich hatte bei Florians Code jedoch gleich den Verdacht, dass unabhängig vom eigentlichen Problem jemand, der in Interrupts Floating-Point-Rechnungen durchführt, diese Feinheit im Umgang mit globalen Variablen auch übersehen hatte - und genau so ist es.
Hmm.. so wie ich das verstanden habe dient volatile (!beim AVR!) dazu, Variablen, die außerhalb der Funktion 'main' behandelt werden, neu einzulesen und während des Einlesens den globalen INT zu sperren, um teilweises Lesen zu vermeiden, falls währenddessen ein INT auftritt. Hatte auch noch nie Probleme in der Richtung. Aber, falls das anders ist, wieder was gelernt.
Alle Ports und Steuerregister sind "volatile". Wenn GCC da jedesmal einen cli/sei-Wrapper drumwickeln würde...
Bei Ports und Steuerregistern muss er das ja auch nicht, da die Byteorientiert sind. Dachte, nötig ist es nur bei Variablen >8 Bit, da es mehrerer Leseoperationen für diese Typen bedarf. Lasse mich aber gerne eines Anderen belehren.
Ist auch nur bei >8bit nötig, allerdings sind manche I/O-Register >8 breit (z.B. bei Timer, ADC). Aber das Philosophieren lässt sich ganz einfach abkürzen: Guck in den Code und vertrau darauf, dass GCC sich korrekt verhält. Stimmt fast immer.
Also ich hatte noch keine Probleme mit GCC. Find ich prima.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.