Forum: Compiler & IDEs UART will nicht (Atmega88)


von Thomas L. (tom)


Lesenswert?

Hallo zusammen :) Nachdem ich mit heute schonmal mit dem define blamiert
habe, versuche ich es jetzt gleich noch mal aufs Neue :)

Ich nutze einen UART(0) von einem Atmega88. Kommunizieren soll er mit
einem USB/Serial Wandler von FTDI. Der FTDI wird korrekt erkannt - hier
dürfte es also keine Probleme geben. Es handelt sich dabei um ein
fertiges Modul von www.elk-tronic.de. Angeschlossen sind einzig und
allein TXD und RXD. Sonst nichts - das Ding sollte sich den Saft ja vom
USB holen.

Ich habe jeweils RXD an TXD angeschlossen. Dieser Code soll den UART
initialisieren:

---snip---
  // USART
  // 8N1, Parity: None, 9600 Baud
  UBRR0H = 0x00;
  UBRR0L = F_CPU / (UART_BAUD_RATE * 16L) - 1;

  UCSR0B |= (1 << TXEN0);
  UCSR0C |= ((1 << UCSZ00) | (UCSZ01));
---snip---

F_CPU ist 8 MHz (habe ich auch im AVR Studio überprüft)
UART_BAUD_RATE ist 9600

Meine Endlosschleife habe ich etwas modifiziert:
---snip---
  while(1) {
    writeChar('A');
  }
---snip---

Die dazugehörige Methode ist:

---snip---
void writeChar(char c)
{
    while (!(UCSR0A & (1<<UDRE0)));
    UDR0 = c;
}
---snip---


Wenn ich mir das am Oszi anschaue, dann sehe ich auch etwas - deuten
kann ich es zwar nicht, aber es sieht mir wie ein digitales Signal aus.


Daher jetzt meine Frage - woran könnte es liegen, dass ich am PC nichts
sehe ?

von Thomas L. (tom)


Lesenswert?

Never mind - alles funktioniert auf einmal, wenn man das Ding am
richtigen Pin anschliesst :)

Danke :)

von Thomas L. (tom)


Lesenswert?

Sooo .. Kommando retour ...

es kommt zwar was an .. scheint mir aber nur Blödsinn zu sein grmml.
Findet vielleicht jemand oben einen Fehler ?

Anstatt Buchstaben bekomme ich nur ein € \0 €  .. also drei Zeichen.
dabei ist es egal, was ich sende ... seufz

von Thomas L. (tom)


Lesenswert?

ok .. bin knapp davor ... wenn ich im terminal programm auf 1200 Baud
stelle, passts ...

aber wo ist der Hund? Die Berechnung habe ich aus dem Atmel Datasheet -
stimmen tuts um einen Faktor 8 nicht ... würde eigentlich auf eine
falsch eingestellte F_CPU deuten .. aber die Fuses sagen 8MHz ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> aber die Fuses sagen 8MHz ...

Sicher?  1 MHz ist doch der Default...

von Thomas L. (tom)


Lesenswert?

beim atmega8 ist standard 1 MHz ...

ich verwende den Atmega88 - den kann man bei den Fuses nichtmal auf
1MHz stellen (da gibts nur 8MHz oder externer Quarz) ...

von Frank Schuessler - fs0001 (Gast)


Lesenswert?

Hi,

versuchs mal ganz quick an dirty ob's an Deiner Kalkulation der
Baudrate liegt,
lass das mal weg:

 UBRR0H = 0x00;
 UBRR0L = F_CPU / (UART_BAUD_RATE * 16L) - 1;

und ersetze es durch:
 UBRR = 51;

schau ob dann die Kommunikation mit 9600 Baud bei 8 Mhz geht; wenn ja
ist noch irgendwas an der Definition Deiner Konstanten bzw.
Baudrateneinstellung falsch.

Mehr dazu im Atmega88 Datenblatt ( ATmega48/88/168 Preliminary Complete
   (361 pages, revision F, updated 06/05) auf Seite 194.

Gruss


Frank

von Thomas L. (tom)


Lesenswert?

Hallo :)

Hab ich auch schon versucht ...

Leider selbiges Ergebnis .. Zeichen kommen laut hterm mit 1200Baud an.
Als Register habe ich UBRR0 verwendet - das stimmt schon, oder? (weil
du UBRR schreibst).

Im Datasheet habe ich eben gelesen: "The Transmitter divides the baud
rate generator clock output by 2,8 or 16 dependinung on mode." ...
(Seite 170).

Kanns damit zusammenhängen?

von JürgenR (Gast)


Lesenswert?

Datenblatt Seite 25 :

Default Clock Source:    The device is shipped with
internal RC oscillator at 8.0MHz and with the fuse CKDIV8
programmed, resulting in 1.0MHz system clock.

Wird also bei Standard-"fuses" mit 1MHz laufen.

von Thomas L. (tom)


Lesenswert?

Ahhhhhhhhhhhh ... DAS hab ich übersehen ...

Herzlichen Dank - das war des Rätsels Lösung ... Da hätte ich noch ewig
gesucht ... habe bei den Fuses nur gelesen: 8MHz .. und mir gedacht, das
passt ...

Danke

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nö, praktisch alle AVRs kommen mit 1 MHz daher (mittlerweile).
Der Grund ist einfach: die 8 MHz sind nicht für den kompletten
Betriebsspannungsbereich zulässig.

Die Einstellung über CKDIV8 hat Ursachen im internen Design.
Früher haben sie den RC-Oszillator variabel gebaut, dafür
brauchte der dann mehrere Kalibrierbytes usw.  Jetzt läuft der
auf einer festen Frequenz, die durch ein IO-Register dann
runtergeteilt werden kann.  Die CKDIV8-Fuse macht nun weiter
nichts, als den power-on default für den Taktteiler festzulegen.

von Thomas L. (tom)


Lesenswert?

Danke. Da werde ich wohl noch öfters drüber stolpern. Das werd ich mir
jetzt mal merken müssen. :)

von Thomas L. (tom)


Lesenswert?

Aaaaaalso ...

So .. das Empfangen eines Bits mittels Interrupt habe ich nun auch
geschafft, aber nun fehlts mir ein wenig an Logik.

Angenommen ich habe eine Befehlssequenz, bestehend aus mehreren Chars,
die ich dem Atmega zukommen lassen möchte.
Wie würde ich da am intelligentesten vorgehen. Was ich mir bereits
überlegt habe:
* fixes Datenformat (z.B. 5 Byte)
* Datenformat mit variabler Länge (Ringspeicher?)
* nach gewisser Inaktivität array löschen (timer benötigt).
* Delimiter verwenden.

Was würdet ihr als brauchbar erachten. Das fixe Datenformat wäre wohl
am einfachsten, was passiert jedoch, wenn mal ein Command nicht
ankommt, dann hängt das Ganze in irgendeinem unbrauchbaren Zustand.
Der Ringspeicher ist sicher praktisch, kann bis zu einer x-beliebigen
Länge genutzt werden - braucht jedoch Speicher .. und: welches Zeichen
soll ich als "Endzeichen" nehmen. Dazu kam dann eben die Idee, nach
einer gewissen Zeit das array zu löschen und somit zurückzusetzen. Da
bräuchte ich jedoch einen Timer dazu (Verschwendung).

Ich würde mich über Anregungen freuen :)

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.