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
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
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
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.
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.
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.
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
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)