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.
Hi Überprüfe mal, ob du nicht den 5Bit-Modus bei der UART eingestellt hast. @ Online Debugger 'char' sollte eigentlich bis 127 gehen. MfG Spess
korrektur zu meinem oberen Beitrag: 63 dez entspricht 00111111b (0x3F), es sind nur die obersten 2 Bit nicht korrekt. daniel
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...
Hier meine Funktionen, dies betrifft:
1 | void UART_Init(void) |
2 | {
|
3 | DDRD = (1 << PD1) | (0 << PD0); |
4 | |
5 | UCSRB |= (1 << RXCIE) | (0 << TXCIE) | (1 << RXEN) | (1 << TXEN); |
6 | |
7 | // Baudrate: 19200bps bei 8MHz
|
8 | UBRRL = 25; |
9 | UBRRH = 0; |
10 | }
|
11 | |
12 | |
13 | void UART_send_char(unsigned char data) |
14 | {
|
15 | while (!(UCSRA & (1<<UDRE))) |
16 | {
|
17 | ; // warten, bis UDR leer ist |
18 | }
|
19 | UDR = data; |
20 | }
|
Sieht doch eigentlich gut aus oder?
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...
Vielleicht zeigt VB die nicht darstellbaren Zeichen (also 0xFF) nur einfach als '?' an.
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!
bushobbyentwickler wrote:
>
1 | > void UART_Init(void) |
2 | > { |
3 | > DDRD = (1 << PD1) | (0 << PD0); |
4 | >
|
5 | > UCSRB |= (1 << RXCIE) | (0 << TXCIE) | (1 << RXEN) | (1 << TXEN); |
6 | > } |
7 | >
|
8 | >
|
> > 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 :(
Das Teil ist wirklich super!!! Also der MC sendet 0xFF, dann liegt es 100%ig an der VB-Komponente.
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?
Kommt denn eine 62d an, wenn du 254d übermittelst? Nicht, dass die 63d gar nichts mit den übertragenen Bytes zu zun hat.
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.
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.