mikrocontroller.net

Forum: Compiler & IDEs UART sendet nur 0x00 und 0xC0


Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich steh gerade mal im Wald
[C]
#include <avr/io.h>
#include <avr/delay.h>

#define SYSCLK    1048576  //intern 1Mhz = 2^20
#define BAUD    9200
#define UBRR_BAUD  ((SYSCLK/(16*BAUD))-1)

/* USART initialisieren */
void uart_init(void);


int main(void)
{
  unsigned char buffer;
  DDRD |= (1 << DDD7);    //Ausgang
  PORTD |= (1 << PD7);    //High

  /* USART initialisieren */
  uart_init();

  while (1)
  {
    /* Warten bis Daten empfangen wurden */
    while ( !(UCSRA & (1<<RXC)) );

    PORTD &= ~(1 << PD7);
    _delay_ms(300);

    /* Empfangsregister auslesen */
    buffer = UDR;

    /* Warten bis der Sendepuffer frei ist */
    while ( !( UCSRA & (1<<UDRE)) );

    PORTD |= (1 << PD7);

    /* Daten in den Puffer schreiben und damit senden */

    UDR = buffer;
   }
}

/* USART initialisieren */
void uart_init(void)
{
  /* Baudrate einstellen ( Normaler Modus ) */
  UBRRH = (unsigned char) (UBRR_BAUD>>8);
  UBRRL = (unsigned char) UBRR_BAUD;

  /* Aktivieren von receiver und transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);

  // 8 Datenbits, 1 Stoppbit
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

[\C]

Wenn ich über Bray-Terminal was sende, leuchtet eine LED und das
Empfangene wird wieder zurück gesendet.
Nur ... die LED leuchtet brav so wie es sein soll.
Aber das Empfangene im Terminal ist 0x00 und darauf folgend 0xC0, egal
was ich sende. Auch wenn ich einen String sende.
Was ist falsch ??

Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TESTCODE

Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UPS, Schrägstrich hat falsch Richtung
Tschuldigung

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #define SYSCLK    1048576  //intern 1Mhz = 2^20

Nein, 1 MHz ist 1 MHz ist 1 MHz und nicht 1 MiHz = 1,049 MHz.

#define SYSCLK 1000000ul

oder besser

#define F_CPU 1000000ul

(dieser Makro hat sich irgendwie eingebürgert dafür).

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich dachte erst,
> #define SYSCLK    1048576  //intern 1Mhz = 2^20
> #define BAUD    9200
> #define UBRR_BAUD  ((SYSCLK/(16*BAUD))-1)

könnte zufällig den richtigen Wert liefern, aber:

1048576/(9200*16)=7,
Gegenprobe: 1000000/(7*16)=8928 und das ist daneben genug...

Falk
P.S.: RS232 ist alles andere als trivial. Wenn man alle Möglichkeiten
berücksichtigt, einen Fehler zu machen, kommt man auf eine Erfolgsquote
von ca. 2^10:1 ;-)

Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke. Ich habs jetzt abgeändert. Funktioniert auch. Aber eine kleine
Frage hab ich noch.
Ich habe stehen:
// 8 Datenbits, 2 Stoppbit
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
Nach dem AVR-GCC Tutorial und einigen Beispielen im WWW müsste das
Terminal-Programm auch auf 8Daten, 2Stopp eingestellt werden.
Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück. Buchstaben
jedoch werden verfälscht.
Binär für ein 'a' kommt an: 11100001b
Stelle ich es auf 7Daten,2Stopp kommt alles richtig zurück.
Jetzt kommt für 'a': 01100001b
(?? 8te bit nicht gesendet ??)
Warum??

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück.
Buchstaben
jedoch werden verfälscht."


Das liegt daran:

#define SYSCLK    1048576  //intern 1Mhz = 2^20

Genauer an dem Wörtchen "intern"

Mehr sag ich dazu nicht, zweimal die Woche reicht mir, hab ja schon
Fusseln am Mund.


Peter

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Homer:
> "Stelle ich es auf 8Daten,2Stopp kommen alle Ziffern zurück.
> Buchstaben jedoch werden verfälscht."

Peter:
> Das liegt daran:
> #define SYSCLK    1048576  //intern 1Mhz = 2^20
> Genauer an dem Wörtchen "intern"

Er hat ja "etwas" abgeändert.

Die wahrscheinlichsten Fehler:
1) 9600Bd mit ca. 1MHz ergibt einen Fehler >7% (Wenn U2X==0)
2) 9200 != 9600, 2^20 != 10^6
3) Der RC-Oszillator ist für sowas nicht gut geeignet.

Wenn 1) und 2) korrigiert sind, könnte es trotz 3) sogar oft
funktionieren.

> Mehr sag ich dazu nicht, zweimal die Woche reicht mir, hab ja
> schon Fusseln am Mund.

Deswegen tippe ich mit den Fingern, das gibt zwar Hornhaut, aber die
Tasten bleiben trocken ;-)

Falk

Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>

#define F_CPU    1000000ul
#define BAUD    9600
#define UBRR_BAUD ((F_CPU/(16l*BAUD))-1)

/* USART initialisieren */
void uart_init(void);
void uart_send(unsigned char buffer);
unsigned char uart_receive(void);

int main(void)
{
  unsigned char buffer;
  //DDRD |= (1 << DDD7)|(1 << DDD6);    //Ausgang
  //PORTD |= (1 << PD7)|(1 << PD6);    //High

  /* USART initialisieren */
  uart_init();
    
  while (1)
  {
  /*  
    // Warten bis Daten empfangen wurden

    PORTD &= ~(1 << PD7);
    while ( !(UCSRA & (1<<RXC)) );
    
    // Empfangsregister auslesen
    PORTD |= (1 << PD7);
    buffer = UDR;

    // Warten bis der Sendepuffer frei ist
      PORTD &= ~(1 << PD6);
    while ( !( UCSRA & (1<<UDRE)) );

    PORTD |= (1 << PD7)|(1 << PD6);

    // Daten in den Puffer schreiben und damit senden
    
    UDR = (buffer);
  */  
  buffer = uart_receive();
  uart_send(buffer);  
  
   }
}

/* USART initialisieren */
void uart_init(void)
{
  /* Baudrate einstellen ( Normaler Modus ) */
  UBRRH = (unsigned char) (UBRR_BAUD>>8);
  UBRRL = (unsigned char) UBRR_BAUD;

  /* Aktivieren von receiver und transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);

  // 8 Datenbits, 2 Stoppbit
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void uart_send(unsigned char buffer)
{
    // Warten bis Daten empfangen wurden
    while ( !(UCSRA & (1<<RXC)) );
    
    /* Warten bis der Sendepuffer frei ist */
    while ( !( UCSRA & (1<<UDRE)) );

    /* Daten in den Puffer schreiben und damit senden */
    UDR = (buffer);
    while ( !( UCSRA & (1<<UDRE)) );
}

unsigned char uart_receive(void)
{
    // Warten bis Daten empfangen wurden
    while ( !(UCSRA & (1<<RXC)) );

    // Empfangsregister auslesen
//    buffer = UDR;
    
    // Wert zurückgeben
    return UDR;
}
Ich habs jetzt abgeändert. Funktioniert bei 7Datenbits. Danke also
schon mal.
7Datenbits
01100010    'a'
8Datenbits
11100001    'a'
(?? 8te Bit nicht gesendet ??)

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #define F_CPU    1000000ul
> #define BAUD    9600
> #define UBRR_BAUD ((F_CPU/(16l*BAUD))-1)

Rechnen wir mal:
1.000.000/(16*9600)=6,51041 --> UBRRL=6, UBRRH=0

>  UBRRH = (unsigned char) (UBRR_BAUD>>8);
>  UBRRL = (unsigned char) UBRR_BAUD;

Und damit stellst Du
1.000.000/(6*16)=10416,66666 --> 10416 Baud ein.

Schreibe mal
UCSRA |= (1 << U2X);
UBRR = 12;         //Statt UBRRL=... und UBRRH=...
in die Initialisierung.

Warum das dann klappt, steht in
http://www.atmel.com/dyn/resources/prod_documents/...
genau erklärt.

Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.