Hallo, erstmal danke für das tolle Tutorial, bisher hat alles wunderbar geklapt. Jetzt wollte ich mich mit dem UART beschäftigen. Dabei habe ich allerdings einige Probleme. Leider konnte mir die Suche bisher auch noch nicht helfen. Das ganze ist auf einem Bread Board aufgebaut, ich Benutze einen ATmega8 (ATMEGA 8-16 DIP). Der Aufbau ist soweit genau wie im Tutorial beschrieben, mit der kleinen Ausnahme das ich einen normalen Quarz verwende (http://www.reichelt.de/?SID=X;ACTION=3;LA=4;GROUP=B41;GROUPID=3173;ARTICLE=2449;START=0;SORT=artnr;OFFSET=16). Den habe ich wie im Datenblatt auf Seite 25 beschrieben mit 22pF Kondensatoren angeschlossen. Als Programm verwende ich das erste Beispiel (uart-mega8.asm) von http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART Ich habe schon diverse Taktgeber Kombinationen versucht (externer Quarz, sowohl den internen 1Mhz und 4Mhz). Als Verbindung zum Computer habe ich sowohl einen normalen Seriellen Anschluss als auch ein USB Adapter verwendet, jedoch mit dem selben Ergebnis. Am Computer kommt nur jede Menge müll an, das beste Ergebnis habe ich bisher mit .equ CLOCK = 1000000 (interner Taktgeber, alle FUSES im Auslieferungszustand) .equ BAUD = 4800 gemacht. Am Computer habe ich entsprechend 4800,8,N,1 eingestellt, damit bekam ich jedoch wiederum nur Müll. Ich habe es dann auf 9600 gestellt (nur am PC, nicht im Programm), dann habe ich schon einige "Test!"s empfangen, jedoch immer noch mit einer menge Müll (siehe Anhang). Ich weis nicht woran es noch liegen könnte. Desweiteren ist mir ein kleiner Fehler im aufgefallen, dort findet man diese Zeile: UBRR = Taktfrequenz / 16 * Baudrate - 1 Die Klammern fehlen.
Hi! Wenn du nach UBRR den (Wert deines Quarzes(in Hz)/(16 x gewünschte Baudrate)-1) lädst, sollte es auch klappen. MFG Uwe
habe diese zwei Zeilen hinzugefügt: ldi temp, UBRRVAL out UBRR, temp Resultat: error: Undefined symbol: UBRR
Beim ATMega8 muß das so aussehen: ldi r16,25 ;9600 Baud @ 4MHz out UBRRL,r16 ldi r16,0 out UBRRH,r16 Das Register heißt UBBRL und nicht UBRR.
Außerdem: Nimm auf jeden Fall einen EXTERNEN Quarz, der interne Oszillator funktioniert manchmal, manchmal aber auch nicht. Mit einem externen Quarz, am besten einem Baudratenquarz, bist Du auf jeden Fall auf der sicheren Seite.
Mit den 4 Befehlen habe ich wieder ein ähnliches Phänomen, am Computer habe ich 9600 eingestellt => nur Müll. Mit 19200 kann man wiederum einige verstümmelte Test lesen. Ich hab es sowohl mit dem internen als auch mit dem externen getestet. Ich habe hier noch zwei andere Atmels, einen mega162 und einen kleinen tiny2313, ich werde mal gucken ob ich die zum laufen bekomme. Die ganze Geschichte mit den Oszilatoren ist ziemliches Neuland für mich, das es mit dem Internen öfters zu Problemen kommt habe ich hier schon mehrfach gelesen, aber woran erkenne ich den einen "Baudratenquarz"?
Hi! Du musst natürlich den Wert für UBRR(L/H) immer mit deiner verwendeten Quarzfreq. neu berechnen und eintragen. Nochwas, wenn der Wert für UBRR(H/L) <255 ist, reicht es UBRRL zu beschreiben. MFG Uwe
Genau das mach ich ja eigentlich auch, mit 4Mhz Quarz=> 4M/(16*9600)-1 = 25 ldi r16, 25 out UBRRL,r16 ldi r16, 0 out UBRRH,r16
habe es jetzt mal mit dem mega162 versucht, mit dem internen war nix zu machen, mit dem externen 4Mhz läuft es jetzt auch mit der richtigen Baudrate, aber es kommt immer noch eine menge Müll an.
Hast Du auch die Fuses geändert? Einfach nur einen externen Quarz hinhängen bringt nämlich nix, Du mußt auch die Fuses ändern. Ich habe auch einen 4MHz-Quarz bei 9600 Baud, die 25 ist schon richtig...
Hier is mal ein total simples Programm, mit dem ich teste, ob die USART-Hardware funktioniert. Sendet nach einem Reset "Ben!" per USART und macht danach nichts mehr. für 9600 Baud @ 4 MHz Gerade nochmal probiert, funktioniert. ;Sendet "Ben!" .include "m8def.inc" .def usart_send = r17 .org 0x000 rjmp reset ; /*Interrupts: .org 0x001 reti .org 0x002 reti .org 0x003 reti .org 0x004 reti .org 0x005 reti .org 0x006 reti .org 0x007 reti .org 0x008 reti .org 0x009 reti .org 0x00a reti .org 0x00b reti ;rjmp Usart_RXC ; USART RX-Complete .org 0x00c reti .org 0x00d reti ;rjmp Usart_TXC ; USART TX-Complete .org 0x00e reti .org 0x00f reti .org 0x010 reti .org 0x011 reti ; Interrupts*/ reset: ldi r16,low(RAMEND) ; Stack out SPL, r16 ldi r16, high(ramend) out SPH, r16 ldi R16, 25 ; UBBR:9600 Baud @ 4MHz out UBRRL, r16 ldi r16,0 out UBRRH, r16 ldi r16,(1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1) out UCSRC, r16 ldi r16, (1<<TXEN) ; | (1<<RXEN) out UCSRB, r16 sei ;Enable Interrupts ;Sendet Ben! ldi usart_send,'B' rcall SEND ldi usart_send,'e' rcall SEND ldi usart_send,'n' rcall SEND ldi usart_send,'!' rcall SEND ldi usart_send,13 ;Carriage Return (CR) rcall SEND ldi usart_send,10 ;LineFeed (LF rcall SEND MAIN: rjmp MAIN SEND: sbis UCSRA,UDRE rjmp SEND out UDR,usart_send ret
Danke, es läuft jetzt, die Fuses, etc. waren alle richtig gesetzt. Das Problem lag an der Spannung, ich habe hier eigentlich eine kleine konstant Spannungsquelle wie im Tutorial beschrieben aufgebaut, beim Messen kam 5,04V raus. Ich habe durch Zufall die Spannung auf 4V runtergesetzt, damit läuft es jetzt wunderbar. Obwohl laut Datenblatt eigentlich 4,5V - 5,5V möglich sein sollen.
@ Frederik: Meinst Du Vcc vom Atmega8 ? Mit richtiger Spannung funktioniert es jetzt? Ich habe nämlich bei mir genau das gleiche Problem: Uart sendet und ich empfange nur kryptische Zeichen mit dem Terminal Programm.
Ich habe das komplette Breadboard auf 4V gesetzt, nicht nur Vcc/AVcc vom mega8, auch Vcc vom meinem MAX3232. Der MAX lief allerdings auch problemlos auf 5V (per loopback getestet). Probier es einfach mal aus die Spannung nen bisschen runterzuregeln. Ich werde nachher auch nochmal genau gucken wo der Problem Punkt liegt.
Also ich hab als Spannugn ~5V auf µC und am MAX232. Trotzdem funktioniert das Senden nicht richtig. Mein Problem liegt darin: Wenn ich z.B. sende "aaaabbbbcccc" dann kommt auf dem Terminal-Prog raus ";;;;9999====". Also alles irgendwie "verschoben". Die Anzahl der Zeichen stimmt schon, nur empfange ich das gesendete Zeichen nicht. Vielleicht liegt es an der Übertragungsart?
5,04 V dürfen aber eigentlich nicht das Problem sein. Ich hab die MAX232 CPE von Reichelt, funktionieren wunderbar.
Ich hab auch mit dem Oszi gemessen. Am Ausgang des MAX232 kommen -10 und +10V Pegel heraus. Also das stimmt schon alles. Kann sein das die Ursache im HyperTeminal Programm liegt, dass ich das falsch eingestellt habe? Weil gesendet wird ja was, das sehe ich auch mit dem Oszi.
Hmm. Auch aus dem Vergleich der Bitmuster werde ich nicht schlauer
1 | a a a b b b c c |
2 | 61 61 61 62 62 62 63 63 |
3 | 01010001 01010001 01010001 01010010 01010010 01010010 01010011 01010011 |
4 | |
5 | ; ; ; 9 9 9 = = |
6 | 3B 3B 3B 39 39 39 3D 3D |
7 | 00111011 00111011 00111011 00111001 00111001 00111001 00111101 00111101 |
Das ergibt irgendwie nicht wirklich was. Da ist keine Verschiebung oder sowas zu erkennen. Auch die doppelte Baudrate scheidet aus, weil ja die Anzahl der gesendeten Zeichen mit der Anzahl der empfangenen Zeichen übereinstimmt. Trotzdem würde ich mal auf ein Timing Problem tippen. Wenn beide Schnittstellen (µC und PC) auf 8N1 eingestellt sind, ist eine nicht funkionierende RS232 eigentlich praktisch immer eine Timing-Sache. Die Sache mit der Versorgungsspannung weiter oben, mag ich kaum glauben. Ich kann mir beim besten Willen nicht vorstellen, wie die die Übertragung beeinflussen kann. D.h. Ich könnte mir schon was vorstellen: interner Oszillator als Taktgeber, aber der wurde ja explizit ausgeschlossen.
Also ich hab µC sowie PC auf 8N1 Übertragung @ 9600 Baud eingestellt. Der Controller ist ein Atmega8 @ 4Mhz. Die Anzahl der Empfangenen Zeichen stimmt mit der Anzahl der Gesendeten überein, jedoch ist das übertragene Zeichen meist ein anderes. Benutze ein externen Quarz, Fuses: CKSEL=1110 SUT=10 (müsste alles richtig sein soweit...) Ich poste hier mal mein .c Prog vielleicht kann man da den Fehler finden: Danke schonmal! #includes..... #define F_CPU 4000000UL #define BAUD 9600UL #define UBRR_BAUD ((F_CPU)/(16*(BAUD))-1) // ************************************* UART_EINSTELLUNGEN void uart_init(void) { UCSRB |= (1<<TXEN) | (1<<RXEN); // UART TX, RX einschalten UCSRC |= (1<<URSEL) | (3<<UCSZ0); // Asynchron 8N1 // UART Baudrateregister setzen UBRRL = (uint8_t) UBRR_BAUD; UBRRH = (uint8_t) (UBRR_BAUD>>8); } // ************************************* UART_SENDE_FUNKTIONEN int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = c; return 0; } void uart_puts(char *str) { while (*str) { uart_putc(*str++); } } // ************************************* HAUPTPROGRAMM int main(void) { uart_init(); while( 1 ) { uart_puts("AAAABB"); } return 0; }
> // UART Baudrateregister setzen > UBRRL = (uint8_t) UBRR_BAUD; > UBRRH = (uint8_t) (UBRR_BAUD>>8); Zuerst das Highbyte setzen und dann das LowByte. Mit dem Setzen des LowBytes werden beide in die tatsächliche Verarbeitung übernommen. Obwohl: Das High Byte ist doch bei deinen Werten sowieso 0. Egal: Einen Versuch ist es wert.
Hallo Martin, hab Dein Programm gerade bei mir laufen lassen, bei mir funktioniert es. Der Fehler liegt also woanders. Hab Dir mal das benutze Makefile mit angehängt, hab allerdings nichts daran geändert. Viel Glück bei der Fehlersuche!
Dein Tip hab ich mal umgesetzt mir der Reihenfolge, aber daran liegts auch nicht. Ich check morgen mal die Hardware vom MAX232, vielleicht spinnt der. Aber dass 5V Pegel in -10V und 0V in 10 gewandelt werden ist schon richtig oder?
Also bei mir spinnt das Ding ab 4,7/4,8V, zu Weihnachten gibst mal nen anständiges Labornetzteil ;). Den MAX kannst du eigentlich recht einfach testen, schliss einfach die TX/RX Pins den du normalerweise an den µC anschließen würdest kurz, und dann tipp nen bisschen im hyperterminal rum, du solltest alles was du eingetippt hast genauso wieder angezeigt bekommen.
Im Anhang hab ich ein leicht verändertes Programm aus dem Tutorial, sollte einfach alles was rein kommt wieder raus schicken, bei mir klappt es auch.
Ich hab mal nachgemessen: Da wo die Kondensatoren angeschlossen sind an dem MAX232 ist eine Wechselspannung anliegend, von ca. 190 kHz. Da frag ich mich doch was das soll.... Vom Netzteil kommt nur 5V rein und die ist sehr glatt. Der Receive Kanal funktioniert nicht, aber der wird ja auch beim Senden nicht benutzt, also ist das keine Lösung für mein Problem.
So ich hab das Problem gelöst. Der GND Pin hatte ich falsch angeschlossen (schäm)das war aber nicht nur das Problem, sondern auf dem Laptop funktioniert die Ausgabe nicht, auf einem normalen PC aber schon. Verkehrte Welt...
Ich habe das Problem gefunden. Ich habe den 22µF/63V Elko zwischen dem GND/VCC Pin des MAX 232 ICs durch einen 100nF Keramik Kondensator ersetzt. Jetzt klappt es auch wunderbar mit 5V. Sobald ich den Kondensator auch nur über 5cm Kabel anschließe klappt es schon nicht mehr, wirklich nur wenn man den Kondensator direkt an die zwei Pins klemmt.
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.