Forum: Mikrocontroller und Digitale Elektronik RS232 unter C auf Atmega8 konfiguriren


von Viktor T. (viktort)


Lesenswert?

hallo,

habe folgendes problem, ich habe die baud rate auf dem PC und µc 
angepast (9600 8N1) und den externen quartz eingestelt 3,6MHz auch die 
dafür notwendigen fuse bits gesetzt, meine konfiguration in C (siehe 
unten).

Ich bekomme aber laute unsinige Zeichen angezeigt.

ich komme einfach nicht weiter.

#define   F_CPU   3686400
#include   <avr\io.h>
#define   BAUD   9600
//----------------------------------------------------------------------
// Titel   : C-Funktion Zeichen zu UART senden.
// IN       : char data
//----------------------------------------------------------------------
void uartPutChar(char data)
{
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
  while (!(UCSRA&32));
  //sende
  UDR=data;
}
void uartPutBin(char data)
{
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
  while (!(UCSRA&32));
  //sende
if (data&1)   uartPutChar('1'); else uartPutChar('0');
if (data&2)   uartPutChar('1'); else uartPutChar('0');
if (data&4)   uartPutChar('1'); else uartPutChar('0');
if (data&8)   uartPutChar('1'); else uartPutChar('0');
if (data&16)  uartPutChar('1'); else uartPutChar('0');
if (data&32)  uartPutChar('1'); else uartPutChar('0');
if (data&64)  uartPutChar('1'); else uartPutChar('0');
if (data&128) uartPutChar('1'); else uartPutChar('0');
}
//----------------------------------------------------------------------
// Titel   : C-Funktion wartet auf Zeichen von UART.
// OUT      : data
//----------------------------------------------------------------------
char uartGetChar()
{
  char data=0;
  //warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
  while (!(UCSRA&128));
  //empfangen
  data=UDR;
  return data;
}
//----------------------------------------------------------------------
// Titel   : C-Funktion wartet auf Zeichen von UART.
// OUT      : data, error = keine Daten
//----------------------------------------------------------------------
bool error;
char uartIsChar()
{
  char data=0;
  error=true;
  //chek RX-complete RXC UCSRA
  if (!(UCSRA&128)) return 0;
  //zeihen abholen
  data=UDR;
  error=false;
  return data;
}
//----------------------------------------------------------------------
// Titel   : C-Funktion Zeichenkette zu UART senden.
// IN       : char *buffer, Zeichenkette mit NUll abgeschlossen
//----------------------------------------------------------------------
void uartPutString(char *buffer)
{
  for (int i=0; buffer[i] !=0;i++)
    uartPutChar (buffer[i]);
}
//---------------------------------------------------------------------- 
--
// Initialisierungen
//---------------------------------------------------------------------- 
--
void init()
{
  // UART initialisieren
  sbi(UCSRB,3);   // TX aktiv
  sbi(UCSRB,4);   // RX aktivieren
  UBRRL=(uint8_t)(F_CPU/(BAUD*16L))-1;   // Baudrate festlegen
  UBRRH=(uint8_t)((F_CPU/(BAUD*16L))-1)>>8;   // Baudrate festlegen
  //alles Ausgang
  DDRB=0b00111111;
  DDRC=0b11111111;
  DDRD=0b11111110;
}

von Peter D. (peda)


Lesenswert?

Deine Init stimmt nicht.
1
void init_uart( uint16_t bauddivider )
2
{
3
  UBRRH = bauddivider >> 8;
4
  UBRRL = bauddivider;                  // set baud rate
5
  UCSRA = 0;                            // no U2X, MPCM
6
  UCSRC = 1<<UCSZ1^1<<UCSZ0             // 8 Bit
7
#ifdef URSEL
8
           ^1<<URSEL                    // if UCSR0C shared with UBRR0H
9
#endif
10
           ;
11
  UCSRB = 1<<RXEN^1<<TXEN;              // enable RX, TX
12
}


Peter

von Timmo H. (masterfx)


Lesenswert?

Viktor Tschetwerik schrieb:
> void init()
> {
>   // UART initialisieren
>   sbi(UCSRB,3);   // TX aktiv
>   sbi(UCSRB,4);   // RX aktivieren
Machs doch so wie alle anderen:
1
  UCSRB = (1<<RXEN) | (1<<TXEN);
2
  UBRRL=(uint8_t)(F_CPU/(BAUD*16L))-1;   // Baudrate festlegen
3
  UBRRH=(uint8_t)((F_CPU/(BAUD*16L))-1)>>8;   // Baudrate festlegen
4
  // Hier was wichtiges:
5
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
6
  DDRB=0xff;
7
  DDRC=0xff;
8
  DDRD = ~(1<<PD0);

Und was ist denn das für eine Schreibweise
>void uartPutChar(char data)
>{
>  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
>  while (!(UCSRA&32));
besser:
1
void uartPutChar(char data)
2
{
3
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
4
  while (!(UCSRA & (1<<UDRE))) ;
5
  UDR=data;
6
}

übrigens kannst du dir das " while (!(UCSRA & (1<<UDRE))) ;" in der 
uartPutBin auch sparen, da du es eh bei jedem Zeichen in der uartPutChar 
prüfst.

von Peter D. (peda)


Lesenswert?

Viktor Tschetwerik schrieb:
> void uartPutBin(char data)
> {
>   //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
>   while (!(UCSRA&32));
>   //sende
> if (data&1)   uartPutChar('1'); else uartPutChar('0');
> if (data&2)   uartPutChar('1'); else uartPutChar('0');
> if (data&4)   uartPutChar('1'); else uartPutChar('0');
> if (data&8)   uartPutChar('1'); else uartPutChar('0');
> if (data&16)  uartPutChar('1'); else uartPutChar('0');
> if (data&32)  uartPutChar('1'); else uartPutChar('0');
> if (data&64)  uartPutChar('1'); else uartPutChar('0');
> if (data&128) uartPutChar('1'); else uartPutChar('0');
> }

Also in unseren Breitengraden steht ja üblicherweise das höchstwertige 
Digit links.
Auch muß man Flash nicht mit Gewalt vergeuden.
1
void binout( uint8_t val )
2
{
3
  for( uint8_t i = 8; i--; val <<= 1 )
4
    uputchar( '0' + !!(val & 0x80) );
5
}


Peter

von Timmo H. (masterfx)


Lesenswert?

> !!(val & 0x80)
^^ das ist echt tricky, gefällt mir.
Hab sonst auch immer
1
if(val & 0x80)
2
  putchar('1');
3
else
4
  putchar('0');
gemacht, vorteil ist natürlich dass es leserlicher ist.

von Viktor T. (viktort)


Lesenswert?

Vielen dank für eure schnelle Antwort, ich habe es ausprobiert und es 
geht immer noch nicht. Dar selbe fehlerbild!:-( er zeigt mir laute 
unleserliche zeichen!

von Karl H. (kbuchegg)


Lesenswert?

Viktor Tschetwerik schrieb:
> Vielen dank für eure schnelle Antwort, ich habe es ausprobiert und es
> geht immer noch nicht. Dar selbe fehlerbild!:-( er zeigt mir laute
> unleserliche zeichen!

Dann solltest du erst mal prüfen, ob das hier

#define   F_CPU   3686400


auch tatsächlich stimmt.
Dort ist eine Testprozedur beschrieben:
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

Solange du die nicht positiv bestätigen kannst, macht es keinen Sinn, 
sich über weitere Dinge zu unterhalten.


Deine Init hast du schon korrigiert?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Viktor Tschetwerik schrieb:
> Vielen dank für eure schnelle Antwort, ich habe es ausprobiert und es

Welche der beiden Vorschläge hast du ausprobiert?

In deinem Beispiel sehe ich auch keine main() Funktion. Man kann nicht 
entscheiden, ob du die uart* Funktionen überhaupt korrekt aufrufst.

> geht immer noch nicht. Dar selbe fehlerbild!:-( er zeigt mir laute
> unleserliche zeichen!

Und die wären bei welchem gesendeten Zeichen welches empfangene Zeichen?

Hast du schon auf dem PC alle Baudraten (insbes. 1200 BAUD) 
durchprobiert?

Welche Werte stehen in UBRRH und UBRRL letztendlich?

von Karl H. (kbuchegg)


Lesenswert?

Wichtig ist zb auch hier im Original
1
  UBRRL=(uint8_t)(F_CPU/(BAUD*16L))-1;   // Baudrate festlegen
2
  UBRRH=(uint8_t)((F_CPU/(BAUD*16L))-1)>>8;   // Baudrate festlegen

das die Reihenfolge, in der 16 Bit Pseudoregister beschrieben werden, 
eben nicht egal ist. Diese hier ist falsch rum.
Bei derartigen 16-Bit Registern: Immer zuerst H beschreiben und dann L

Ein Studium des Tutorial-Artikels
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART
ist dringend angeraten!

von Viktor T. (viktort)


Lesenswert?

hallo, tut mir leid das ich mich lange nicht gemeldet hab, ich habe 
folgendes ausprobiert und es hat mehr oder weniger geklapt, blos halt 
zimmlich ungenu und langsam.

#define F_CPU 3686400
#include <avr\io.h>
//----------------------------------------------------------------------
void uartInit()
{
  UBRRL = 23;           //9600Baud siehe Baudratentabelle
  UCSRB = 8 + 16;         //Sender enable, Empfänger enable
}
//----------------------------------------------------------------------
char uartGetChar()
{
  char data=0;
  //warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
  while (!(UCSRA&128));
  //empfangen
  data=UDR;
  return data;
}
//----------------------------------------------------------------------
void uartPutChar(char data)
{
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
  while (!(UCSRA&32));
  //sende
  UDR=data;
}
//----------------------------------------------------------------------
main ()
{
  uartInit();
  while (true) // Mainloop
  {
    char zeichen;
    zeichen=uartGetChar();
    uartPutChar(zeichen);
  }
}


hier ist noch die intro funktion was er mir anzeigen soll habe aus eimen 
bsp rausgenomen und wie es in main aufegufen wird.

void intro()
{
  uartPutChar('\n');
  for (int i=0;i<42;i++) uartPutChar('=');
  uartPutString("\n mySmartControl Simple Term 1.2 \n www.myAVR.de");
  uartPutChar('\n');
  for (int i=0;i<42;i++) uartPutChar('-');
  uartPutString("\nKommandos: zwei Byte, Kein Trennzeichen");
  uartPutString("\n PB = PortB alle Bits ON");
  uartPutString("\n pb = PortB alle Bits OFF");
  uartPutString("\n PC = PortC alle Bits ON");
  uartPutString("\n pc = PortC alle Bits OFF");
  uartPutString("\n PD = PortD alle Bits ON");
  uartPutString("\n Bx = PortB Bit X ON  (X = 0..5)");
  uartPutString("\n bx = PortB Bit X OFF (X = 0..5)");
  uartPutString("\n Cx = PortC Bit X ON  (X = 0..5)");
  uartPutString("\n cx = PortC Bit X OFF (X = 0..5)");
  uartPutString("\n Dx = PortD Bit X ON  (X = 2..7)");
  uartPutString("\n dx = PortD Bit X OFF (X = 2..7)");
  uartPutString("\n iX = config Port(C,B,D) IN mit PullUP");
  uartPutString("\n ix = config Port(c,b,d) IN ohne PullUP");
  uartPutString("\n gx = get PIN(b,c,d)");
  uartPutString("\n GX = get Port(B,C,D)");
  uartPutString("\n Gx = get DDR(b,c,d)");
  uartPutString("\n Ox = config Port(B,C,D) = OUT");
  uartPutChar('\n');
  for (int i=0;i<42;i++) uartPutChar('=');
}
//////////////////////////////////////////////////////////////////////// 
/////
// Main-Funktion
//////////////////////////////////////////////////////////////////////// 
/////
main()
{
  unsigned char portBuffer[3]={0}; // B,C,D
  char z1,z2;
  init();   // Initialisierungen
  intro();
  while (true)    // Mainloop-Begin


Großen dank nochmal!

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.