Hallo,
ich habe in einem Programm den Fehler, dass ein Wert aus dem EEPROM
gelesen wird und über UART an den PC gesendet wird. Dort kommen aber nur
Werte kleiner 64 an. Wenn im EEPROM 0xFF drinsteht, dann wird 63 an den
PC gesendet. Steht im EEPROM an der Stelle ein Wert kleiner 63, dann
wird der richtige Wert über UART gesendet!
Ein anderer Fehler in diesem Programm ist, dass eine LED mit einer
ungefähren Frequenz von 1Hz mittels eines Delays in der Endlosschleife
in der Main blinkt. Sende ich Daten über UART an den MC, dann blinkt die
LED extrem langsamer (60sec für an und aus anstatt 1sec)???
Da ich mit dem STK500 programmiere habe ich dazu eine allgemeine Frage:
Wenn ihr einen Fehler im Programm habt und nich wisst woran es liegen
kann, wie geht ihr dann vor, um den Fehler zu finden?
Vielen Dank schonmal
Hi,
prinzipiell sollte man sich nochmal den Code genau ansehen. Und nochmal
das Funktionsprinzip ueberpruefen ob dieses auch wirklich korrekt
umgesetzt wurde.
Erfahrung spielt beim Debuggen schon eine grosse Rolle, denn mit jedem
Fehler den man findet, lernt man dazu.
Es gibt verschiedenen Fehler,die leichtesten sind die syntaktischen ;),
das sind Fehler wo der Compiler meckert. Dann kommen die systematische,
von den hast du 1 in deinem Programm(Fehler mit den Bits). Dass sind die
wo der Compiler nicht mehr meckert, aber dafuer der Kunde :). Und dann
kommen die ganz fiesen Fehler, dass sind dann die stochastischen, wo die
systematik stimmt aber troztdem spinnt das Programm wegen den
Interrupts. Passieren oft nur zufaellig und sind deswegen schwer zu
finden. Davon hast du auch einen (deine LED) obwohl man den leicht
findet. Das sind so die bekanntesten Fehlerklassen.
Am wichtigsten ist es immer den Code nochmal anschauen und ueberdenken
was man da wirklich geschrieben hat. Dann auf die Variablen achten und
vor allem die Array. (Schreibt man mehr daten in ein array als da hinein
passen, dann schreibt der uC munter weiter im Speicher und ueberschreibt
benachbarte Variablen im Speicher )
Fuer dein Problem mit dem UART kannst du schauen ob wirklich alle Bits
deines Bytes uebergibts, oder ob nicht ein anderer Programmteil ein Teil
des Bytes ueberschreibt. Denn 63 dez enspricht 00011111b (binaer), das
bedeutet das deine obersten 3 bit von deinem Wert auf 0 gesetzt werden
(durch ein AND irgendwo?, die Einstellung im UART?, ... )
Fuer dein Problem mit deiner LED, kann ich folgendes sagen. Da du sie in
der Main- Schleife laufen laesst und die Zeit ueber eine Endlosschleife
regelst, ,kann folgendes passieren. Dein Program in der "Main-Schleife"
wird ausgefuehrt und ploetzlich moechte aber der UART ein Zeichen
senden, dann hat der UART (ein Interrupt) Vorang (eine hoehere
Prioritaet) vor deinem Program und arbeitet sein Programmabschnitt(vom
UART) ab. Wenn dieser nun sehr lang ist oder du dort auch noch
Endlosschleifen einsetzt, dann arbeitet der Mikrocontroller die ganze
Zeit am UART und zaehlt nicht mehr an der Endlosschleife im "main"
weiter. Irgendwann ist er dann fertig mit dem UART und zaehlt nun noch
zusaetzlich die Zeit deiner Endlosschleife ab. Aber halt, der
Programmabschnitt vom UART Interrupt moechte nun nochmal senden ;).
So kann es leicht passieren das deine LED dann 1min braucht, statt 1s.
Denn die Zeit deiner Endlosschleife in "main" und die mehrmalige Zeit
vom dem "UART- Interrupt" (so oft er eben waerende der Endlosschleife
senden moechte) addieren sich.
Hoffe es ist verstaendlich, wenn nicht weiterfragen.
daniel
> Wenn im EEPROM 0xFF drinsteht, dann wird 63 an den> PC gesendet. Steht im EEPROM an der Stelle ein Wert kleiner 63, dann> wird der richtige Wert über UART gesendet!
du arbeitest irgendwo mit char, wo 'unsigned char' hin sollte.
Ich würde das Programm in Einzelteile zerlegen und diese gezielt prüfen.
Sicher, dass deine Datenquelle wirklich Zahlen > 63 erzeugt? Ich würde
versuchen einen hart verdrahteten Wert zu übermitteln und alle nicht
benötigten Programmteile auszublenden.
Wenn das dann immer noch nicht geht einfach die USART-Routine neu
schreiben und wenn die funktioniert mit der alten vergleichen.
Wenn das Problem verschwindet liegt's an der Datenbeschaffung, für die
uns hier noch ein paar Infos fehlen...
Viel Erfolg
Kai
>Überprüfe mal, ob du nicht den 5Bit-Modus bei der UART eingestellt hast.
6 Bit meintest du vermutlich :)
Wehe daran liegt's - na gut, kann ja auch versehentlich passieren.
@bushobbyentwickler
Debuggen ist das Lösen eines Problems durch das Aufteilen in einzelne
kleine Probleme (Teile und Herrsche).
Teil dein Problem in einzelne kleine Aufgaben auf:
1) Stell erst mal sicher, dass die serielle Schnitte funktioniert. Sende
ein Zeichen vom PC zum AVR ändere die Bits (z.B. incrementieren,
decrementieren, interiteren) und schick das Zeichen zurück.
2) Wenn das geht, kommt das EEPROM dran....
3) Wenn das geht, ...
Alles gleichzeitig zum Laufen gekommen ist meines Wissens das letzte Mal
bei Frankenstein (und das Ergebnis war nicht gut!).
Vielen Dank für die Antworten!
Zu dem Problem mit UART:
Ich habe mal probiert sonstwo in dem Programm einfach nur das Byte 0xFF
rauszuschicken. Am PC kommt da nur '?' (0x3F) an.
Ich hab echt keine Ahnung woran es liegt...
Im ganze Programm schick ich hin und wieder Daten an den PC, allerdings
nur kleine Werte (also nie über 63) deshalb fällt mir der Fehler jetzt
erst auf...
Ich hab jetzt mal im HyperTerminal angeschaut was der MC scickt: y mit
Doppelpunkt also 0xFF!!!!
Dann liegt der Fehler wohl an der Windows-Anwendung. Da verwende ich
Visual Basic (2008) mit der integrierten COMport-Komponente. Dann wird
da wohl irgendwo der Fehler liegen, obwohl eigentlich alles richtig
eingestellt ist...
Ich empfehle unbedingt einen richtigen Debugger zur Unterstützung der
Fehlersuche. Ich weiß nicht, mit welchem Mikrocontroller du arbeitest,
ich verwende z.B. den AVR Dragon für den Atmega168. Da kannst du dann
den C-Sourcecode Zeile für Zeile durchsteppen, Variablen anschaun und
ändern, und du kannst richtig "sehen" wohin das Programm läuft -
wunderschön! Ohne Debugger ist es oft echt sehr sehr mühsam, es ist wie
ein Tappen im Dunkeln und Raten, was das Programm wo vielleicht tut.
Warum sich das Leben unnötig schwer machen, der Dragon kostet nicht die
Welt!
>> Sieht doch eigentlich gut aus oder?
eine 0 irgendwohin zu schieben ist absolut sinnlos, da es immer eine 0
bleiben wird, und "irgendwas oder 0" immer "irgendwas" bleibt.
(logische) linksschiebeoperationen kann man sich auch wie eine
multiplikation mit einer 2er-potenz vorstellen, also
umgekehrt "entspricht" eine rechtsschiebeoperation einer
ganzzahldivision durch eine zweierpotenz.
zum thema uart:
besorg dir das programm "portmon" (afair von sysinternals), damit kannst
du die komplette kommunikation über die serielle und parallele
schnittstelle(n) aufzeichnen.
da du mit hyperterminal bereits "richtigere" daten empfangen hast als
mit vb, check mal die baudraten- und formateinstellung der vb-komponente
und rechne nochmal nach, ob der uC wirklich eine brauchbare baudrate
erzeugt...
Daniel F. wrote:
> eine 0 irgendwohin zu schieben ist absolut sinnlos, da es immer eine 0> bleiben wird, und "irgendwas oder 0" immer "irgendwas" bleibt.
Nicht "sinnlos" sondern "wirkungslos". Es ist hier durchaus sinnvoll, da
es dokumentiert, dass beispielsweise der RX Interrupt ausgeschaltet
bleibt.
Andreas Kaiser wrote:
> Nicht "sinnlos" sondern "wirkungslos". Es ist hier durchaus sinnvoll, da> es dokumentiert, dass beispielsweise der RX Interrupt ausgeschaltet> bleibt.
Dann müsste man aber immer alle 8 Bits hinschreiben.
Außerdem ging es hier um eine »|=«-Operation, dann bleibt der
Rx-Interrupt trotzdem eingeschaltet, sofern er es vorher schon war.
In diesem Kontext also wirklich sinnlos.
@ Daniel F.
1 x 2 = 4, das hat was ;-)
Das Schieben einer 0 ist zur Dokumentation sinnvoll
und kostet keine Rechenzeit, weil das ja der Compiler schon ausrechnet.
Großbuchstaben sind im Deutschen anerkannte Hilfsmittel zur
Textdarstellung.
Sie verringern die Lesbarkeit eines Textes nicht im Mindesten.
Ähnlich wie z.B. auch Umlaute und Doppelkonsonanten.
'tschuldigung, hatte vorher 1 << 1 - da habe ich wohl vergessen, die 2
in 4 zu ändern
aja, und das mit der Kleinschreibung ist wohl z.t. auch Schuld meiner
Professoren - die schreiben auch alles klein ;-)
@ bushobbyentwickler (Gast)
> Ich hab jetzt mal im HyperTerminal angeschaut was der MC scickt: y mit> Doppelpunkt also 0xFF!!!!
Das ist ein allgemeines Problem, wobei ich mir immer noch nicht sicher
bin, wie die Logik dahinter ist in manchen Windowskomponenten.
wie Du schon selbst schreibst, kommt im Terminal das 0xff als y mit
Diaeresis ÿ an, was also der Codierung entsprechend der
Windows-Codepage 1252 entspricht. Eigentlich müsste das immer so sein,
und wäre auch logisch. Allerdings scheint dies auch vom benutzten Font
abzuhängen, ob dies dann richtig angezeigt wird, oder als Fragezeichen
(ein beliebtes Ersetzungszeichen unter Windows, mit 0x3F codiert), oder
in manchen Programmen gar als einfaches Kästchen (was nach reinem
Anzeigeproblem ausschaut).
Beispiel: Datei mit hex werten ff 30 9f 39 3f 30 unter Windows
Problem bei mir (mit WinXP) scheint zumindest das 9f zu sein in einigen
Programmen.
Wordpad (write) und notepad zeigen alles richtig an (ÿ0Ÿ9?0)
Der Lister im Total Commander zeigt dagegen ein Kästchen anstelle des
großen Y mit Diaeresis an. Kopiere ich diesen verunstalteten String ins
Notepad, wird's plötzlich wieder richtig angezeigt (was aber auch nichts
generell sicherstellt). Scheinbar schießt der eingestellte Font hier
quer, oder die vom Programm benutzten Runtime-Libs eincompilierter Code
taugen an der Stelle nicht viel. Die VB Libs scheinen da also auch
irgendwie ihr eigenes Ding zu drehen.
Wenn Du die Möglichkeit hast, die empfangenen Bytes erstmal als Hex
anzuzeigen, dann kannst Du ja damit erstmal die empfangenen Daten
checken.
Das (0 << TXCIE) hab ich drin, weil ich zum Debuggen den TX-Interrupt
ausgestellt habe, also kein Stress!!! ^^
Den Portmon werde ich mal ausprobieren. Wie gesagt: In Hyperterminal
kommt das richtige Zeichen an, nur in meiner Visual Basic - Anwendung
nicht.
Bei der Komponente ist Baudrate, Anzahl Daten- und Stopbits sowie
Parität auch richtig eingestellt...
Stelle ich im MC und in der Anwendung eine andere Baudrate (z.B. 9600)
ein, habe ich genau das gleiche Problem, dass die empfangenen Zeichen
nur Werte von 0 bis 63 haben können!
0011 1111 = 63
-> sieht halt schon sehr danach aus, dass die letzten beiden Bits (LSB
kommt in UART ja zuerst oder?) verdaddert werden...
[quote]Wordpad (write) und notepad zeigen alles richtig an (ÿ0Ÿ9?0)
Der Lister im Total Commander zeigt dagegen ein Kästchen anstelle des
großen Y mit Diaeresis an. Kopiere ich diesen verunstalteten String ins
Notepad, wird's plötzlich wieder richtig angezeigt (was aber auch nichts
generell sicherstellt). Scheinbar schießt der eingestellte Font hier
quer, oder die vom Programm benutzten Runtime-Libs eincompilierter Code
taugen an der Stelle nicht viel. Die VB Libs scheinen da also auch
irgendwie ihr eigenes Ding zu drehen.
Wenn Du die Möglichkeit hast, die empfangenen Bytes erstmal als Hex
anzuzeigen, dann kannst Du ja damit erstmal die empfangenen Daten
checken.[/quote]
Ich habe das betreffende Zeichen schonmal mit Str(Asc(...)) umgewandelt
und in einer MsgBox anzeigen lassen. Und da steht dann der Dezimalwert
63.
Aber ein interessanter Gedanke. Vielleicht entspricht in dem
Zeichensatz, der von der Comport-Komponente verwendet wird das
Fragezeichen '?' dem Wert 0xFF, und bei der Umwandlung mit Asc(...) wird
nach dem dem ASCII-Wert des Zeichens (und nicht nach dem Wert im von der
COM-Komponente verwendeten Zeichensatz) gesucht?!?
ich glaube, 0xff entpricht in keinem Zeichensatz einem Fragezeichen (im
Gegenteil, in den meisten Codepages ist dort sogar gar kein Zeichen oder
ein Steuerzeichen). Aber vielfach wird da '?' einfach als
Ersetzungszeichen verwendet von manchen Win-Komponenten (möglicherweise
auch in VB), vermutlich einfach in der Annahme, daß das ohnehin kein
gültiges Zeichen wäre (vielleicht aus historischen Gründen, wo noch 437
und 850 intensiv genutzt wurden, wo 0xFF ein Sonderzeichen war)
VB enthält wohl immer noch solche Relikte ....
Google einfach mal nach OCCONSOLE
oder schau da vorbei
http://www.elektronikladen.de/occonsole.html
Das Teil ist super, läuft ohne Installation vom USB-Stick
und hat den Binär-Modus, wo ein FF als FF angezeigt wird.
Wird leider nicht mehr weiterentwickelt :(
Also hier mal ein Bild von den Einstellungen der SerialPort-Komponente.
Weiß jemand, was hier der Auslöser sein könnte, dass die ReadExisting
63d zurückgibt obwohl 255d gesendet (und mit einem Terminal-Programm)
empfangen wurde?
Ich hab gestern die Lösung gefunden.
Wenn ich den InPuffer der VB-Komponente mit der Funktion ReadExisting
auslese, enthält der zurückgegebene String nur Werte zwischen 0 und 63
(wieso auch immer).
Lese ich den Puffer dagegen byteweise mit ReadByte aus, dann werden
Werte von 0 bis 255 ausgegeben!
Es gibt auch noch eine Funktion ReadChar, die allerdings wie
ReadExisting nur Werte von 0 bis 63 ausgibt.