Forum: Mikrocontroller und Digitale Elektronik "Zeichensalat" über den UART


von Timo (Gast)


Lesenswert?

Hallo,
Haben folgendes Programm in den Controller (ATMega 16) geladen:
1
#include <avr/io.h>
2
3
#ifndef F_CPU
4
#define F_CPU 8000000UL              
5
#endif              
6
7
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
8
9
#define UART_BAUD_RATE 9600         
10
11
12
int main (void)
13
{
14
  UCSRB  |=  (1<<TXEN);            
15
  UCSRC  |=  (1<<URSEL)  |  (3<<UCSZ0);  
16
17
  UBRRH  =  0x00;
18
  UBRRL  =  0x33;
19
 
20
  //Senden einzelner Zeichen
21
22
  while (!(UCSRA & (1<<UDRE)))        
23
  {
24
  }
25
26
  while (1)
27
  {
28
    UDR    =  'A';
29
  }
30
31
  return (0);
32
  }

Die Baudrate ist auf 9600 eingestellt -> siehe UBRRL = 33_hex -> 51_dez
-> bei 8 MHz = 9600 Baud (laut Toturial)

Wir haben einen Schnittstellentreiber benutzt (MAX232). Zum Testen, ob
der Controller "sendet", haben wir ein Schnittstellentester zwischen
MC und PC geschaltet. Die LED TX und RX leuchten korrekt. Wir verwenden
auch das korrekte Kabel. Wir wollen das Zeichen "A" nun am PC auslesen.
Wir benutzen HyperTerminal. Drücken wir nun auf lesen (Baud - Rate,
Stop - , Startbit und soweiter korrekt eingestellt) erhalten wir
Zeichen vom MC. Jedoch NICHT nur dass gewünschte A, sondern ab und zu
ist ein "P" dabei, ein "I" u.s.w. Sieht aber alles sehr regelmäßig aus.
Wir haben nun zum Test ein anderes Zeichen vom MC gesendet. Es kommt
aber immer der selbe "Zeichensalat" an. Wir haben die TX - Leitung des
MC am Oszilloskop untersucht. Das "A" lässt sich nicht erkennen. Wir
haben das wie folgt gemacht:

ASCII - Code für "A" herausgesucht. Diesen in einen Binärwert
umgerechnet. Start- und Stopbit berücksichtigt. Dann haben wir uns
dass zu erwartende Bitmuster aufgezeichnet.
Anschließend haben wir gemessen. Das theoretische stimmt keineswegs
mit dem gemessenen überein. Wir sehen zwar TTL - Signale, die auch
sehr regelmäßig sind, diese ergeben aber keinen Sinn. Rechnerisch
brauchen wir bei 9600 Baud pro Bit etwa 10 us. Am Oszilloskop nach-
gemessen sind es etwa 100 us.

Ist am Programm etwas faul?
Sonstige Ideen ?

Achja:
Folgende Änderung des Quellcodes haben wir verwendet:
1
  while (1)
2
  {
3
    if (UCSRA & (1<<UDRE))
4
    {
5
    UDR    =  'A';
6
    }
7
  }

Nach dieser Änderung sollte er nach jedem gesendeten Zeichen auf die
Bereitschaft ein Zeichen zu senden warten. Aber auch hier das selbe
Problem wie bereits erwähnt. Wir empfangen "Zeichensalat".

von Jörg X. (Gast)


Lesenswert?

Du wartest beim ersten Code-Teil ein Mal darauf, dass der USART bereit 
ist. Du musst das natürlich jedes Mal machen:
1
while (1){
2
    while(!UCSRA & (1<<UDRE))
3
        ; // dies ist eine Warteschleife
4
    UDR = 'A';
5
}
und die ~100µs scheinen mir korrekt: beim UART entspricht die Baudrate 
der _Bit_-rate

lies bitte noch mal nach, wie man die Register des UART benutzt (im 
Datasheet am besten)

hth. Jörg

von Timo (Gast)


Lesenswert?

Danke Jörg. Meinst du also, dass ich die Register falsch benutze?

von Jörg X. (Gast)


Lesenswert?

Nicht völlig falsch, aber man sollte sich die entsprechenden Kapitel mal 
anschauen ("Register description", gibt's im Datasheet für fast alle 
Peripherie) und auch den Code verstehen, wie z.B die leeren 
while-Schleifen, die ja öfter vorkommen.
 Auch ist es besser Formeln in den Code zu schreiben, z.B. in Makros, 
als nur die Zahlen. In deinem Quelltext stehen die defines für die 
UBRR-Registerwerte schon drin, aber du benutzt sie nicht:
1
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
2
#define UART_BAUD_RATE 9600
3
4
// ...
5
6
UBRRH = UART_UBBR_CALC(UART_BAUD_RATE) >> 8; //Highbyte
7
UBRRL = UART_UBBR_CALC(UART_BAUD_RATE); //Lowbyte
8
/* falls das nicht klappt, beides nach "uint8_t" bzw "unsigned char" casten:
9
UBRRL = (uint8_t) UART_UBBR_CALC(UART_BAUD_RATE);
10
*/
Die Warteschleife "while(!UCSRA & (1<<UDRE));" soll verhindern, dass 
Werte im UDR überschrieben werden.

Und die letzte Fehlerquelle (eigentlich die erste): Bist du sicher, dass 
der Atmega mit den 8MHz läuft?
 Nur "#define F_CPU 8000000L" reicht ja nicht (Stichwort: Fuses).

hth. Jörg

von Timo (Gast)


Lesenswert?

Also:
Der Controller läuft mit 8 MHz. Haben es extra mit dem Oszi überprüft. 
Wir haben deine Zeile zum Senden übernommen:

Also:
1
while (1){
2
    while(!UCSRA & (1<<UDRE))
3
        ; // dies ist eine Warteschleife
4
    UDR = 'A';
5
}

Der Pegelwandler ist richtig verlötet. Wir empfangen trotzdem nicht das 
gewünschte Zeichen.

An was kann es liegen? Es kommt wieder "Zeichensalat" an.

Gruß

von Toni (Gast)


Lesenswert?

Masse verbunden?

von holger (Gast)


Lesenswert?

Internen RC Osci verwendet ?

von Falk (Gast)


Lesenswert?

@ Timo (Gast)

>Der Controller läuft mit 8 MHz. Haben es extra mit dem Oszi überprüft.

Mit inerenm 8 MHz Oszillator (UNGENAU!) oder Quarz/Quarzoszillator?

http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART#Senden

MfG
Falk

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.