Forum: Compiler & IDEs UART funktioniert partout nicht


von Alexander S. (knut740)


Lesenswert?

Hallo,

nach Lektüre vieler Beiträge und Tutorial-Artikel dachte ich, daß ein 
funktiomierender Code entstanden ist, um Daten vom ATMEGA 16 zum 
PC-Terminal transferieren zu können - aber es geht einfach nicht!

Ob sich mal jemand mit unvoreingenommenem Blick meinen Code ansehen 
könnte?
1
#define BAUD   9600UL
2
#define UBRR_BAUD ((F_CPU) / (16UL*BAUD) - 1)
3
4
void USARTinit(void)
5
{
6
   UBRRH = (uint8_t) (UBRR_BAUD>>8);
7
   UBRRL = (uint8_t) (UBRR_BAUD & 0x0FF );
8
   UCSRB |= (1<<TXEN);            // USART TX einschalten zum Senden
9
   UCSRC |= (1<<URSEL) | (1<<UCSZ1) |(1<<UCSZ0) ;  // Asynchr 8N1
10
}  
11
12
und dann aus endloser Schleife in main der Aufruf:
13
14
       USARTinit();
15
       while (!(UCSRA & (1<<UDRE)))  // warten bis Senden möglich 
16
         {                           // while-Schleife ist hier unnötig!)
17
         }
18
       UDR = 'x';

Laufen soll das auf einem ATMEGA16, am anderen Ende der seriellen 
Leitung ist ein PC mit AVRTerm. Die Schnittstelle ist ok, lt. AVRTerm 
scheint es eine Verbindung zu geben, aber es kommt nichts an, kein "x" 
und auch keine Sonderzeichen.

Falls die Baudrate falsch eingestellt wäre, müßten ja wenigstens 
irgendwelcher Kram ankommen - aber es kommt nichts.

Den Code habe ich mir nicht selbst ausgedacht, es ist aus dem Manual, 
div. Forenbeiträgen usw. übernommen. Meine Hoffnung ist, daß irgend 
jemand vielleicht einen Schreibfehler findet (obwohl der Compiler von 
WinAVR nichts beanstandet).
Ansonsten bin ich ratlos.

Vielen Dank im Voraus
Alexander

PS: Der Atmega hat einen externen Quarz, aber die Aufschrift fehlt, 
(wahrscheinlich 8MHz), deshalb würde ich mich z.Zt. mit schrägen 
Sonderzeichen begnügen, wenn nur etwas ankäme.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1. Feststellen mit welcher Speed der Atmega16 tatsächlich läuft.

Mit Datenblatt:
AVR Fuses auslesen und Setting nachschlagen

Mit Oszi oder Frequenzzähler:
Takt per Hardware auf den Pin CLKOUT geben und messen.

Mit LED/Vorwiderstand:
F_CPU auf irgendeinen Wert z.B. 1 MHz definieren und eine LED mit Hilfe 
der _delay_ms() (#) blinken lassen. Wenn die im Programm vorgegebene 
Blinkzeit 8s beträgt und die LED tatsächlich im 1s Abstand blinkt, ist 
die tatsächliche F_CPU 8 MHz. Wenn die Messung mit diesen Zahlen zu 
schwierig ist, Zahlen im nächsten Durchgang anpassen.

(#)
1
#include <util/delay.h>
2
void warte()
3
{
4
  uint8_t i;
5
  for (i=0; i<8*10; i++)
6
    _delay_ms(100); // 100ms * 10 * 8 = 8s (bei F_CPU 1 MHz)
7
}

2. Tatsächliche F_CPU nach 1. definieren und damit UBRR berechnen und 
UART Programm laufen lassen.

Senderoutine:
1
int main()
2
{
3
  USARTinit();
4
  while(1)
5
  {
6
    while (!(UCSRA & (1<<UDRE))) // warten bis Senden möglich 
7
    {
8
    }
9
    UDR = 'x';    
10
  }
11
}

von Hc Z. (mizch)


Lesenswert?

> Die Schnittstelle ist ok, lt. AVRTerm
> scheint es eine Verbindung zu geben,

Es gibt bei einer einfachen Dreidrahtverbindung keine Möglichkeit für 
ein Terminalprogramm, Folgendes festzustellen: "lt. AVRTerm scheint es 
eine Verbindung zu geben".

Um die Schnittstelle zu testen: µC ziehen und den RxD- mit dem TxD-Pin 
verbinden.  Kommen jetzt alle eingegebenen Zeichen wieder zurück, ist 
die serielle Verdrahtung in Ordnung.

von Alexander S. (knut740)


Lesenswert?

Hallo

ist denn der Code an sich in Ordnung?

Bei der CPU-Taktfrequenz hatte ich über Delayschleifen schon 
festgestellt, daß der externe Quarz seinen Dienst tut. Nur habe ich noch 
nicht getestet, ob es ein 8 MHz oder ein 7,3...MHz (für UART) drin ist.
Auf jeden Fall will ich mir einen mit 7,3...MHz beschaffen und 
einsetzen.
Aber nebenbei: wenn die Baudrate ein wenig oder auch massiv falsch ist, 
müßte nicht irgendetwas gesendet werden?

@ Hc Zimmerer
Ausbau des µC ist schwierig, aber ich komme an die Kontakte. Könnte man 
hilfsweise auch die TX- und RX-Pins miteinenander verbinden - über einen 
1k-Widerstand, damit nichts zerstört wird?

Was ich zu erwähnen vergessen hatte: ich benutze ein Board AVR-P4ß 0535 
aus dem hiesigen Shop, mit MAX232 (und nachgerüsteter Drahtverbindung 
zwischen µC und MAX).

Viele Grüße
Alexander

von Karl H. (kbuchegg)


Lesenswert?

Alexander Schmeil schrieb:

> ist denn der Code an sich in Ordnung?

Dein Originalcode - Ausschnitt?
1
und dann aus endloser Schleife in main der Aufruf:
2
3
       USARTinit();
4
       while (!(UCSRA & (1<<UDRE)))  // warten bis Senden möglich 
5
         {                           // while-Schleife ist hier unnötig!)
6
         }
7
       UDR = 'x';

Nein.
Lass die UART arbeiten und Initialisiere sie nicht innerhalb der 
Endlosschleife immer wieder neu.
Initialisieren heist deshalb Initialisieren, weil man diese Aktion am 
Anfang des Programms nur einmal macht.

> Bei der CPU-Taktfrequenz hatte ich über Delayschleifen schon
> festgestellt, daß der externe Quarz seinen Dienst tut. Nur habe ich noch
> nicht getestet, ob es ein 8 MHz oder ein 7,3...MHz (für UART) drin ist.

Das solltest du aber wissen.
Allerdings: wenn der Wert nicht mit dem übereinstimmt, mit dem du 
rechnest sollte sich zumindest beim Empfänger etwas tun. Du kriegst zwar 
die falschen Zeichen, aber du kriegst zumindest irgendwelche Zeichen


> @ Hc Zimmerer
> Ausbau des µC ist schwierig, aber ich komme an die Kontakte. Könnte man
> hilfsweise auch die TX- und RX-Pins miteinenander verbinden - über einen
> 1k-Widerstand, damit nichts zerstört wird?

Meinst du die Tx/Rx Pins direkt am Prozessor?
Ich denke nicht das das funktionieren wird. Letztendes hängt es davon 
ab, wer mehr "Kraft" hat: der µC, der seinen Ausgangspin auf zb 0 halten 
will, oder der RS232-Treiber, der dieselbe Leitung partout auf 1 ziehen 
will.

> Was ich zu erwähnen vergessen hatte: ich benutze ein Board AVR-P4ß 0535
Wo liegt dann das Problem?
Den Prozessor aus dem Sockel ziehen. Mit einem Stückchen Draht im Sockel 
eine Verbindung der RX/Tx Pins herstellen und auf dem PC auf der 
Tastatur klimpern. Wenn die Übertragungsstrecke steht, dann erscheint 
das Getippte wieder auf dem PC. Gegentest: Drahtbrücke rausnehmen und 
das mitschreiben auf dem PC muss aufhören.

von Hc Z. (mizch)


Lesenswert?

> Ausbau des µC ist schwierig, aber ich komme an die Kontakte. Könnte man
> hilfsweise auch die TX- und RX-Pins miteinenander verbinden?

Nein, das wird nicht funktionieren.  Der AVR wird sich gegenüber dem 
MAX232 durchsetzen.

Abgesehen davon solltest Du erst mal die Baudrate ermitteln.  Wenn die 
nicht auf wenige einstellige Prozent stimmt, klappt die Übertragung 
nicht.  Allerdings sollte bei Abweichungen wie 8 MHz vs. 7,3 MHz schon 
wenigstens Müll auf der Gegenseite ankommen.

von Alexander S. (knut740)


Lesenswert?

>
>        USARTinit();
>        while (!(UCSRA & (1<<UDRE)))  // warten bis Senden möglich
>          {                           // while-Schleife ist hier
> unnötig!)
>          }
>        UDR = 'x';
> [/C]
>
> Nein.
> Lass die UART arbeiten und Initialisiere sie nicht innerhalb der
> Endlosschleife immer wieder neu.

sorry, habe ich falsch kopiert, die Initialisierung ist in Wirklichkeit 
v o r  dem Eintritt in die Endlosschleife. Aber sonst sind die Register 
usw. richtig?


> die falschen Zeichen, aber du kriegst zumindest irgendwelche Zeichen
damit wäre ich als erste Erfolgkontrolle höchst zufrieden, bis der 
UART-Quarz geliefert wird.
>

> Meinst du die Tx/Rx Pins direkt am Prozessor?
> Ich denke nicht das das funktionieren wird. Letztendes hängt es davon
> ab, wer mehr "Kraft" hat: der µC, der seinen Ausgangspin auf zb 0 halten
> will, oder der RS232-Treiber, der dieselbe Leitung partout auf 1 ziehen
> will.
Ja, ich hatte an die PINs direkt am µC gedacht, weil der Ausbau durch 
darüberliegende Teile (LCD usw) sehr schwierig ist. Aber ich könnte auf 
dem µC ein "Programm" laufen lassen, das die beiden PINs auf high oder 
low hält???

Gruß
Alexander

von Karl H. (kbuchegg)


Lesenswert?

Alexander Schmeil schrieb:

> Ja, ich hatte an die PINs direkt am µC gedacht, weil der Ausbau durch
> darüberliegende Teile (LCD usw) sehr schwierig ist. Aber ich könnte auf
> dem µC ein "Programm" laufen lassen, das die beiden PINs auf high oder
> low hält???

Und, was hilft dir das?
Es ist trotzdem (im Prinzip nach) nur 1 'Kabel' an dem alle Teilnehmer 
hängen. Und wenn der eine auf 1 will und der andere auf 0, dann gibt es 
ein Problem.

Bau die Hardware auseinander. Bei der Gelegenheit kannst du auch gleich 
nachsehen, was auf deinem Quarz draufsteht :-)

von Alexander S. (knut740)


Lesenswert?

Karl heinz Buchegger schrieb:

>
> Bau die Hardware auseinander. Bei der Gelegenheit kannst du auch gleich
> nachsehen, was auf deinem Quarz draufsteht :-)


Ich habe am MAX232 (der bei mir anders beschriftet ist) die TX- und 
RX-Pins verbunden - und auf dem PC-Monitor waren die eingegebenen 
Zeichen zu sehen - wie Du beschrieben hast - also ist die Schnittstelle 
ok.

Als nächstes habe ich die bisher unbenutzten Verbindungen zu PB5 und PB6 
zu RX und TX getauscht - danach kamen auf dem PC verquere Zeichen an, 
die Übertragung mit "meinem" Code funktionierte also jetzt.

Zuletzt habe ich die Inschrift auf dem Quarz idenfizieren können, es war 
einer für UART (7372800 Hz), den Wert ins Makefile geschrieben - nun 
kommen ordentliche Zahlen an - und ich bin happy!

Ohne Eure Hilfe hätte ich mich noch lange mit der Software beschäftigt 
und nie an die vertauschten Leitungen gedacht.
Vielen Dank!

Gruß
Alexander

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.