Forum: Mikrocontroller und Digitale Elektronik ATMEGA162 - UART will nicht...


von Sanchez (Gast)


Lesenswert?

Hallo miteinander!

Also ich hab irgendwie ein echtes Problem mit meinen UART... Wie im 
Betreff erwähnt benutze ich einen ATMEGA162 mit dem ich jetzt versuche, 
das Uart-Programm aus dem Tutorial zum laufen zu bringen... Hier mein 
Assembler-Programm:

.include "m162def.inc"

.def temp = r16
.equ CLOCK = 8000000
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1

        ; Stackpointer initialisieren
        ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

        ; Baudrate einstellen
        ldi temp, LOW(UBRRVAL)
        out UBRR1L, temp
        ldi temp, HIGH(UBRRVAL)
        out UBRR1H, temp

        ; Frame-Format: 8 Bit
        ldi temp, (1<<URSEL)|(3<<UCSZ0)
        out UCSR1C, temp

        sbi UCSR1B,TXEN1                    ; TX aktivieren

loop:   ldi temp, 'T'
        rcall serout                      ; Unterprogramm aufrufen
        ldi temp, 'e'
        rcall serout                      ; Unterprogramm aufrufen
        ldi temp, 's'
        rcall serout                      ; ...
        ldi temp, 't'
        rcall serout
        ldi temp, '!'
        rcall serout
        ldi temp, 10
        rcall serout
        ldi temp, 13
        rcall serout
        rjmp end

serout:
        sbis UCSR1A,UDRE1                   ; Warten bis UDR für das 
nächste
                                          ; Byte bereit ist
        rjmp serout
        out UDR1, temp
        ret                               ; zurück zum Hauptprogramm
end:    rjmp end


Eine Anmerkung zu der verwendeten Taktfrequenz: hab mal die 
Einstellungen, die im µC vorprogrammiert waren gelassen (siehe Anhang). 
Laut Datenblattangebe des Herstellers läuft der µC bei diesen 
Einstellungen mit einer internen Taktfrequenz von 8 MHz. Irgendwo hier 
im Forum hab ich aber mal gelesen, dass alle Mega's von Werk ab auf 1 
MHz laufen. Hab beides probiert... ES LÄUFT NICHT!!!

8 MHz:  Hyperterminal empfängt ÇÇÇÇÇÇÇÇÇÇÇÇÇÇ
1 MHz:  Hyperterminal empfängt willkürlich 7 Zeichen

Wieso, hab ich KEINE AHNUNG!!! Das Kabel hab ich auch mal getestet (PIN2 
+ 3 zusammen). Läuft Einwandfrei! Sorry, bin noch Anfänger... Für 
schnelle Hilfe wär ich super Dankbar!

Gruß Waldemar

von Waldemar T. (sanchez251)


Angehängte Dateien:

Lesenswert?

Sorry, die datei wurde irgenwie nicht hochgeladen... Ich hoffe jetzt 
gehts...

von Magnus Müller (Gast)


Lesenswert?

Der interne Oszillator deines mega162 läuft zwar auf 8MHz, aber durch 
die gesetzte CLKDIV8 Fuse wird der Takt intern nochmal durch 8 geteilt. 
Resultat: 1MHz Takt für CPU und synchrone Peripherie.

Gruß,
Magnetus

von Waldemar T. (sanchez251)


Lesenswert?

Mhh, komisch laut Datenblatt ergibt die Einstellung (CKSEL3) 0010 
(CKSEL0) einen devision Faktor von 4. Bei 16 MHz Maximalfreqenz sind das 
4 MHz. Durch 8 ergeben das dann 500 kHz. Oder lieg ich da falsch? Um 
Standartmäßige 4 MHz zu bekommen muss ich demnach CKDIV8 ausmachen.

Hier ist mal ein Link zum datenblatt des Mega162:

http://pdf1.alldatasheet.com/datasheet-pdf/view/80272/ATMEL/ATMEGA162.html

Die Daten von denen ich spreche befinden sich auf seite 37 und 40

Angenommen ich arbeite wirklich mit 1 MHz. Wieso zeigt er ir dann so 
einen Blödsinn an? Stimmt was mit meinem Programm nicht?

von Waldemar T. (sanchez251)


Lesenswert?

OK, hab mich mal eben durch die letzten Threads in diesem Forum 
gewühlt... Im Beitrag "Fusebits bei Quarz" von wulf hieß es, dass bei 
Uart-Anwendungen der interne Oszillator nicht genau genug ist.. Stimmt 
das? Wie soll ich dann meinen Mega162 fusen, damit ich 'nen normal 4MHz 
Quarz zwischen XTAL1 und XTAL2 hängen kann? (Hab zwar noch 2 Mega162 da, 
aber der eine ist vielleich schon geschrottet :( Muss gucken ob ich den 
noch retten kann... Deshalb probier ich mal lieber nicht einfach so 
drauf los...)

von Waldemar T. (sanchez251)


Lesenswert?

OK, bemüht euch nicht weiter... hab einfach noch ein bissl im Datenblatt 
recherchiert und bin auch nach ein wenig probieren auf die richtige 
einstellung und beschaltung gekommen... Uart läuft! Und es geht wirklich 
nur mit einem externen Quarz!

Tread beendet... Danke nochmal an magnetus!

von Metaller (Gast)


Lesenswert?

Ich lasse meinen Mega8 mit internen 8MHz problemlos mit 38,4k 
übertragen. Warum sollte das bei Dir nicht gehen? Deine Fuse sind auch 
richtig eingestellt und der Takt wird nicht, wie oben gesagt wurde, 
nochmal durch 8 geteilt.


Hier meine Ini für das URAT im Mega8 (38,4k):

URAT_INIT:
.equ CLOCK = 8000000
.equ BAUD = 38400
.equ UBRRVAL = CLOCK/(BAUD*16)-1
; Baudrate einstellen
  ldi r16, LOW(UBRRVAL)
  out UBRRL, r16
  ldi r16, HIGH(UBRRVAL)
  out UBRRH, r16
; Frame-Format: 8 Bit
  ldi r16, (1<<URSEL)|(3<<UCSZ0)
  out UCSRC, r16
  sbi UCSRB,TXEN    ; TX aktivieren
ret


Hier meine Ini für das URAT im Mega128 (115,2k):

USART0_Init:
  ldi temp, 0
  sts UBRR0H, temp
  ldi temp, 7
  out UBRR0L, temp

  ldi temp, 0b00011000
  out UCSR0B,temp

  ldi temp, 0b00000110
  sts UCSR0C,temp
ret



Die Sequenz "ldi temp, (1<<URSEL)|(3<<UCSZ0)" funktioniert bei meinem 
128er nicht, daher habe ich es so gemacht "ldi temp, 0b00011000".

von Metaller (Gast)


Lesenswert?

Hmmm, da warst Du schneller als ich :)

von Waldemar T. (sanchez251)


Lesenswert?

Trotzdem Danke... Hab´es jedenfalls jetzt auf externen Takt eingestellt, 
wie ich es von anfang an geplant hatte, und funktioniert super. Ich 
hoffe, der Rest, den ich geplant hatte funktioniert auch noch, aber wenn 
nicht, weiß ich ja, wen ich löchern kann... ;-)

von Andi H. (leguan08)


Angehängte Dateien:

Lesenswert?

habe ein ähnliches Problem mit dem At Mega 162, bringt bei mir auch nur 
wilde Zeichen, habe einen externen 8 MHz Quarz und die Fuses wie im 
Anhang eingestellt.

Kannst Du mir Deine Fuses Einstellung mal sagen, wie Du es mit Deinem 
externen Quarz hinbekommen hast ?

Danke und Grüße,

Andi

von Waldemar T. (sanchez251)


Angehängte Dateien:

Lesenswert?

Grüß Dich Andi!

Sorry, dass ich erst jetzt antworte... Also im Anhang ist mal ein Bild 
meiner Fusebits, wobei die derzeitige Einstellung einem externen Quarz 
von 4 MHz entspricht. Außerdem arbeite ich mit yaap wo angekreuzte Bit 
bedeuten, dass sie nicht programmiert sind. Das ist bei dir nicht der 
Fall, wenn ich das richtig interpretiert hab.

Wichtig ist bei dir, dass du die Einstellung (CKSEL3) 1111 (CKSEL0) 
nimmst... Bei SUT1:0 nimmst du am besten die Einstellung 01.

Auf JEDEN Fall musst du CKDIV8 setzen, da sonst alles für die Katz ist, 
was du an CKSEL3..0 gemacht hast (Gesetzt bedeutet deaktiviert). 
Ansonsten stell alles so wie bei mir an, dann kann nichts schiefgehen 
(Merke: Verkehrte Logik!!!)

Ich hoffe, ich konnte die Helfen...

Gruß Waldemar

von Andi H. (leguan08)


Lesenswert?

Hallo Waldemar,

vielen Dank für deine Antwort, aber ich hab jetzt alle Varianten (Fuses 
und Baud Rates) durchprobiert und bekomme immer noch Müllzeichen.

Hab hier mal den Testcode angehängt, vielleicht ist hier ja der Hund 
begraben. Mit einem AT90S8515 funktionierts super.

Auch die Einzelzeichen Rückgabe aus einem Terminal funktioniert zum 
Teil, aber nur Buchstaben, keine Zahlen keine sonstigen Zeichen.

Villeicht fällt die ja was ein...

Danke und Grüße,

Andi

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>

#define F_CPU             8000000UL  // 8 MHz
#define BAUD            9600UL
#define UBRR_BAUD         ((F_CPU/(16*BAUD))-1)
#define USART_BUFFER_SIZE 8

void delay_ms(unsigned int millisekunden)
{
  int i;
  for (i=0;i<(millisekunden*10);i++)
    _delay_ms(1);
}

void uart_init(void)
{       // 1. UART
  UBRR0H = (unsigned char) (UBRR_BAUD>>8);
  UBRR0L = (unsigned char) UBRR_BAUD;
  // 2. UART
  UBRR1H = (unsigned char) (UBRR_BAUD>>8);
  UBRR1L = (unsigned char) UBRR_BAUD;

  UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
  UCSR1B = (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1);

        UCSR0A = 0x00;
        UCSR1A = 0x00;

  // 8 N 1
  UCSR0C = (1<<URSEL0)|(1<<UCSZ10)|(1<<UCSZ00);
  UCSR1C = (1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ01);

  // Interrupts aktivieren
  sei();
}

// einzelnes Zeichen Senden
void usart_putc(char zeichen)
{
  while ( !(UCSR0A & (1<<UDRE0)) ); // Wait untill USART data register 
is empty
    UDR0 = zeichen; // Transmit data
}

// ganzen String senden
void usart_puts(char *data)
{
  int len, count;

  len = strlen(data);
  for (count = 0; count < len; count++)
    {
      usart_putc(*(data+count));
      _delay_ms(10);
    }
}

SIGNAL(SIG_USART0_RECV) // Eingang über RS232
{
  unsigned char buffer;

  // Daten aus dem Puffer lesen ...
  buffer = UDR0;

  // AVR warten bis der RS232 Sendebuffer leer ist ...
  while ( !( UCSR0A & _BV(UDRE0)) )
          ;
  // ... und gleich wieder zurück zum RS232 schicken
  usart_putc(buffer);

  // AVR warten bis der RS485 Sendebuffer leer ist ...
  while ( !( UCSR1A & _BV(UDRE1)) )
    ;
}

int main(void)
{
  // USART initialisieren
  uart_init();

  while (1)
    {
            usart_puts("2 Das ist der erste Test der RS232 Ausgabe");
            delay_ms(4000);
          }
}

von Waldemar T. (sanchez251)


Lesenswert?

Hey andi!

Leider muss ich dich enttäuschen... Hab noch nie ein µC-Programm in C 
geschrieben. Bis jetzt hab ich mich nur auf der Assembler-Schiene 
gehalten. Vielleicht kann dir ein anderer hier aus dem Forum helfen, was 
das Programm angeht. Evtl. könntest du mal die Fusebit-Einstellung in 
yaap programmieren und dann direkt von dem was ich dir gesagt hab 
ableiten. So wäre zumindest diese Möglichkeit ausgeschlossen.

Ansonsten solltest du mal das Datenblatt zwischen 35 und 40 
durchstöbern. Kann man bei www.alldatasheet.com als Vollversion 
downloaden. Vielleicht findest du ja was, was ich übersehen hab.

MfG Waldemar

von Andi H. (leguan08)


Lesenswert?

Hallo Waldemar,

trotzdem vielen Dank, an den Fuse Bits kann es jetzt wohl nicht mehr 
liegen, da habe ich alles ausprobiert. Habe sie auch, wie du beschrieben 
hast, mit yaap geschrieben, aber von den Grundeinstellungen waren sie 
schon so wie ich sie vorher gesetzt hatte.

Aber vielleicht findet ja ein AVRGCC Guru hier aus dem Forum den Fehler.

Gruß,

Andi

von Andi H. (leguan08)


Lesenswert?

Hallo Waldemar,

hab den Fehler gefunden, mit den Fuses hat alles gepasst, nur mit dem 
initialisieren der Uarts habe ich einen Fehler gemacht:

statt:

// 8 N 1
  UCSR0C = (1<<URSEL0)|(1<<UCSZ10)|(1<<UCSZ00);
  UCSR1C = (1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ01);

muß es so heißen:

// 8 N 1
UCSR0C = (1<<URSEL0)|(1<<UCSZ01)|(1<<UCSZ00);
UCSR1C = (1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ10);

dann funktionierts problemlos.

Trotzdem nochmals vielen Dank,

Gruß,

Andi

von Waldemar T. (sanchez251)


Lesenswert?

Super! Tolles Gefühl, wenn man etwas zum laufen bringt, gell? :) Also 
viel spaß noch beim basteln...

Gruß Waldemar

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.