Forum: Mikrocontroller und Digitale Elektronik ATmega8 UART


von blan (Gast)


Angehängte Dateien:

Lesenswert?

hi, ich habe mein ATmega8 mit einem MAX232 CPE verbunden um mir eine
Schnittstelle zum PC zu bauen. Was allerdings komisch ist, dass sobald
ich den PC mit dem Board verbinde mein ATmega8 Timer stehnbleibt und
solange nicht weitermacht bis ich die verbindung wieder trenne. Ich
denke dass die die leitungen richtig angeschlossen habe da ich zwischen
GND - Pin2 -8.5V, GND - Pin3 0.0V haben und die Voltzahl sich verändert
wenn der Timer jede ~6sec ein zeichen sendet. jemand eine erklärung
dafür?

mfg blan

von A.K. (Gast)


Lesenswert?

Sieht schwer danach aus, als ob doch etwas falsch
angeschlossen/verbunden ist.

von blan (Gast)


Angehängte Dateien:

Lesenswert?

update

jo das kabel hat nicht so recht getan. habs nun direkt an PC
angeschlossen und der timer läuft ganz normal bloß kommen keine daten
an. weder übers Windows Terminal, mein kleines C-Programm noch "cat
/dev/ttyS0". woran könnte das liegen? stimmt denn mein ATmega8 UART
Code den ich oben gepostet habe? hab noch mein C-Programm angehängt.

mfg blan

von blan (Gast)


Lesenswert?

update

also scheint so alsob ich was gesendet bekomm, jedenfalls hat man nur
was im hex-view gesehn und das war ne ganze menge "00", also mehr als
12 oder so. wie kommen die zusammen bei nur einem 'c' das gesendet
wird?

mfg blan

von Martin #. (martin-)


Lesenswert?

Also mich wundert das dein MCU-Programm überhaupt läuft weil in main
eine Endlosschleife fehlt. So weit ich weiss ohne solche Schleife wird
das Programm dauern beendet und neu durchlaufen.

Die funktionen uart_init und uart_putc scheinen in Ordnung zu sein(für
atmega8).
Ich habe sie mit Funktionen verglichen die ich benutze.

von blan (Gast)


Lesenswert?

hrm bis jetzt hab ich alle programme so gemacht unds hat immer
funktioniert, naja werds mal reinmachen. beim kompilieren bekomm ich
diesen fehler:

main.c: In function `uart_init':
main.c:28: warning: integer overflow in expression

kanns vll daran irgendwie liegen. die "00" kommen mir irgendwie
komisch vor :(

mfg blan

von uwegw (Gast)


Lesenswert?

>>>das war ne ganze menge "00", also mehr als
12 oder so. wie kommen die zusammen bei nur einem 'c' das gesendet
wird?

riecht nach nicht passender Baudrate, weil interner Takt statt Quarz
aktiv... probier mal 600 Baud im Terminal aus, dann müsste es klappen
wenn der AVR noch auf 1MHz läuft.

von Martin #. (martin-)


Lesenswert?

>>main.c:28: warning: integer overflow in expression
Ja stimmt das habe ich übersehen. das muss beim compilieren berechnet
werden weil es nich ich 16bit passt. Also mach das lieber so:
ubrr-Variable komplett weg, also das verschwindet:
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUD_RATE) - 1);

Makro definieren:
#define UART_BAUD_CALC(UART_BAUD,F_OSC) ((F_CPU)/((UART_BAUD)*16L)-1)

Und dann anstatt:
    UBRRH = (uint8_t) (ubrr>>8);
    UBRRL = (uint8_t) (ubrr);
Das rein machen:
    UBRRH=(unsigned char)(UART_BAUD_CALC(UART_BAUD,F_CPU)>>8);
    UBRRL=(unsigned char)UART_BAUD_CALC(UART_BAUD,F_CPU);

von johnny.m (Gast)


Lesenswert?

@Martin:
Alle mir bekannten Compiler fügen am Ende von main automatisch eine
(leere) Endlosschleife ein.

von blan (Gast)


Angehängte Dateien:

Lesenswert?

sehr geil danke, es funktioniert fast perfekt. ich bekomm immer so wies
sein sollte 'c' gesendet. jedoch manchmal aufeinmal 20 'c'
aufeinmal. wie ist das mit 1mhz gemeint, der ATmega8 hat doch 16Mhz so
wie ichs oben definiert habe? und ich hab jetzt im programm BAUD = 9600
und im terminal = 600, da kann dann ja auch net alles passen?

mfg blan

von Thorsten F. (thorsten)


Lesenswert?

was du im programm für eine taktfrequenz definierst, interessiert den
controller herzlich wenig.

der richtet sich nach seinem internen takt oder ggf. nach dem von einem
quarz oder von sonsteiner taktquelle.

einzustellen über die fusebits -> datenblatt.

gruß

von Martin #. (martin-)


Lesenswert?

>>jedoch manchmal aufeinmal 20 'c'
Also höstwahrscheinlich liegt das an dem PC-Programm mit dem du es
empfengst. Ich habe hier dein Progamm in ein Atmega8 einprogrammiert
und es scheint alles in ordnung zu sein. Diode Blinkt und synchron dazu
wird ein c gesendet.

>>16Mhz
Ich benutze hier etwas andren uart-gerechten Quarz 14.7456MHz
Schau im Datenblatt nach wie gut sich 16MHz und 9600Baud vertragen.

von blan (Gast)


Lesenswert?

>> was du im programm für eine taktfrequenz definierst, interessiert
den
controller herzlich wenig.

der richtet sich nach seinem internen takt oder ggf. nach dem von
einem
quarz oder von sonsteiner taktquelle.

einzustellen über die fusebits -> datenblatt.

gruß

natürlich, is mir klar aber der ATmega8 hat doch ne taktfrequenz von
16Mhz, so stands jedenfalls mal auf nem Datenblatt. die frage ist halt
nur was ich machen kann ohne mir ein externen quarz zu holen und ein
sauberes signal bekomme?

mfg blan

von Thorsten F. (thorsten)


Lesenswert?

nur weil im datenblatt steht, dass der controller bis 16mhz laufen KANN,
heisst das nicht, dass er es im auslieferungszustand auch tut.

falls du an den fuses bis jetzt nichts verstellt und keine externe
taktqualle dranhast läuft das teil mit internen 1mhz.

gruß

von blan (Gast)


Lesenswert?

okay, da das teil dann wohl mit 1mhz läuft hab ich mein F_CPU angepasst
und im datenblatt geschaut was ich so bei 1mhz benutzten kann, jedoch
kommen zwischendurch (mal mehr mal weniger oft) mehrere 'a' an und
manchmal sogar ein 'c' was überhaupt net gesendet wurde o.O muss man
sowas akzeptieren oder habt ihr solche probleme nicht?

mfg blan

von thkais (Gast)


Lesenswert?

Nuja, so ein Controller macht sowieso, was er will. Da kanns dann
schonmal passieren, dass der UART ausser Kontrolle gerät und wild
herumsendet.

Quatsch mit Soße ;)

Natürlich ist das nicht normal. Du hast mit Sicherheit einen Bug in
Deinem Programm.
Ich habe nur kurz drübergeschaut, was hast Du an Deinem ext. Int
angeschlossen? Einen Taster? Dann suche mal im Forum nach "Taster
entprellen).

von Hannes L. (hannes)


Lesenswert?

Der interne RC-Oszillator ist für UART-Übertragung zu ungenau. Du
solltest einen Baudratenquarz verwenden, z.B. 3,6864MHz oder ein
ganzzahliges Vielfaches davon.

Der Mega8 wird mit aktiviertem internen Oszillator ausgeliefert, der
auf 1MHz eingestellt ist. Will man eine andere Taktquelle und/oder eine
andere Taktfrequenz, dann muss man das dem Mega8 auch über die Fusebits
mitteilen. Das sollte man aber erst tun, wenn man sich sachkundig
gemacht hat (Datenblatt, diverse Threads hier im Forum), denn wenn man
ohne exaktes Wissen drauflos probiert, dann hat man sich schnell
ausgesperrt. Übrigens hat das mir vorliegende Datenblatt zum Mega8 303
Seiten. Da steht alles Wichtige drin. Es genügt aber nicht, nur die
erste Seite mit der Feature-Auflistung zu lesen.

...

von blan (Gast)


Lesenswert?

hrm an dem ext. interrupt ist normal nichts dran, werd ihn aber trotzdem
mal ausmachen. also kann ich daraus schließen dass ich ohne einen
externen quarz bzw. mit meinen 1mhz nichts mit dem UART anfangen kann?

mfg blan

von johnny.m (Gast)


Lesenswert?

> also kann ich daraus schließen dass ich ohne einen
> externen quarz bzw. mit meinen 1mhz nichts mit dem
> UART anfangen kann?

Im Prinzip ja. Der interne RC-Oszillator hat je nach Einstellung
Abweichungen im Prozent-Bereich. Dazu kommt noch eine starke
Temperaturdrift (Im Datenblatt unter Electrical Characteristics sind
irgendwo die Kennlinien). Da man für eine asynchrone serielle
Übertragung einen ziemlich genauen Takt braucht (als Toleranz werden
meist 2% angegeben, weniger ist aber sinnvoll), ist das mit dem
internen RC-Oszillator eher Glückssache, wenn die Übertragung mal
klappt... Und wenns im Sommer klappt, dann im Winter wahrscheinlich
nicht

von thkais (Gast)


Lesenswert?

Man kann den internen Oszillator kalibrieren, d.h. in diesem Fall etwas
verstimmen, um näher an die richtige Baudrate heranzukommen. Aber das
ist nicht sehr temperaturstabil. Oder die Baudrate auf 2400 Baud
runterschrauben, dann klappt es recht gut, auch wenn die Abweichungen
recht groß sind.
Wenn Du am externen Int nichts dran hast, dann fängt der Pin Störungen
auf und löst den Interrupt aus. Mindestens den internen Pull-Up
einschalten oder einen externen Pull-Up anschließen.

von johnny.m (Gast)


Lesenswert?

> Oder die Baudrate auf 2400 Baud runterschrauben

Auch bei niedrigeren Baudraten gelten die genannten (prozentualen!)
Toleranzen. Wenn es mit 9600 Baud nicht läuft, dann gehts mit 2400 auch
nicht besser! Es ist der selbe Oszillator, und wenn Du das
Oszillator-Signal runterdividierst wirds auch nicht genauer...

von Hannes L. (hannes)


Lesenswert?

Es ist schon ein kleiner Unterschied, ob man durch Reduzieren der
Baudrate (bei Benutzung eines Quarzes, der für UART nicht optimal ist)
einen ganzzahligen Teiler erreicht (und damit die Abweichung
minimiert), oder ob man damit versucht, die durch einem recht
instabilen RC-Oszillator schlechte und unzuverlässige Übertragung zu
verbessern.

Im ersten Fall hat man schon eine Chance, im zweiten Fall nicht. Denn
die prozentuale Abweichung bleibt bei jeder Baudrate erhalten.

Wenn es aber zuverlässig sein soll, sollte man schon einen
baudratentauglichen Quarz benutzen.

...

von johnny.m (Gast)


Lesenswert?

@Hannes:
Stimmt natürlich. Ich war jetzt von der Voraussetzung ausgegangen, dass
beide genannten Baudraten mit der gegebenen Taktfrequenz mit gleicher
Genauigkeit einstellbar sind...

von blan (Gast)


Lesenswert?

okay ist natürlich jetzt bischen schade das zu hören :(
kann mir jemand sagen wo es die Quarze gibt. Hab bei reichelt geschaut
aber weiss net ob ich jetzt ein "Quarz" oder ein "Quarzoszillator"
brauch und wieviel Mhz optimal für sone schaltung sind (sollte ich dann
gleich ambesten irgendwas mit 16,xxxx Mhz nehmen?)

mfg blan

von Hannes L. (hannes)


Lesenswert?

Ich habe mich mal bei CSD mit baudratentauglichen Quarzen eingedeckt. Da
gibt es "die ganze Staffel" zu fairen Preisen. Es kann aber sein, dass
man dort momentan etwas warten muss, denn da ist zur Zeit der Bär los
weil sich die fairen Preise herumgesprochen haben.

Ich persönlich bevorzuge beim AVR Quarze (also keine
Quarzoszillatoren), denn der AVR hat den Oszillator bereits eingebaut.
Du solltest bei der Gelegenheit auch an die 22pF-Kondensatoren für die
Quarze denken, siehe auch Datenblatt Seite 25.
Ein paar Kerkos 100nF (z.B. in SMD 0805) solltest du auch gleich
mitbestellen, die werden nämlich vom Anfänger gern vergessen.

Quarzoszillatoren (als komplettes Bauteil) haben einen höheren
Stromverbrauch, erzeugen mehr Störungen und sind meist teurer. Mir
fällt gerade kein Grund ein, sie für AVRs zu verwenden.

> ambesten irgendwas mit 16,xxxx Mhz nehmen?

Gibt es einen Grund, ständig am Limit (oder dahinter) zu arbeiten?

Man muss doch den Controller nicht immer mit maximaler Taktrate fahren.
Meist reicht 3,6864MHz oder 7,3728MHz völlig aus. Beachte, dass höhere
Taktfrequenzen auch höhere Ansprüche an das Platinendesign stellen.

Eine Liste einiger baudratentauglicher Frequenzen findest du hier:
http://www.hanneslux.de/avr/tipps/baudratenquarz.html
oder im Datenblatt des Mega8 Seite 156 bis 159.

...

von blan (Gast)


Lesenswert?

ok danke. ne muss net sein dass man immer am limit arbeitet aber habs
grad so mit meim cpu im pc verglichen da kauf ich mir meist auf net des
langsamste :D

achso: seitdem ich den interrupt, der (was ich garnet wusste) ein 'c'
sendet wenn er aktiviert wird, auskommentiert habe funktioniert der UART
soweit ich des seh perfekt. im datenblatt steht auch dass er bei 2400
BAUD nur 0,2% fehler hat (bei 1.000000mhz)

also aufjedenfall nochmals vielen dank, bei ner neuen schlatung werd
ich dann quarze verwenden. darf ich bei dem quarz auch 100nF kerkos
verwenden (hab grad soviele da ^^)

mfg blan

von Hannes L. (hannes)


Lesenswert?

> darf ich bei dem quarz auch 100nF kerkos
> verwenden (hab grad soviele da ^^)

Aber sicher darfst du das. Ist ja dann dein Quarz und dein MC.

Aber schwingen wird der Quarz damit vermutlich nicht. Denn 100nF ist
etwa das Fünftausendfache des empfohlenen Wertes. Das empfindet Quarz
und Oszillator vermutlich als Kurzschluss.

...

von blan (Gast)


Lesenswert?

kleine frage hab ich noch. momentan realisier ich die abfrage von dem
UART mit einem Timer, was aber sicher nicht sehr elegant ist. bloß
bleibt mein programm immer bei folgendem stehen:

INTERRUPT(SIG_UART_RECV)
{
  uint8t_t dummy = uart_getc_wait();
  switch_port(0, 1);
}

wieso?

mfg blan

von johnny.m (Gast)


Lesenswert?

Lass um *Gottes* Willen die Finger von INTERRUPT! Da ist SIGNAL ja
noch besser! Allerdings sind beide veraltet! Bitte benutze ISR und
dann den richtigen Vektornamen! Sorry für die vielen Ausrufezeichen,
aber wenn ich so was sehe, dann....!!!!!

von Karl heinz B. (kbucheg)


Lesenswert?

>   uint8t_t dummy = uart_getc_wait();

des weiteren muss das hier keine ...wait() Funktion
sein (was auch immer die macht. Aber das ...wait() varanlasst
mich zur Vermutung, dass die auf irgendetwas warten wird).

Du bist im Interrupt. Du weist, dass ein Zeichen empfangen
wurde, sonst wärst du nicht im Interrupt.
Du kannst das Zeichen aus dem UDR Register holen, denn es steht
bereits vollständig drinnen.

von johnny.m (Gast)


Lesenswert?

Ich vermute mal, dass es genau diese wait-Funktion ist, die dafür sorgt,
dass 'das Programm stehenbleibt' (worauf auch immer diese Funktion
wartet...). Möglicherweise ein klassischer Stack Overflow...

Vielleicht noch mal zur Erklärung: eine mit INTERRUPT eingeleitete ISR
ist (im Unterschied zu SIGNAL und ISR) unterbrechbar. Je nachdem, was
Du in der ISR machst, kann es passieren, dass sich die ISR selber
unterbricht, wenn Interrupts schneller kommen, als sie bearbeitet
werden. Und genau das führt zwangsläufig zu einem Stack Overflow und
damit zum Systemabsturz. Verschachtelte Interrupts sollte man nur dann
verwenden, wenn man sich ganz sicher ist, dass man weiß, was man tut!

von Karl heinz B. (kbucheg)


Lesenswert?

Eine andere Möglichkeit wäre, dass diese ...wait()
Funktion genau auf das Auftreten des Interrupt Flags
wartet. Dieses ist aber bereits gelöscht worden, da
ja die Interrupt Funktion aufgerufen wurde.

von blan (Gast)


Lesenswert?

wo bekomm ich denn die vectornamen her, überall steht was anderes. im
datenblatt steht nicht viel drin und hier steht alles aber funktionert
wohl nicht
(http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#gae8ea90ab1d3064dfeb128c126d4709d)

ISR(TIMER0_OVF_vect)
{
  switch_port(0, 1);
  switch_port(1, 1);
  switch_port(2, 1);
}

muss doch funktionieren.

mfg blan

von Karl heinz B. (kbucheg)


Lesenswert?

Die Dinger heissen normalerweise gleich wie
im Datenblatt von AVR, nur mit einem angehängten _vect

TIMER0_OVF_vect

ist daher richtig.
Im Zweifelsfall kann man immer noch in das Prozessor-
spezifische io.h schauen. Bei einem AMega16 heist diese
Datei zb. iom16.h

> muss doch funktionieren.

Rein von dem was ich hier sehen kann: Klar, sollte tadellos
funktionieren. Die ISR sollte aufgerufen werden. Falls
Timer und Interrupts richtig initialisiert werden.

von blan (Gast)


Lesenswert?

ja genau auf die idee bin ich auch gekommen nur steht dort folgendes:

/* Interrupt vectors */

#define SIG_INTERRUPT0    _VECTOR(1)
#define SIG_INTERRUPT1    _VECTOR(2)
#define SIG_OUTPUT_COMPARE2  _VECTOR(3)
#define SIG_OVERFLOW2    _VECTOR(4)
#define SIG_INPUT_CAPTURE1  _VECTOR(5)
#define SIG_OUTPUT_COMPARE1A  _VECTOR(6)
#define SIG_OUTPUT_COMPARE1B  _VECTOR(7)
#define SIG_OVERFLOW1    _VECTOR(8)
#define SIG_OVERFLOW0    _VECTOR(9)
#define SIG_SPI      _VECTOR(10)
#define SIG_UART_RECV    _VECTOR(11)
#define SIG_UART_DATA    _VECTOR(12)
#define SIG_UART_TRANS    _VECTOR(13)
#define SIG_ADC      _VECTOR(14)
#define SIG_EEPROM_READY  _VECTOR(15)
#define SIG_COMPARATOR    _VECTOR(16)
#define SIG_2WIRE_SERIAL  _VECTOR(17)
#define SIG_SPM_READY    _VECTOR(18)

was bischen komisch ist oder?

timer sollte richtig initialisiert sein, mit INTERUPT() hats auch
geklappt:

int main(void)
{
  TIMSK |= (1 << TOIE0);
  TCNT0  = 0x0;
  TCCR0 |= (1 << CS02);

  uart_init();

  sei();

  return 0;
}

mfg blan

von Karl heinz B. (kbucheg)


Lesenswert?

> nur steht dort folgendes:

Geh mal schnell zu http://winavr.sourceforge.net/
und hol dir eine neuere Version.

von blan (Gast)


Lesenswert?

jo hab wohl echt ne veraltete version. nur gibts für meine distribution
nur diese version. muss ich mal schaun wie ich das hinbekomme :(

mfg blan

von Simon K. (simon) Benutzerseite


Lesenswert?

Was für ne Distribution?!

von blan (Gast)


Lesenswert?

ubuntu dapper

von blan (Gast)


Lesenswert?

also ich hab mir jetzt die neuste version neu compiliert und tatsächlich
- es funktioniert :D

ich empfehl jemdem die neuste version ;)

danke nochmals!

mfg blan

von johnny.m (Gast)


Lesenswert?

@Karl Heinz:

> ...genau auf das Auftreten des Interrupt Flags
> wartet. Dieses ist aber bereits gelöscht worden, da
> ja die Interrupt Funktion aufgerufen wurde.

If memory serves: War da nicht was, dass das RXC-Flag, im Unterschied
zu den meisten anderen Interrupt-Flags, erst dann gelöscht wird, wenn
UDR gelesen wird, und nicht beim Einsprung in die ISR?

von Karl heinz B. (kbucheg)


Lesenswert?

Ja da war was.
Ich denke du hast recht.
Aber ohne Kenntnis des Aufbaus der Funktion ist das
alles sowieso stochern im Nebel :-)

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
Noch kein Account? Hier anmelden.