Einen "Guten Morgen" an die uC Community ! Nach vielen Stunden probieren und Atmega644 heisslaufen lassen weiss ich einfach nicht mehr weiter: Eigentlich geht es mir nur um einen Timer den ich in zwei Zeitbasen unterteilen will. Dazu löse ich alle 100ms ("T_RESOLUTION") einen Overflow Interrupt aus der mir die schnelle Zeitbasis liefern soll. Zum Überprüfen habe ich den PD7 als Ausgang definiert und mit "PORTD ^= (1<<PD7)" toggle ich den Ausgang mit den erwarteten 50Hz - soweit so gut, das Oszi gibt mir genau den erwarteten Wert. Um jede Sekunde langsamere Aufgaben zu erledigen ist die Idee mit der Variablen "Tick Counter" bis auf 100 zu zählen um dann per: if(TickCounter >= 100) { TickCounter = 0; PORTD ^= (1<<PD6); } eine Unterteilung in Sekunden zu erzielen. Zum Überprüfen toggle ich PD6. In der Simulation läuft alles wie es soll, sobald ich das Programm aber auf meinen Atmega644 aufspiele ist Schluss. PD7 toggelt nach wie vor, aber es ist tote Hose auf PD6. Interessanterweise funktioniert's wenn ich anstatt 100 nur 2 verwende, also anstatt "if(TickCounter >= 100)" die IF Konstruktion: "if(TickCounter >= 2)". In diesem Fall zeigt das Oszi keine Halbierung der Frequenz sondern eine Änderung des Tastverhältnisses (immer noch 50Hz auf PD6 aber zwei Drittel der Zeit ist der Ausgang 0 und ein Drittel der Periode auf 1). In der Simulation verhält es sich aber wie's soll. Ich benutze das AVR studio 6 (mit letztem Patch) der Quarz ist ein 11.0592MHz Baud Quarz. Den Code habe ich in einem File versammelt, ich häng' den mal an. Ich denke dass ich irgendwo Tomaten auf den Augen habe, das Problem erscheint mir so primitiv dass ich mir keinen "Kompilerfehler" vorstellen kann. Hätte jemand eine Idee dazu ?? Vielen Dank: Hermann
Am Anfang der ISR setzt du den Tick-Counter auf 0, bei jedem Aufruf. Das ist suboptimal. Weil er dann nur schwer auf 100 kommen kann. Und noch ein Hinweis: 100ms und 50Hz widersprechen sich. Vermutlich meinst du 10ms. Das würde auch zu %100 für 1s passen.
>Am Anfang der ISR setzt du den Tick-Counter auf 0, bei jedem Aufruf.
Nein. Bei einer static Variablen wird diese Initialiserung nur einmal
ausgeführt, nämlich beim ersten Ausführen der Funktion.
Und bei dem Stichwort "Funktion" bimmelts irgendwie bei mir.
Eine Interrupt-Service-Routine ist keine herkömmliche Funktion. Sie
bekommt keine Parameter. Zwar hat sie für lokale Variablen wohl einen
Stack-Frame, aber ich hätte nicht vorausgesetzt, das der Compiler auch
statische Variablen in ISRs wie in Funktionen behandelt. In der Tat ist
das die erste ISR die ich sehe in der eine static-Variable deklariert
ist.
Ich nehme an, das der Compiler das Ding wie eine lokale Variable
behandelt und das (unter Annahme verschiedener Nebenumstände) der Stack
im Simulator zufällig noch diesen Wert behielt. Warum das nun im realen
Prozessor nicht so ist, kann ich im Moment nicht erklären. Der
Assemblercode könnte das klären.
Ich empfehle Dir die Variable ausserhalb jeder Funktion zu deklarieren.
Entferne das static und füge ein volatile hinzu.
Danke Georg ! Die 50Hz sind logisch da die ISR alle 100ms ausgeführt wird. In jeder ISR wird PD7 getoggelt. Dh. PD7 ist 100ms "high" und dann 100ms "low" das ergibt eine Periode von 200ms und damit 50Hz. Was die Initialisierung von TickCounter angeht so habe ich die Variable als "Statisch" definiert, damit wird nach meinem (vielleicht falschen ??) Kenntissstand die Variable nur einmal am Programmanfang initialisiert und dann nicht mehr, sie müsste also ihren Wert von dann an beibehalten ?! Grüsse aus dem sonnigen Frankreich: Hermann
Das mit 100ms toggle eine 50Hz Frequenz erreicht wird, beruht meiner Ansicht nach, auf einem Rechenfehler. Es sind 5Hz. Für 50Hz bräuchtest Du 10ms.
Oups, in der Zwischenzeit ist ja noch ein weiterer Beitrag gekommen, nochmals "Danke". Ich hab' das sofort getestet und außerhalb von "main(){}" die Variable TickCounter mit "volatile uint8_t TickCounter = 0;" als global definiert. In der ISR führe ich die Variable mit "extern uint8_t TickCounter;" ein. Jetzt ist es aber so dass das Programm auch mit "if(TickCounter >= 2)" keinerelei Aktivität an PD6 mehr ergibt (gescheige denn mit Werten grösser als 2) Immerhin zeigt sich eine Veränderung des Verhaltens was mich vermuten lässt dass das Problem in dieser Richtung zu suchen ist. Grüsse: Herman
Also, ich habe mal ein bisschen gegoogelt und nachgedacht. Theoretisch spricht eigentlich nichts dagegen, in einer ISR eine statische Variable zu haben. Ich finde auch Beispiele dazu. Mein mein "dummes Gefühl" dabei mag also unbegründet sein. Das ich das noch nie so gemacht habe, ist ja nicht ausschlaggebend. Vielleicht magst Du aber doch mal ausprobieren, die Variable global und volatile zu deklarieren.
>In der ISR führe ich die Variable mit "extern uint8_t TickCounter;" >ein. Das ist unnötig und sogar falsch, wenn der Code wie oben gezeigt, in einer Datei enthalten ist. Jedenfalls fehlt das volatile. Lösch die Deklaration "extern uint8_t TickCounter;" einfach.
"Für 50Hz bräuchtest Du 10ms." Das ist völlig richtig, war ein Denkfehler von mir da ich durch 100 teile in "#define T_RESOLUTION 100" ! (aber 1000/100 ist wie du richtig bemerkst 10 und nicht 100)
Das "extern" ist nur dann nötig, wenn Du zwei C-Dateien hast von denen eine die Definition der Variablen enthält (nicht static) und die andere C-Datei diese Variable referenzieren will. Wenn nur eine Datei vorhanden ist, dann ist das "extern" falsch.
hm, Hab' im gleichen File die ISR unter den "main" -Abschnitt verschoben so dass TickCounter in der ISR bekannt ist. (und nur noch "volatile uint8_t TickCounter = 0;" überhalb von main()) Das praktische Resultat ist aber leider unverändert. Nochmals Grüsse: Hermann
Poste doch bitte mal den ASM-Code, den der GCC baut. Dann sieht man vermutlich, was passiert.
Hallo Georg, jetzt erwischt du mich an meiner weichen Stelle - ich weiss nicht wie ich an den Assembler Code rankomme !
Um jedes Missverständnis auszuschliessen, bitte ich Dich, den momentanen Code zu posten und das nunmehr beobachtete Verhalten zu beschreiben. Die Reihenfolge von main und der ISR spiel keine Rolle. Besonders nicht in Bezug auf darin verwendete Variablen. In Bezug auf Variablen würde die Reihenfolge der Variablen-Definitionen/Deklarationen und der Funktionen welche sie verwenden ein Rolle spielen. Aber das ist ein anderes Thema.
Fühl mich ein wenig komisch dich mit "Hm" anzusprechen aber ich finde es Klasse von euch dass ihr mir wirklich versucht zu helfen !! also nochmals Danke. Den code hab' ich so wie er ist angeheftet. Das Verhalten ist so dass PD7 nach wie vor dass tut was es soll, in "if(TickCounter >= 2)" aber mit PD6 Schluss ist wenn 2 durch einen höheren Wert ersetzt wird.
ASM sieht so weit unauffällig aus. Muss aber erst einmal SN machen. Wenn es dann immer noch unklar ist, geht es weiter.
>Fühl mich ein wenig komisch dich mit "Hm" anzusprechen...
Ich nenne mich ja auch "Hmm". :-)
Also ich sehe an dem Code nichts, warum das nicht gehen sollte.
Bleiben also die üblichen Verdächtigen:
Hast Du
1. im Simulator
2. beim Compiler
3. beim Programmier-Dialog
jeweils den richtigen Prozessor eingestellt?
Hast Du dir richtigen Fuses eingestellt?
1. Taktquelle
2. CKDIV8
Du kannst ja mal sicherheitshalber das lss file schicken wenn Du für den
Vergleichswert 100 einsetzt. Aber ich denke nicht, das sich da was Neues
ergibt.
Welche Frequenz ergibt sich an PD6 solange Du auf >= 2 testest?
Nee, kein Watchdog aktiviert, meine Antworten werden in den nächsten Minuten etwas unregelmässiger da meine Freundin mich zum Essen machen verdonnert hat ...
Tja... wie sag ich es am schonendsten... Auf meinem STK500 mit einem 1284 (sollte keinen Unterschied machen, war zu faul zum wechseln) mit "alle 100" funktioniert es wunderbar. Kein Fehler feststellbar. (Ehefrau macht ausnahmsweise das Essen)
aaalso: zu "Welche Frequenz ergibt sich an PD6 solange Du auf >= 2 testest?" Frequenz an PD6 mit ">= 2" nach wie vor 50Hz aber mit verandertem Tastverhältniss 1/4 auf '1' 3/4 auf '0' d.h. PD6 über eine 20ms Periode: 5ms "an" 15 ms "aus" F_CPU=11059200UL Der Compiler ist bei mir standardmässig auf C++ gesetzt (in "ALT+F7" -> AVR/GNU Compiler habe ich: -funsigned-char -funsigned-bitfields -DF_CPU=11059200UL -O0 -fpack-struct -fshort-enums -g2 -Wall -c -gdwarf-2 -x c++ -std=gnu++98 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -mmcu=atmega644 wo's von den Standard Settings abweicht ist der Zusatz: "-x c++ -std=gnu++98" um alles mit C+ zu compiliern (schreibe viel in C++ und hatte soweit keine Probleme damit) Der Prozessor ist ein 644A, da sagt er aber dass er den io?? File nicht findet. Ich habe ihn deshalb als 644 (ohne A) definiert, hoffe das es nicht daran liegt. Taktquelle/CKDIV8: Sicher nicht, die im Oszi angegeben Frequenz stimmt (50Hz)
>... mit einem 1284 (sollte keinen Unterschied machen ...
Um ein mögliches Missverständnis zu vermeiden. Es ist dennoch nötig zu
kontrollieren ob Du die Optionen zum simulieren, kompilieren und
programmieren im AVRStudio wegen des Prozessortyps richtig und gleich
eingestellt hast.
Hab soeben auch noch alle Atmega644 mit "Change Device" durchgespielt und aufgflasht - (A,PA,P, 644 ohne Endung) leider keine Änderung im Problem...
Jetzt muss ich doch mal ein bisschen "strenger" werden. ;-) Nicht einfach irgendwas rumprobieren. Das hilft in der Technik nicht und kann bis zur Zerstörung von Teilen führen. Du hast einen bestimmten Prozessortyp, nämlich 644A und den stellst Du in den Dialogen ein. Es gibt keinen Grund da irgendwas "herumzuprobieren". Deine Aussage >zu "Welche Frequenz ergibt sich an PD6 solange Du auf >= 2 testest?" >Frequenz an PD6 mit ">= 2" nach wie vor 50Hz aber mit verandertem >Tastverhältniss >1/4 auf '1' 3/4 auf '0' d.h. PD6 über eine 20ms Periode: 5ms "an" 15 ms >"aus" >F_CPU=11059200UL deutet auf irgendwas Oberfaules hin. Es kann nicht sein, das bei einer Veränderung des Vergleichskriterium von 100 auf 2 die Frequenz gleich bleibt und sich das Tastverhältnis ändert. Prüfe bitte zusätzlich ob Du auch die richtige Hex-Datei programmierst. Wohlgemerkt, nachdem Du den richtigen Prozessortyp eingestellt hast.
644 rausgesucht und eingebaut. Neu compiliert. Programm tut das gewünschte. Allerdings nicht c++ sonder als c (normal) gebaut. Da keine c++ Features verwendet werden, sollte es nichts ändern.
>644 rausgesucht und eingebaut.
Hey, nett von Dir. Ich seh keinen Grund warum das nicht bei ihm spielen
sollte. Irgendwas ist da im Setup faul.
Super von euch dass ihr euch die Mühe macht ! Was die HEX Datei angeht so bin ich mir sicher das es die Richtige ist, beim Verändern des Codes wegen ">= 2" habe ich ja die Änderung gesehen und auch den Path mehrfach überprüft. "deutet auf irgendwas Oberfaules hin" - Dem kann ich leider nur zustimmen ! Ich muss jetzt leider weg da der Famileinfrieden ernsthaft bedroht ist ! Heute Abend nach 20:00 bin ich zurück. Da ich noch andere Prozessoren hier rumliegen habe werd' ich's mal mit denen versuchen und auch den Kompi wechseln wo ich noch die "Urform" von AVR-Studio6 bzw Studio4 installiert (nix C++) habe. Ich halt' euch auf dem Laufenden ... Hermann
Stell die HEX Datei auch mal rein. Dann flashe ich die auf meine Hardware und teste.
Hmm schrieb: > Ich empfehle Dir die Variable ausserhalb jeder Funktion zu deklarieren. > Entferne das static und füge ein volatile hinzu. das ist total unsinn. volatil ist hier nicht notwendig und wenn man es vermeiden kann macht man keine globalen Variablen!
>das ist total unsinn. volatil ist hier nicht notwendig und wenn man es >vermeiden kann macht man keine globalen Variablen! Wenn ich auch Deine Ausdrucksweise nicht mag: Ich stimme Dir zu, das volatile nicht nowendig ist. Ob man globale Variablen vermeidet, ist aber Geschmackssache. "Unsinn" ist hier nur das volatile. Ich finde Du hättest noch eine Begründung hinzufügen sollen. Da Du es unterlassen hast, tue ich das für Dich. volatile ist hier nicht notwendig, weil es nur eine Stelle, nämlich in der ISR gibt, in der die Variable geschrieben und gelesen wird. D.h. der Compiler trifft auf keine andere Codestelle an der er die Möglichkeit hätte einen noch in einem Register gespeicherten Wert der Variablen weiterzuverwenden, während er potentiell in der ISR verändert werden könnte. Zur Verwendung oder Nicht-Verwendung von globalen Variablen gibt es eine Reihe von Standpunkten mit unterschiedlichem Schwerpunkt. Z.B. die möglicherweise unbeabsichtigte Verwendung einer Variablen in einem Modul, die in einem anderen Modul definiert ist. Wenn man aber die Variable auch ein zweites Mal definiert dann gibt es bei den heutigen C-Compilern eine Warnung. Trifft hier nicht zu, weil es nur ein Modul gibt. Ob da die Kritik an einer globalen Variable überhaupt angebracht ist, bezweifle ich.
Hier einmal mit ">= 2" und einmal mit ">= 10" zum Vergleich, muss jetzt los...
Schlechte Nachrichten... beide Files funktionieren. Kein Fehler zu finden. Also muss es deine Hardware sein. Kurzschluss zwischen zwei Prozessorbeinen?
Wow, Super Georg ! Auch wenn du das als schlechte Nachrichten bezeichnest so schränkt es doch die Fehlermöglichkeiten weiter ein und hilft insoweit echt weiter. Bevor ich weg ging habe ich noch den geposteten File mit Studio 4 compiliert und aufgespielt - leider ohne Veränderung. Im Licht von deinem Bericht ist dies auch kein Wunder - der .Hex scheint ja zu stimmen. Ich schraub jetzt mal den 644A raus und ersetz ihn durch 'nen anderen. Mehr gleich .. Hermann
Na sowas hab' ich bislang noch nie gesehen. Ich habe den Atmega644 rausgehebelt und durch einen 8535 ersetzt (im gleichen Board). Im Programm musste ich noch TIMSK1 durch TIMSK ersetzen da dies der 8535 nicht kennt, compilieren, aufspielen und siehe da es funzt ! Damit kann es auch kein Kurzschluss gewesen sein (hätte eh' keine unabhängigen Signale an PD6 und PD7 erlaubt). m.a.W. das Problem war/ist wahrscheinlich im Atmega644 selbst ! Zum Glück hab ich noch ein ganzes Packet an Atmega644's, ich versuchs mal mit dem nächsten... Als letztes an "Hmm" im Grunde hast du Recht was das "rumspielen" mit den 644(A/P etc.) Endungen angeht. Ich muss zu meiner Verteidigung aber einwenden dass das Studio4 den 644A nicht in der Liste hat und auch Studio6 mir mitgeteilt hat das es den iom644A.h nicht hat; auf meinen Chips (Quelle: Radiospares) ist aber ein dickes 644A aufgedruckt ! Gut jetzt geht's ans rumschrauben ! Muchas Grazias: Hermann Falls alles so geht geb' ich noch ein letztes Update ...
dad war's genauer gesagt der Atmega selbst. Keine Ahnung warum es ihn zersemmelt hat und noch weniger warum er noch so getan hat als ob er funktionieren würde, ich dachte ich hatte ihn schonend behandelt. Es bleibt mir nur noch ein wenig das frustrierende Gefühl dass ich immer noch nicht verstehe was da eigentlich im Innern schief lief, aber dazu müsste ich wohl jemand von Atmel bestechen um mit deren Methoden das Teil zu analysieren (schliesslich arbeite ich ja zur Hälfte für die Uni Trondheim wo die ja herkommen) Klasse, ihr (i.B. Georg und "Hmm" (auch wenn ich mit dem Namen immer noch ein Problem habe) wart wirklich ein echte Hilfe ! Jetzt kann's mit meinem Projekt endlich mit Volldampf weitergehen, zumal meine Freundin eh' gerade im Flieger nach Paris sitzt.
Herrmann schrob: >Jetzt kann's in meinem Projekt endlich mit Volldampf weitergehen zumal >meine Freundin gerade im Flieger nach Paris sitzt Hoffentlich hat sie den Lötkolben da gelassen.... ;-) MfG Paul
Keine Bange, sie ist normalerweise eher tolerant was das angeht, da sie aber über 500km von mir weg wohnt und wir uns nur am WE sehen wird sie manchmal etwas ungeduldig wenn ich die wenige Zeit auch noch mit Programmieren und Rumschrauben verbringe. Is ja nachvollziehbar ...
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.