Hallo!
Ich versuche mich gerade an einem Kabeltester und bin am verzweifeln.
Ich habe ein Kabel mit 10 Leitungen. Also habe ich 10 Ausgänge und 10
Eingänge. Ich gebe auf die Ausgänge nacheinander ein 5V-Signal und messe
bei den Eingängen was ankommt. Manchmal ist in den Steckern gewollt eine
Brücke. Um sämtliche Kabelbelegungen nicht softwaretechnisch speichern
zu müssen gibt es einen Lernmodus. Man steckt ein Musterkabel auf uns
drückt auf einen Taster. Der Atmega8535 merkt sich das was beim Muster
zurückkommt als Referenz. Dann soll man mit einem Taster "Messen" andere
Kabel auf Unterschiede zum Muster durchmessen können.
Nun zu meinem Problem: Ich speichere die 10 Eingangssignale in einem 10
Felder großen uint16_t array ab. Bei der Messung werden wie bei dem
Lernmodus ebenso auf alle Leitungen nacheinander 5V gegeben und dann
soll der Wert an PINC bzw. PIND mit dem gespeicherten Wert verglichen
werden. Wenn das Programm im Debugger in die Funktion vergleiche_pin()
reinspringt zeigt er mir für die übergebene Variable "vergleichswert" 0
an. An PD3 liegt ebenfalls 0V an. Trotzdem springt die Result-Variable
"res" auf 0. wieso? Mache ich beim Bitvergleich irgendwas falsch?
Verträgt er evtl den Vergleich eines 8-Bit mit einem 16-Bit Wert nicht?
Speichert er den 16-Bit Wert anders ab (LSB, MSB)? Ich komm nicht
weiter!
Danke für eure Antworten!
Gruß,
Alex
1
voidnaechster_pin(volatileintakt_pin){
2
//Gibt immer auf den nächsten Pin eine 1 und setzt alle anderen Pins auf 0
Und hier wolltest du wohl auch eher PINC und PCx haben.
Außerdem überall "(PXx)" durch "(1<<PXx)" ersetzen.
Wird aber trotzdem nicht funktionieren, denn da die Bitpositionen von
den Ports und in res nicht übereinstimmen, kannst du nicht mit einem
direkten Vergleich arbeiten.
(Rest des Codes habe ich mir nicht weiter angeschaut)
PS: Du hast offensichtlich die Bedeutung von "volatile" nicht
verstanden. Das bitte nochmal nachlesen.
Hallo!
Vielen Dank für den Hinweis. Du hast aber Recht - es funktioniert
trotzdem nicht.
volatile bedeutet doch, dass der Compiler die Variablen nicht optimieren
(kürzen) soll, damit diese verändert werden können und kein Speicher
überschrieben wird, oder? Deswegen habe ich jede verändernde Variable so
deklariert. Ich werde es mir aber nochmal durchlesen.
Trotzdem bleibt mir ein Verständnisproblem. Mit
1
((PIND&(1<<PD1))
selektiere ich doch das Bit und es sollte als Ergebnis 0 oder 1 geben.
Mit
1
(vergleichswert&0b0000000001000000))
wird ebenfalls ein Bit ausgewertet was zu einem Ergebnis 0 oder 1 führen
sollte. Diese sollte das Programm doch auswerten können, oder?
Hallo Alex,
> überschrieben wird, oder? Deswegen habe ich jede verändernde Variable so> deklariert. Ich werde es mir aber nochmal durchlesen.
Vor Deine Funktionen gehört kein "volatile", auch nicht vor die
Variablen innerhalb der Funktionen (falls eine Variable von einem zum
nächsten Aufruf erhalten bleiben soll, sollte sie "static" sein). Es
wird nicht schaden, alle globalen Variablen "volatile" zu machen. Das
ist stark vereinfacht, sollte aber am Anfang OK sein.
> Trotzdem bleibt mir ein Verständnisproblem. Mit>
1
((PIND&(1<<PDx))
> selektiere ich doch das Bit und es sollte als Ergebnis 0 oder 1 geben.
Ja, Du selektierst das Bit; nein, das Ergebnis kann zwischen 0 und 128
liegen!
Stell Dir vor, bit 3 in PIND ist gesetzt und Du verknüpfst
1
PIND&(1<<PD3)
Also bekommst Du 0b1000 als Ergebnis; nicht 1 und nicht 0!
> mit
1
(vergleichswert&0b0000000001000000))
> wird ebenfalls ein Bit ausgewertet was zu einem Ergebnis 0 oder 1 führen> sollte.
Siehe oben -- gleiches Problem! Und dann vergleichst Du 8-Bit mit
16-Bit-Werten; Gleichheit kann nur dann gegeben sein, wenn der 16-Bit
Wert <256 ist.
Gruß
Fred
aah - jetzt verstehe ich es.
Ich habe das Problem mittlerweile so gelöst, dass ich wie in der
Lernphase die Pegel an PINC und PIND in einer 16-Bit Variable speichere
und beide Werte zum Schluß vergleiche. So funktioniert es.
Vielen Dank für die schnelle Hilfe(n).
Gruß,
Alex
Fred S. wrote:
> Es> wird nicht schaden, alle globalen Variablen "volatile" zu machen.
Doch: die fehlende Optimierung kann man schon als Schaden ansehen,
das ist einfach lausig.
Selbst solche Variablen, die volatile sein müssen, cachet man u. U.
besser in einer separaten (lokalen) Variable, bspw. innerhalb einer
ISR, um die durch volatile entstehende Pessimierung der Zugriffe
abzufedern.
Hallo Jörg,
erklär das mal bitte dem OP so, dass er es auch versteht. Ich habe extra
dazugeschrieben, dass das "stark vereinfacht" ist und ich dies "am
Anfang" empfehle und hatte mir sogar überlegt, eine Warnung
dazuzuschreiben, um nicht gleich eine Flame wie Deine auszulösen. Deine
in meinen Augen überaggressive Reaktion (als "einfach lausig" lasse ich
meine Hilfestellung, die eindeutig der Erfahrung des OP angepasst war,
nicht sehr gerne bezeichnen!), wo ich nicht verallgemeinert habe, finde
ich sehr bedauerlich. Wo siehst Du ein Problem durch "fehlende
Optimierung" beim obigen Code?
Gruß
Fred
Ich kann Jörg nur beipflichten: volatile sollte man ganz bewusst
einsetzen, auch als Anfänger. Pauschal alle externen Variablen damit zu
schmücken, ist blanker Unsinn. Auch für Anfänger.
volatile sagt dem Compiler, daß sich diese Variable ändern kann, ohne
das dieses für ihn aus dem Programm ersichtlich ist. Prinzipiell "weiss"
der gcc aber immer ganz genau, ob sich der Wert einer Variable seit der
letzten Benutzung geändert haben kann. Kann sich der Wert nicht geändert
haben, nutzt er alle Optimierungsmöglichkeiten, z.B, den Wert in einem
Register zu halten, anstelle den Speicher bei jeder Verwendung neu zu
lesen.
Die einzigen Fälle, die der Compiler übersieht (weil C das per
Definition gar nicht kennt), sind Variablen, die in einer ISR UND in
einem Hauptprogramm verwendet werden, sowie Adressen im Speicherbereich,
die sich selbständig ändern (IO-Register, Hardwarezähler, usw.). Dafür
ist volatile da.
Im o.a. Programm gibt es gar keine ISR. Insofern braucht es da nirgends
ein volatile. Die IO-Register sind in den ioxxx.h-headern sowieso
volatile definiert.
Oliver
Fred S. wrote:
> ..., um nicht gleich eine Flame wie Deine auszulösen.
Naja, irgendwie übertreibst du ganz schön.
> Deine> in meinen Augen überaggressive Reaktion (als "einfach lausig" lasse ich
Sorry. Es war wohl leider doch etwas zu früh am morgen. :-( Das
sollte eigentlich heißen: ,,der dabei generierte Code ist einfach
lausig''. Das war keineswegs auf deine Hilfestellung bezogen.
> Wo siehst Du ein Problem durch "fehlende> Optimierung" beim obigen Code?
Wenn jemand nicht optimieren will, soll er einfach mit -O0 arbeiten.
Wenn aber jemand offensichtlich keine rechte Vorstellung davon hat,
was volatile bewirkt (einerseits, warum man es manchmal braucht,
andererseits, wie schlecht der generierte Code davon wird), dann
ist es in meinen Augen halt kein guter Rat, ihm zu schreiben: ,,lass
es erstmal, kann ja nichts schaden''. Der in meinen Augen bessere
Rat wäre es gewesen: ,,lass volatile erstmal weg, bis du weißt, warum
und wofür man es braucht''.