Hallo zusammen, Bin gerade am verzweifeln. Habe einen MyAVR Stamp 256k (Da ist ein Atmega 2560 drauf) hier und versuche ihn dazu zu bekommen mittels UART mit HTerm zu kommunizieren. Habe dazu ein einfaches C-Programm geschrieben, dass mir meine Eingabe auf dem Terminal direkt wieder zurückgeben soll. Leider produziert dies jedoch nur Datenmüll. Gebe ich hallo ein kommt hynlo zurück. Wenn mir jemand einen Tipp geben könnte was mein Fehler ist wäre ich euch dankbar. Verschiedene Baudraten habe ich schon getestet. #include <avr/io.h> #include <inttypes.h> #define BAUD 2400UL #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1) // USART initialisieren void uart_init(void) { // Baudrate einstellen (Normaler Modus) UBRR3H = (uint8_t) (UBRR_BAUD>>8); UBRR3L = (uint8_t) (UBRR_BAUD & 0x0ff); // Aktivieren von receiver und transmitter UCSR3B = (1<<RXEN3)|(1<<TXEN3); // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit UCSR3C = (1<<UCSZ31)|(1<<UCSZ30); } int main(void) { uint8_t buffer; // USART initialisieren uart_init(); while (1) { // Warten bis Daten empfangen wurden while ( !(UCSR3A & (1<<RXC3)) ) ; // Empfangsregister auslesen buffer = UDR3; // Warten bis der Sendepuffer frei ist while ( !( UCSR3A & (1<<UDRE3)) ) ; // Daten in den Puffer schreiben und damit senden UDR3 = buffer; } }
Habe disen Code bei mir getestet (nur Register an ATMega8 angepasst), und alles funktionierte einwandfrei. Vielleicht wurde die F_CPU nicht richtig definiert, oder in HTerm-Einstellungen irgendwas übersehen - bei BAUD oder Databits. MfG Kerik
Hallo, Danke für die Antwort. Mit einem Atmega 8 hats bei mir auch funktioniert. Nachdem ich das Programm aber für nen Atmega 2560 umgeschrieben hab gehts nicht mehr. Kann es daran liegen, dass der 2560 mit 16Mhz läuft und ich deshalb einen Fehler in der Baudrate von 0,2% habe? Andreas
An einem Fehler von 0,2 % liegt es mit Sicherheit nicht. Das ist unproblematisch zulässig.
Versuchen Sie mal eine andere Formel für die Berechnung des UBRR Wertes! Die Formel ist auch bei AVR-Tutorial hier auf der Seite angegeben. UBRR = (((F_CPU+BAUD*8)/(16UL*BAUD))-1) Vielleicht wurde bei der ersten Formel unglücklich gerundet. So nur eine Vermutung! MfG Kerik
Dann weiß ich langsam auch nicht mehr weiter. Hab mal manuell versucht UBBR zu verändern. Bei 103 kommt nach Eingabe hallo das schon erwähnt hynlo. Bei 104 gibt hterm hyllo aus und bei 102 hqnlo
Hatte die Bausrate auf 9600 gesetzt für die Sachen die ich im letzten Post geschrieben habe. Wenn ich das mit der Formel ausrechne komme ich auf 103,666. 104 wäre also demnach am nächsten dran
Andreas schrieb: > // Aktivieren von receiver und transmitter > UCSR3B = (1<<RXEN3)|(1<<TXEN3); > > // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit > UCSR3C = (1<<UCSZ31)|(1<<UCSZ30); Tauche mal die Reihenfolge: erst Datenformat, dann Enable. Bei einem anderen AVR hat das schon mal geholfen... Gruß Dietrich
Hi, Das Tauschen und die andere Formel haben leider nicht geholfen. Bekomme bei einem gesendeten Hallo ein Hqllo zurück Andreas
Komme einfach nicht drauf wo der Fehler liegen könnte. Kann es passieren, dass der Quarz eine andere Frquenz liefert als angegeben ist?
Andreas schrieb: > Komme einfach nicht drauf wo der Fehler liegen könnte. > Kann es passieren, dass der Quarz eine andere Frquenz liefert als > angegeben ist? Dein Quarz hat sicher nicht exakt 16000000 Hz. Aber er ist nahe genug drann, dass das kein Problem sein sollte. Hast du schon mal in die andere Richtung den UBRR Wert verändert: 102, 101
Ja, hab ich auch schon. Dann kommt allerdings nur noch Müll. Probiere es gleich nochmal aus und poste dann was genau ankommt
Also bei 104 bekomme ich Hqllo zurück, darunter Hynlo und irgendwann nur noch Müll
Hallo, Andreas schrieb: > #define BAUD 2400UL > #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1) ich verwende nun nur noch diesen schönen Trick mit Rundung:
1 | #define BAUDRATE 9600U
|
2 | #define UBRR_BAUD (uint16_t)((F_CPU) *1.0 / ((BAUDRATE) * 16l) - 0.5)
|
Ich erhalte mit F_CPU=16MHz und 9600 Baud UBRR_BAUD:=103.
Ja, die 103 habe ich auch raus. Damit kommt aber leider nur Müll. Also bei Hallo gesendet Hynlo. Bei 1 kommt 9, bei 2 ein : und bei 3 kommt 3.
ist schon der Tipp mit dem 1/8 Teiler, den man auch per Fuse-Bits ein und ausschalten kann, gekommen? Solche Probleme hallte ich letztens nur mal mit einem Software Uart mit FIFO bei 9600 Baud. Da waren 1MHz dann doch zu langsam und mit 8 MHz lief das gesamte Programm schnell genug.
Hast du mal die anderen UARTs probiert? Kannst du dir die Signale vielleicht mal auf einem Oszilloskop anschauen? Hier mal ein Stück Code wie er bei mir auf einem ATmega2560 läuft.
1 | // set baudrate
|
2 | UBRR3 = (uint16_t)(F_CPU / (baudrate * 16L) - 1); |
3 | |
4 | // set paritymode & number of databits
|
5 | UCSR3C = ((parity & 0x05) << UPM30) | ((stopbits & 0x01) << USBS3) | ((databits & 0x07) << UCSZ30); |
6 | |
7 | // enable RX/TX & interrupts
|
8 | if ( databits == DATABITS_9 ) |
9 | UCSR3B = (1 << RXCIE3) | (1 << UDRIE3) | (1 << RXEN3) | (1 << TXEN3) | (1 << UCSZ32); |
10 | else
|
11 | UCSR3B = (1 << RXCIE3) | (1 << UDRIE3) | (1 << RXEN3) | (1 << TXEN3); |
Hallo, Wollte mich für die vielen Vorschläge bedanken. Habe jetzt einen Codeschnipsel gefunden mit dem ichs zum laufen bekommen habe. Was genau falsch war muss ich morgen mal schaun. Hier ist mein jetztiger Quellcode: (Noch nicht schön aufgeräumt, aber er funktioniert erstmal) #include <avr/io.h> #include <inttypes.h> #define BAUD 9600UL #define UBRR_BAUD (103) // USART initialisieren void uart_init(void) { UBRR3H=0x00; UBRR3L=UBRR_BAUD; //--------------------------- UCSR3A=0x00; // U2X auf LO //--------------------------- UCSR3B=0x00; UCSR3B|=0x80; // Rx Interrupt enable UCSR3B|=0x10; // Rx enable UCSR3B|=0x08; // Tx enable //--------------------------- UCSR3C=0x00; // asyncron, no parity, 1stopbit UCSR3C|=0x04; // 8datenbits UCSR3C|=0x02; // 8datenbits } int main(void) { uint8_t buffer; // USART initialisieren uart_init(); while (1) { // Warten bis Daten empfangen wurden while ( !(UCSR3A & (1<<RXC3)) ) ; // Empfangsregister auslesen buffer = UDR3; // Warten bis der Sendepuffer frei ist while ( !( UCSR3A & (1<<UDRE3)) ) ; // Daten in den Puffer schreiben und damit senden UDR3 = buffer; } }
Andreas schrieb: > UCSR3B|=0x80; // Rx Interrupt enable Ich hoffe du hast auch irgendwo den die passende ISR! Könnte sonst zu komischen Effekten kommen, wenn du irgend wann mal die Interrupts frei schaltest.
In dem Programm noch nicht, brauche es aber dafür was ich im weiteren damit vorhabe. Trotzdem danke für den Hinweis ;-)
Hallo, hatte das selbe Problem beim ATmega 2560. Wenn UBRR definieren will und es mit der Formel ausrechnen lässt kommt nur Mist. Erst wenn man den UBRR-Wert direkt einträgt (in diesem Fall "103") klappt es. So ist es nämlich auch in dem 'Codeschnipsel' der gegen Ende des Threads gezeigt wird auch. Deshalb funktioniert er dann auch. Etwas spät aber vielleicht hilft es ja trotzdem noch ein paar Leuten.
Man könnte allerdings auch der Räucherkerzen anzünden, und fünf mal „UBBR“ rufen. Dann geht es auch, aus den selben Gründen. Oliver
Warum verwendet ihr die Standard-Bibliothek zur Berechnung? https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html
Hi >Wenn UBRR definieren will und es mit der Formel ausrechnen lässt kommt >nur Mist. Erst wenn man den UBRR-Wert direkt einträgt (in diesem Fall >"103") klappt es. Dann ist der GCC anscheinend dämlicher als der Atmel-Assembler. Bei dem bekomme ich problemlos die 0x67 (103) heraus. MfG spess
Beitrag #6642547 wurde von einem Moderator gelöscht.
Beitrag #6642617 wurde von einem Moderator gelöscht.
Beitrag #6642632 wurde von einem Moderator gelöscht.
Beitrag #6642810 wurde von einem Moderator gelöscht.
Hi Leute, hat jemand alle vier oder mindestens zwei UART's des ATM2560 mit RX und TX Interrupt gleichzeitig am Laufen? Bei mir funktionieren die UART's einzeln. Wenn man Auf der UART COM3 schreibt/liest und danach auf COM2 und dann... COM1 und dann Com0 geht alles super. Wenn man dann aber wieder auf eine höhere COMx wechselt, dann werden die RX bzw. TX-Interrupts nicht mehr ausgelöst. Wenn man direkt auf UDRx schreibt/ließt, sind die Zeichen da. Also irgendwas macht bei der Priorisierung der Interrupts Probleme. Coding schließe ich aus, weil AVRStudio 6 und 7 gleiche Resultate erzeugen. Auf ATM128 gabs mit dem Source nie Probleme. Im Quellcode kann man mit $OK oder mit $X mit abschließenden CR eine Antwort von der jeweiligen UART erhalten. siehe KommandoX.c THX
Norman P. schrieb: > Also irgendwas macht bei der > Priorisierung der Interrupts Probleme. Kannst du mal erläutern warum du den Watchdog bemühst und zu jeder beliebigen Tag- und Nachtzeit ihn wieder resetten musst. Das "nervt" ungemein und verbrät auch Rechenzeit, zumal du da jedes mal eine Funktion dafür aufrufst - mit dem entsprechenden Overhead .... Dann sehe ich es nicht ein Zeichen(ketten) im Interrupt- Kontext zu senden. Denn beim Senden kann der Controller gerade nicht auf Receive-Interrupts reagieren (sondern erst danach) und es fällt für jedes Zeichen ein Interrupt- Overhead (ISR: Register retten und wiederherstellen) an, das läppert sich .... Ich habe Zeichen schon immer ohne IRQ gesendet und war immer glücklich damit. Habe mich nicht weiter bemüht den ganzen Code zu verstehen, dazu war ich aufgrund der bisherigen "Macken" nicht motiviert. Aber im allgemeinen empfiehlt es sich das Problem auf ein Minimal-Programm zu reduzieren damit es auch jeder gleich versteht.
Hi, der Watchdog überwacht nur den korrekten Lauf des Programms. Wenn ich eine Schleife habe, aus der der Kontroller nicht wieder herauskommt, erfolgt nach dem Watchdog-Zeitintervall ein Reset des Kontrollers. Somit muß im Programmablauf immer der Watchdog-Timer mit seiner Reset-Funktion aufgerufen werden. Gut, man kann auch Inline-Code dafür aufrufen, anstatt ein (CALL, WDT-Reset, Return). Es gibt immer elegantere Lösungen. Wenn ich das Senden per Einzelschreibbefehle mit Warten auf Puffer-Leer durchführe, dann packe ich halt in der MAIN die While-Schleife mit dem Sendealgorithmus zu. Das ist aber nicht Sinn der Übung. Die Kommunikation soll quasi nebenher im Interrupt-Modus erfolgen und in der Main-Schleife will ich dann auf Nachrichten reagieren und Berechnungen etc. durchführen. Wegen der Rechenzeit mache ich mir keine Sorgen. Bei 9k6 Baudrate und dem gelegentlichen Eintreffen von ein paar kurzen Nachrichten, schlafen die ISR die meiste Zeit. Notfalls kann man den Ringpuffer vergrößern oder noch eine Stringliste mit den Nachrichten einfügen. Das ist aber nicht das Problem! Der gepostete Source hat bei mir auf ATM 128 mit 2 UARTs funktioniert, nur eben jetzt auf dem ARD-MEGA250PRO Board mit ATM 2560 geht es nicht mehr. Man kann auch die Anzahl der unterstützten UARTs auf zwei reduzieren. Das Problem, wenn mit UART0 gesendet wurde, dann empfängt UART1 oder 2 oder 3 nichts mehr und das Senden über diese UARTs ist ebenfalls über die ISR blockiert. Das direkte Füllen von UDR1 oder UDR2,3 geht und wird auch gesendet. Nur eben nicht per ISR. Ich sehe momentan keine Grund, warum nicht alle UARTs per ISR senden und empfangen können sollten!!! THX
Norman P. schrieb: > Wenn ich > eine Schleife habe, aus der der Kontroller nicht wieder herauskommt ... dann hast du grob falsch programmiert. Endlos-Schleifen überwacht man mit Status und sinnvollen Abbruch-Kriterien damit man wieder herauskommt. Entweder ich bekomme ein Zeichen oder nicht, beide Ereignisse kann ich gezielt behandeln und muss nicht "aus Verzweiflung" einen Reset auslösen. Ist dir bewusst dass ein Watchdog-Reset dein Programm ganz von vorne anfangen lässt und deine zeitaufwendige Neuinitialisierung durchläuft? Kopfschüttel! Die Magic Numbers die überall im Programm verststreut sind macht hier niemanden Freude. Sie erfordern nämlich jedesmal einen Blick ins Datenblatt ob das eine oder andere Bit richtig gesetzt ist. Hier nur ein Auszug als Beispiel:
1 | while((UCSR0A & 0x40) == 0x40) //TXC == 1 ? |
2 | {
|
3 | watchdog_reset(); |
4 | }
|
5 | UDR0 = 0x0D; //sende CR, damit TXC flag setzen |
6 | SREG |= 0x80; //global INT an |
Warum wohl hat Atmel sinnvolle Namen für die Register-Bits vergeben? Für meine Begriffe musst du deine Programmierung überdenken und (fast) ganz von vorne anfangen. Ich kann dir den Fehler auch nicht direkt nennen (ich habe keine Lust mich mit derart vielen WD-Reset-Bedingungen herumzuschlagen) aber mit dieser Programierung scheint mir das zu fehleranfällig zu sein. Nebenschauplatz: in den Sources sind wild Tabs und Spaces gemischt sodass beim Zitiern von Codeschnipseln hier im Forum ein wildes "Getabbe" entsteht. Im allgemeinen werden Tabs als eine grosse Menge an Spaces interpretiert sodass es oft eine Qual wird die Kommentare im Sourcecode zu lesen.
jo mei schrieb: > Ist dir bewusst dass ein Watchdog-Reset dein Programm ganz von > vorne anfangen lässt Ich meinte natürlich einen Reset den der Watchdog auslöst.
OK, über den Sinn des Watchdog-Reset kann man streiten. Das tut aber nichts zum eigentlichen Problem. Im "Normalzustand" sollte der Watchdog niemals auslösen. Wenn man aber Medizinprodukte herstellt, sind ein externer Hardware- und ein interner Software-Watchdog notwendig!!! Weiterhin sind die Atmelstudio Includes äußerst kontraproduktiv, wenn es um Softwarevalidierung geht. Aber egal ... - ein Programm sollte das Tun, was von ihm erwartet wird. @Tabs: Ich benutze nur Privat das Atmelstudio und da schreibe ich den Source kein Zweites Mal. Ansonsten hat jeder seinen eigenen Programmierstil und in Unternehmen soll dieser dann vereinheitlicht werden. -> Einrückung, Klammern etc. Nun zum Problem: Der ATM 128 mit 2 Uarts kann nur mit UART0 asynchrone Übertragung (lt. Datenblatt). Die UART1 geht dann nur als synchrone UART. Bei ATXMega gehen alle UARTs asynchron, wie man dies erwarten würde. Im Datenblatt des ATM2560 steht dazu nichts, daß nur UART0 asynchron betrieben werden kann und die restlichen UARTs nur im synchronen Betrieb. Offensichtlich ist dieses Feature hier auch zugegen, was die Nutzung der UARTs einschränkt. BITTE weitere POSTs nur zum PROBLEM!
Norman P. schrieb: > hat jemand alle vier oder mindestens zwei UART's des ATM2560 mit RX und > TX Interrupt gleichzeitig am Laufen? Ja! Mein Arduino kann das.... Es ist also nicht unmöglich. Jetzt wollte ich dein Programm testen, aber das scheitert schon an der unsäglichen Groß-Kleinschreibung der Dateinamen. Also: Ich gebe auf.
Hi >Nun zum Problem: Der ATM 128 mit 2 Uarts kann nur mit UART0 asynchrone >Übertragung (lt. Datenblatt). Die UART1 geht dann nur als synchrone >UART. Wie kommst du auf dieses schmale Brett? Wenn mit ATM 128 der ATMega128 gemeint ist besitzt dieser zwei identische USARTs. Beide können sowohl asynchron als auch synchron betrieben werden. Genau wie im Datenblatt beschrieben. >Im Datenblatt des ATM2560 steht dazu nichts, daß nur UART0 asynchron >betrieben werden kann und die restlichen UARTs nur im synchronen >Betrieb. Offensichtlich ist dieses Feature hier auch zugegen, was die >Nutzung der UARTs einschränkt. Meinst du weshalb beim Ardudingsda Mega 2560 alle XCKn-Anschlüsse (die für synchronen Betrieb notwendig sind) unbelegt sind. So doof sind noch nicht mal die Arduidioten. Kann es sein, daß du die Datenblätter etwas falsch verstehst MfG Spess
@AdurinoFanboy: Danke, da muß ich wohl den Ardurino Code mal inspizieren. @Spess53: Es geht hier nicht um zu blöd, sondern daß es mir bei dem ARD ATM2560 Board einfach nicht gelungen ist, alle oder mind. 2 UARTS unabh. voneinander zu betreiben. Ich nutze den RX und den UDRE Interrupt. Vielleicht muß ich den TX-Interrupt nutzen und/oder dann in der ISR das entsprechende Interrupt-Flag zurücksetzen. Das was ich zum ATM128 geschrieben habe, bezieht sich auf den Kompatibilitätsmode und steht auch so im Datenblatt. (Wenn das Fusebit M103 gesetzt ist.) Wenn es nicht gesetzt ist und der ATM im ATM128 Mode ist, sollten die beiden UARTS gleichwertig sein. Ich suche jedenfalls nach einer Lösung für mein Problem. Dabei geht es nicht darum, ob jemand sich zu prasselig anstellt. Ich habe jedenfalls schon erlebt, das Chips nicht funktionierten und die Firma Microchip still und heimlich einen neuen Chip mit Upgrade unters Volk geschmissen hat. (siehe CAN-Controller mit I2C-Interface) Daher frage ich halt gern mal im Forum, ob ich weiter Zeit für die Suche / Lösung meines Problems investieren sollte. Falls jemand Ardurino Programmumgebung nutzt und mal den Source für die UARTs anschaut; wäre für mich hilfreich; ob und mit welchen Interrupts die die UARTs programmiert haben. Ansonsten suche ich mir das morgen selbst raus. PS: Das Problem sitzt meist 30-60cm vorm Bildschirm ;-) (Ironie in eigener Sache)
Man, man ... Selber kucken, macht selber schlau! Google Tipp: "Arduino Avr core github "
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.