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
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
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?
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...)
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!
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".
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... ;-)
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
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
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);
}
}
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
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
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