Forum: Compiler & IDEs AT Mega8 USART defekt?!


von Markus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich hatte schon in
http://www.mikrocontroller.net/forum/read-1-93736.html gepostet und
bevor ich jetzt den ATMega8 auslöte, wollte ich Euch bitten mal über
den Sourcecode zu schauen. Ist zwar nicht sehr schön, aber sollte doch
eigentlich funktionieren, oder?
Ich hab' es mit und ohne Interruptroutinen ausprobiert und es werden
einfach keine Daten gesendet. Der Port ist ständig auf 5 Volt und
nichts passiert.

Vielen Dank für Eure Mühe.

Gruß Markus

P.S.: Der Schaltplan ist im anderen Posting, da es jetzt nur um das
Programm geht, es ist auch nur eine einfache Grundschaltung.

Es gibt zwar viele USART Fragen, aber ich habe noch keine C-Sourcen
gefunden, wenn hier doch welche existieren, tut's mir für das
überflüssige Posting leid.

von Jörg Wunsch (Gast)


Lesenswert?

UART-Beispiele sollte es schon geben...

Guck'mer mal.  Erste Frage:

> // USART Test - ATMega8 @ 16 MHz

Den RC-Oszillator hast Du auch abgeschaltet?

> void flash_init(void);

Kein glücklicher Namen übrigens -- `flash' wird bei Microcontrollern
heutzutage gern mit flash-ROM in Verbindung gebracht.


> SIGNAL(SIG_UART_RECV) {
>   cli();
...
>  sei();

cli()/sei() sind unsinnig.  Beim Eintritt in die Routine sind die
Interrupts sowieso gesperrt, beim RETI werden sie automatisch
freigegeben.

>  PORTD ^= _BV(PC2);

PC2 paßt nicht zu PORTD.  Dann nimm gleich eine 2 (statt PC2), sonst
ist das eher verwirrend.

> // Bei leerem Sendepuffer LED wechsel
> SIGNAL(SIG_UART_TRANS) {

Ich weiß, daß Du das nur für 'ne LED machst, trotzdem der Hinweis:
SIG_UART_TRANS ist selten sinnvoll, SIG_UART_DATA ist sinnvoller.  Das
kommt nämlich wirklich, wenn der Sende*puffer* leer ist, nicht erst,
wenn das Zeichen rausgeschoben worden ist.  Damit kannst Du
rechtzeitig das nächste Zeichen bereitstellen und diese ,,Rücken an
Rücken'' senden.

>  // Port D, Pin 6 auf Eingang schalten
>  DDRD |= _BV(PD6);

Der Kommentar beschreibt genau das Gegenteil von dem, was gemacht
wird.  Wenn ich mir angucke, wie oft Du auf irgendwelchen Bits von
Port D eine LED an- oder ausschalten willst, denke ich, daß Du das
auch im Kopf verdreht hast...  Die LEDs an Port D2 und D3 sind
jedenfalls nicht als Ausgang geschaltet.  Damit wirst Du deren
Blinkern schlecht sehen können, zusammen mit einer schrägen Datenrate
(bspw. durch völlig falschen Prozessortakt, s. o.) siehst Du auch
nichts beim Empfänger, das könnte Dich vermuten lassen, daß gar nichts
geht.  Hast Du denn mal einen Oszi an die TxD-Leitung gehalten?

>    // Auf Frame Error prüfen
>    if (UCSRA & _BV(FE) ) {

Das kann man vielleicht wirklich besser in der Interruptroutine gleich
machen.

>      PORTC &= ~_BV(PC1); // LED an
>      waste = UDR; // UDR leeren

Das ist unsinnig (sollte aber auch nicht schaden): die
Rx-Interruptroutine hat das Zeichen ja schon gelesen, egal ob's ein
framing error war oder nicht.

>  UBRRH = 0x00;

Mußt Du nicht setzen, 0 ist Voreinstellung.

>  // Double Transmission Speed einschalten
>  UCSRA |= _BV(U2X);

?

>  // 8N1 Modus
>  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);

Auch das ist voreingestellt.

Ansonsten sollte das aber schon gehen, ja.

von Markus (Gast)


Lesenswert?

Danke für die Hinweise. Es ist mein erster Atmel und manche Dinge waren
mir nicht klar (sei, cli). Die LEDs nehme ich zum "debuggen", weil
ich kein Oszilloskop habe. Für 5 Projekte im Jahr lohnt es sich nicht.

Die 16MHz liegen an, denke ich. Darauf habe ich die delay_ms Routine
kalibriert. Zugegebenermaßen hatte ich natürlich anfangs die
entsprechenden Fuses nicht gesetzt. Nun sieht's so aus:

Fuse Low Byte      = 0xff
Fuse High Byte     = 0xd9
Fuse Extended Byte = 0xff
Calibration Byte   = 0xa7  --  Read Only
Lock Bits          = 0xff
    BLB12 -> 1
    BLB11 -> 1
    BLB02 -> 1
    BLB01 -> 1
      LB2 -> 1
      LB1 -> 1

Sollte ok sein.

Gruß Markus

von Jörg Wunsch (Gast)


Lesenswert?

> ... weil ich kein Oszilloskop habe. Für 5 Projekte im Jahr lohnt es
> sich nicht.

Ach, ein Oszi lohnt immer.  Für bissel RS232-Analyse genügt ja das
billigste NF-Teil.  Gerade alte DDR-Oszilloskope bekommst Du gut
hinterhergeworfen (und wenn Du einen EO174 nimmst, den kannst Du sogar
mit 12 V und damit netzgetrennt betreiben).

Die Baudrate mag ich jetzt nicht nachrechnen, kannst Du selbst tun
(oder die Rechnung dem C-Präprozessor überlassen).

Bleibt immer noch, daß Du die DDRx-Register falsch herum gesetzt hast.

Deine Hardware habe ich mir nicht angeguckt, aber an die
RS232-Inverter (die Pegelwandler sind invertierend) hast Du gedacht,
ja?

von Markus (Gast)


Lesenswert?

Jup, daran habe ich gedacht und das ist auch das Problem. Ich hatte den
Kondensator an V+ vom MAX232 überbrückt, der ist dadurch ziemlich heiß
geworden - klar - und nun ist mein Problem, das ich nicht weiß, ob der
USART Block vom Atmel auch hin ist. Ich habe testeshalber die Ports
TxD, RxD als normale I/O Ports umprogrammiert und sie dann getestet,
das funktionierte auch.

Den Quellcode habe ich korrigiert. Die Baudrate ist aus dem Atmel
Datasheet. Daher auch der USART-Quellcode, nur das ich ihn ein wenig
abgewandelt habe und zur Sicherheit auch Default Werte nochmal in die
Register geschrieben habe, nachdem ich gesehen habe, was der AVR-GCC
aus der delay_ms Routine ohne den NOP Befehl alles weg optimiert hat.

Nun, da es mein erster Atmel ist und meine erste SMD Lötung und dann
auch nichts auf Anhieb klappt, wird man verzweifelt und macht jeden
unsinnigen Mist in der Hoffnung, dass es die Lösung ist.

von Markus (Gast)


Lesenswert?

Wie auch immer, hab' gerade festgestellt, dass wenn ich die Pins TxD
und RxD mit dem Finger berühre, der µC sich aufhängt. Das Teil ist wohl
im Eimer.
Werd' wohl alles neu machen :-(

Gruß Markus

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.