Forum: Compiler & IDEs Mega8 UART funktioniert nicht


von Dominik (Gast)


Lesenswert?

Hallo!
Ich habe bisher meinen Mega8 immer mit Assembler programmiert. Jetzt 
habe ich ein Programm angefangen, dass mit Assembler einfach zu 
umständlich wird und bin deshalb auf C umgestiegen.

Mit Assembler hat das Senden über den UART problemlos geklappt, mit C 
funktioniert es komischerweise nicht. Es kommt nur sporadisch mal ein 
Zeichen, dass so aussieht wie ein hochgesetztes L. Es wird aber 
scheinbar permanent etwas gesendet, da die LEDs an TX und RX flackern. 
Da es mit Assembler klappt, ist die Hardware also schonmal in Ordnung.

Vielleicht ist es nur ein kleiner Fehler. Bitte helft mir.

Hier mein Code:

#define F_CPU 8000000
#define BAUD 9600

#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
#define LOW(x) ((x) & 0xFF)
#define HIGH(x) (((x) >> 8) & 0xFF)


#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu 
hoch!
#endif


#include <avr/io.h>
#include <stdlib.h>

void initUART()
{
  UCSRB |= (1<<TXEN);
  UBRRL = LOW(UBRR_VAL);
  UBRRH = HIGH(UBRR_VAL);
}

int uart_putc(unsigned char c)
{
  while (!(UCSRA & (1<<UDRE)));  /* warten bis Senden moeglich */
  UDR = c;                      /* sende Zeichen */
  return 0;
}

void uart_puts (char *s)
{
    while (*s)
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
        uart_putc(*s);
        s++;
    }
}

void main()
{
  char buffer[20];

  initUART();

  while(1)
  {
  //sprintf(buffer, "Hallo");
  //uart_puts(buffer);
  uart_putc('H');
  uart_putc('A');
  uart_putc('L');
  uart_putc('L');
  uart_putc('O');
  }
}

von Sven P. (Gast)


Lesenswert?

Dominik wrote:
> void initUART()
> {
>   UCSRB |= (1<<TXEN);
>   UBRRL = LOW(UBRR_VAL);
>   UBRRH = HIGH(UBRR_VAL);
> }

Wie war das mit dem temporären oberen Register?
1
/* entweder */
2
   UBRRH = HIGH(UBRR_VAL);
3
   UBRRL = LOW(UBRR_VAL);
4
/* oder */
5
   UBRR = UBRR_VAL

von Dominik (Gast)


Lesenswert?

OK, danke. Das war schonmal der erste dumme Fehler. Da muss aber noch 
was sein, denn es funktioniert immer noch nicht.

von Stefan E. (sternst)


Lesenswert?

Das "Übliche" hast du abgecheckt?

Richtige BAUD-Rate am Empfänger eingestellt?
Läuft der Mega8 wirklich mit 8MHz?

von Dominik (Gast)


Lesenswert?

Ja, das übliche habe ich gecheckt. Wie gesagt, wenn ich eins von meinen 
Assemblerprogrammen lade, funktioniert es direkt.

von Dominik (Gast)


Lesenswert?

Statt Hyperterminal benutze ich jetzt TeraTerm. In TeraTerm werden jetzt 
sehr schnell hintereinander diese besagten "L" ausgegeben. Woran liegt 
das denn bloß???

von Johannes M. (johnny-m)


Lesenswert?

Sven Pauli wrote:
> Wie war das mit dem temporären oberen Register?
Gibt's beim USART Baud Rate Register aber nicht (macht auch nur dort 
Sinn, wo es wirklich wichtig ist, dass die Werte für Low- und High-Byte 
synchronisiert werden)

> /* entweder */
>    UBRRH = HIGH(UBRR_VAL);
>    UBRRL = LOW(UBRR_VAL);
Siehe oben: Reihenfolge spielt in diesem Fall keine Rolle

> /* oder */
>    UBRR = UBRR_VAL
Ein 16-Bit-Register gibt es in diesem Falle nicht und kann es auch nicht 
geben, u.a. weil UBRRL und UBRRH beim Mega8 im Speicher nicht 
hintereinander liegen.

von Dominik (Gast)


Lesenswert?

Kurzes Update:
Es muss irgendwo in der Baudraten-Berechnung der Wurm drin sein. Ich 
habe jetzt ins Baudratenregister direkt den Wert 52 geschrieben (aus der 
Tabelle im Datenblatt entnommen).

Jetzt kommt aber nur nach mehrmaligem Reset-Drücken das gewünschte 
Zeichen!!!

Woran liegt das nun wieder? Ich verzweifele gleich....

von Johannes M. (johnny-m)


Lesenswert?

> #define BAUD 9600
Das müsste vermutlich ein 9600L oder 9600UL sein, F_CPU sollte auch ein 
8000000UL verpasst bekommen, sonst kann es Problemchen bei der 
Berechnung geben...

von Dominik (Gast)


Lesenswert?

Danke Johannes. Trotzdem ist das Problem noch da: Nur nach mehrmaligem 
Reset kommen die richtigen Zeichen an. Wenn man dann nochmal Reset 
drückt kommen meistens wieder die falschen.

von gast (Gast)


Lesenswert?

mal nen auszug vin meinem mega8, da funktionierts:
[c]
#include <inttypes.h>
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include "lcd_mega8.h"

#ifndef F_CPU
#define F_CPU 8000000
#endif

#define BAUD 9600UL //Baudrate
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)

void wait (uint16_t zeit) //zeit: wartezeit in ms (0 bis 65536)
{
   uint16_t i;
   for(i=0;i<zeit;i++) _delay_ms(1); //da für _delay_ms max 
Takt-abhängige Werte erlaubt
}

// 
uart#################################################################### 
##
void uart_init(void)
{
  UCSRB = (1<<RXEN)|(1<<TXEN);      // UART TX und RX einschalten
    UCSRC |= ( 1 << URSEL )|( 3<<UCSZ0 );  // Asynchron 8N1
  //nur für 19200 Baud bei 16MHz für Mega32
    //UBRRH  = 0;                             // Highbyte ist 0
    //UBRRL  = 51;                            // Lowbyte ist 51

  //falls anderer Mega bzw andere Frequenz
  UBRRH = (uint8_t) (UBRR_BAUD>>8);
    UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
}

void uart_data(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE))) {}  // warten bis Senden möglich
    UDR = c;                         // Zeichen senden
}

void uart_string (char *s)
{
    while (*s)
    {   uart_data(*s);
        s++;
    }
}
//###################################################################### 
#####

int main(void)
{
   uint16_t adcval=0;
   char s[17];

   uart_init();
   uart_string( "Messung gestartet:" );
   uart_string( "\n\r" );


while(1)
{

}

  return 0;

}

[\c]

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.