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


von Homer (Gast)


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 ??

von Homer (Gast)


Lesenswert?

1
TESTCODE

von Homer (Gast)


Lesenswert?

UPS, Schrägstrich hat falsch Richtung
Tschuldigung

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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).

von Falk W. (dl3daz) Benutzerseite


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 ;-)

von Homer (Gast)


Lesenswert?

Danke. Ich habs jetzt abgeändert. Funktioniert auch. Aber eine kleine
Frage hab ich noch.
Ich habe stehen:
1
// 8 Datenbits, 2 Stoppbit
2
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??

von peter dannegger (Gast)


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

von Falk W. (dl3daz) Benutzerseite


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

von Homer (Gast)


Lesenswert?

1
#include <avr/io.h>
2
3
#define F_CPU    1000000ul
4
#define BAUD    9600
5
#define UBRR_BAUD ((F_CPU/(16l*BAUD))-1)
6
7
/* USART initialisieren */
8
void uart_init(void);
9
void uart_send(unsigned char buffer);
10
unsigned char uart_receive(void);
11
12
int main(void)
13
{
14
  unsigned char buffer;
15
  //DDRD |= (1 << DDD7)|(1 << DDD6);    //Ausgang
16
  //PORTD |= (1 << PD7)|(1 << PD6);    //High
17
18
  /* USART initialisieren */
19
  uart_init();
20
    
21
  while (1)
22
  {
23
  /*  
24
    // Warten bis Daten empfangen wurden
25
26
    PORTD &= ~(1 << PD7);
27
    while ( !(UCSRA & (1<<RXC)) );
28
    
29
    // Empfangsregister auslesen
30
    PORTD |= (1 << PD7);
31
    buffer = UDR;
32
33
    // Warten bis der Sendepuffer frei ist
34
      PORTD &= ~(1 << PD6);
35
    while ( !( UCSRA & (1<<UDRE)) );
36
37
    PORTD |= (1 << PD7)|(1 << PD6);
38
39
    // Daten in den Puffer schreiben und damit senden
40
    
41
    UDR = (buffer);
42
  */  
43
  buffer = uart_receive();
44
  uart_send(buffer);  
45
  
46
   }
47
}
48
49
/* USART initialisieren */
50
void uart_init(void)
51
{
52
  /* Baudrate einstellen ( Normaler Modus ) */
53
  UBRRH = (unsigned char) (UBRR_BAUD>>8);
54
  UBRRL = (unsigned char) UBRR_BAUD;
55
56
  /* Aktivieren von receiver und transmitter */
57
  UCSRB = (1<<RXEN)|(1<<TXEN);
58
59
  // 8 Datenbits, 2 Stoppbit
60
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
61
}
62
void uart_send(unsigned char buffer)
63
{
64
    // Warten bis Daten empfangen wurden
65
    while ( !(UCSRA & (1<<RXC)) );
66
    
67
    /* Warten bis der Sendepuffer frei ist */
68
    while ( !( UCSRA & (1<<UDRE)) );
69
70
    /* Daten in den Puffer schreiben und damit senden */
71
    UDR = (buffer);
72
    while ( !( UCSRA & (1<<UDRE)) );
73
}
74
75
unsigned char uart_receive(void)
76
{
77
    // Warten bis Daten empfangen wurden
78
    while ( !(UCSRA & (1<<RXC)) );
79
80
    // Empfangsregister auslesen
81
//    buffer = UDR;
82
    
83
    // Wert zurückgeben
84
    return UDR;
85
}
Ich habs jetzt abgeändert. Funktioniert bei 7Datenbits. Danke also
schon mal.
7Datenbits
01100010    'a'
8Datenbits
11100001    'a'
(?? 8te Bit nicht gesendet ??)

von Falk W. (dl3daz) Benutzerseite


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/doc2486.pdf
genau erklärt.

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.