"Zeichensalat" über den UART

Gast #599554
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".
Gast #599564
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
Gast #599642
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
Gast #602063
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ß

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.