Mega8 UART funktioniert nicht

Gast #877059
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');
  }
}
Gast #877062
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
#877137
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.
Gast #877138
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....
Gast #877165
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]

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren