Servus! AVR Studio : Version 4.12, Service Pack 4, Build 498 WinAVR : 2006-04-21 HW : ATMega16, LCD mit HD44780, 3x4 Tastenfeld Download : AVRISP Problem: Die Tastenabfrage (siehe Datei "keypad_ctrl.c", Methode "readKeypadKEY") funktioniert mit Optimierung 's' in Makefile nicht, hingegen ohne Optimierung '0' sehr wohl. Zu Testzwecken gebe ich mir den binären Wert des PIN Registers der verwendeten Schnittstelle D BUT_PIN (siehe define Konstante in "global_defs.h") auf die LCD Zeile 2 aus und den in der lokalen Variable sample_1 gespeicherten Wert von BUT_PIN auf Zeile 3 aus. Alles in der Methode "readKeypadKEY". Falls die entsprechende Taste gedrückt wird ändert sich der Wert von BUT_PIN aber sample_1 ändert sich mit Optimierung nie, obwohl volatile. Ein weiterer Versuch die Schnittstelle D als formalen Parameter zu übergeben (siehe die Parameter port und pin welche in der jetzigen Version nicht verwendet werden) funktioniert auch mit Optimierung auch wen die lokalen Variablen sample_1 und sample_2 nicht mit volatile qualifiziert werden. -> aber für mich unbefriedigende Lösung Ich wollte euch fragen, wieso in der jetzigen Version der Wert von sample_1 nie erneuert wird, obwohl mit volatile qualifiziert. Brauche wirklich Hilfe da ich bereits zwei volle Tage in dieses Problem investiert habe und keinen mm weiterkomme. Die main befindet sich übrigens in "gasmixer.c". Schönen Dank erstmal.
Servus! Das Problem hat (anscheinend) nichts mit "volatile" zu tun sondern eher mit der Dauer für die Einsynchronisierung der Pins. Vergleicht man das Inline-Assembler File so sieht man: ohne Optimierung: 122: sample_1 = BUT_PIN; +00000B10: 91800030 LDS R24,0x0030 Load direct from data space +00000B12: 878D STD Y+13,R24 Store indirect with displacement mit Optimierung: 122: sample_1 = BUT_PIN; +000003C1: B380 IN R24,0x10 In from I/O location +000003C2: 8389 STD Y+1,R24 Store indirect with displacement das der Unterschied im Ladebefehl des Ports liegt, wobei IN in einem Zyklus und LDS in zwei Zyklen abgearbeitet wird. Der Verdacht bestätigt sich, denn wenn man nach setzen des Ports eine "NOP" Operation einfügt funktioniert der Code auch mit Optimierung. D.h. zwischen setzen des Ports und Einlesen muss gewartet werden. Bei der Variante ohne Optimierung hat es funktioniert, weil eben der LDS Befehl zwei Zyklen benötigt. Jedoch habe ich noch eine Frage. Sieht man sich den Schaltplan im Datenblatt des ATMega16 für eine Schnittstelle an, so sieht man das die Einsynchronisierung über ein Latch und ein D-FF geschieht, welche aber anscheinend immer aktiv sind (keine enable-Leitungen). Dann müsste aber, wenn ich die Taste drücke und eine Zeile des Tastenfelds fix auf 0 liegt, der neue Wert einmal in das PINxn Register übernommen werden. -> somit bräuchte ich theoretisch kein "NOP". Kann mir das bitte einer erklären.
> D.h. zwischen setzen des > Ports und Einlesen muss gewartet werden. Das ist ein alter Hut. Bin ich auch schon drüber gestolpert. ;-) Beispielsweise im Datenblatt vom ATmega640 & Co., Seite 86 Mitte: ``When reading back a software assigned pin value, a nop instruction must be inserted as indicated in Figure 35. The out instruction sets the "SYNC LATCH" signal at the positive edge of the clock. In this case, the delay tpd through the synchronizer is 1 system clock period.''
"welche aber anscheinend immer aktiv sind (keine enable-Leitungen)" Brille putzen. Seite 51.
GasmixMan wrote: > funktioniert der Code auch mit Optimierung. D.h. zwischen setzen des > Ports und Einlesen muss gewartet werden. Bei der Variante ohne Das ist ein generelles Problem aller 1-Zyklus-MCs, auch bei den neuen 8051-ern (z.B. AT89LP4052) ists auch so. Man muß mehrere Sachen machen, hat aber nur einen Taktzyklus. Also macht man mehreres parallel, d.h. der eine Befehl wird komplettiert, während der nächste schon beginnt. Bei den PICs gibt es sogar noch etwas ganz verrücktes. Wenn man 2 Read-Modify-Write Befehle hintereinander schreibt, wird nur der letzte wirklich ausgeführt. Der letzte liest das Portregister bevor der erste die Änderung zurückgeschrieben hat und damit ist die Änderung verloren. Die AVRs und 8051 machen es aber korrekt. Peter
@Peter: Bei welchen PICs gibt's das? Das heisst nämlich, dass der Compiler auf solche Spässe Rücksicht nehmen muss. Die normale 18er jedenfalls sind laut Doku 4-Takter ohne solches Problem.
Servus! Also die Synchronisierschaltung ist immer aktiv siehe S. 51 -> von wegen Brille putzen. Das Problem liegt in der Zeile "setPortHighKEY()", dort werden innerhalb der Schleife alle Zeilen auf '1' gelegt und dann erst die entsprechende Zeile auf '0'. Somit brauche ich das "NOP" wirklich. ``When reading back a software assigned pin value, a nop instruction must be inserted as indicated in Figure 35. The out instruction sets the "SYNC LATCH" signal at the positive edge of the clock. In this case, the delay tpd through the synchronizer is 1 system clock period.'' Hatte ich gelesen und verstanden. Dennoch machte ich den Denkfehler bzw. "Betriebsblindheit", dass die Leitung konstant auf '0' gelegt wird. Dann bräuchte ich das "NOP" nicht, da der PIN Wert durch eine externe Quelle (der Benutzer) verändert wird und durch den dauernd aktiven Synchronizer würde mal ein veränderter Wert eingelesen. Habs im Code einfach übersehen. Danke.
Sorry für das "Brille putzen", war ein Missverständnis. Bei Latches hat der Begriff "Enable" eine besondere Bedeutung.
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.