Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfänger Problem mit der UART (RS232) zwischen PC und ATMega8
Schmidtbot
05.02.2012, 20:57
Hallo,
ich hab ein Problem mit der UART-Schnittstelle.
Wenn ich mit HTERM auf die Schnittstelle schau kommen nur "0x00" an das dafür in rauhen mengen.
Die Baudrate ist auf 38400 eingestellt.
Ich selbst seh leider keinen fehler in diesen Quellcode.
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 36864
#define Baud 38400
void uart_init(void)
{
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
UBRRL=0x05; // Baudrate festlegen
UBRRH=0X0b; // Baudrate festlegen
}
int uart_send(unsigned char c)
{
while (!(UCSRA & (1<<UDRE)))
{
// mach nichts
}
//senden
UDR=c;
return 0;
}
void uart_write(char *s)
{
while(*s)
{
uart_send(*s);
s++;
}
}
int main(void)
{
uart_init();
while(1==1)
{
uart_write("test\0");
}
}
Ich möchte die Schnittstelle für Debugzwecke verwenden. Aber dazu muss ich erst einmal etwas ausgeben können :-(
Besten Dank schon einmal für euere Zeit
radbruch
05.02.2012, 21:09
Sollte es nicht eher #define F_CPU 3686400UL lauten?
Ein 3,6864MHz-Quarz hat bei nahezu allen Baudraten keinen Abweichungsfehler.
Wie kommst du denn darauf?
UBRRL=0x05; // Baudrate festlegen
UBRRH=0X0b; // Baudrate festlegen
Schmidtbot
05.02.2012, 21:22
Diese Werte hab ich von hier: http://www.gjlay.de/helferlein/avr-uart-rechner.html
Die Sache mit der Frequenz hab ich angepasst:
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 3686400UL
#define Baud 38400
void uart_init(void)
{
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
UBRRL=0x05; // Baudrate festlegen
UBRRH=0xb; // Baudrate festlegen
}
Schmidtbot
05.02.2012, 21:46
Was ich vielleich vergessen habe zu sagen, ist dass es sich durch die veränderung nichts an dem Ergebniss geändert hat.
Welche Taktquelle ist denn bei den Fuses festgelegt ? Läuft das Ding eventuell mit dem internen RC-Oszillator?
Probier mal :
void uart_init(void)
{
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
UBRRL=0x05; // Baudrate festlegen
UBRRH=0x00; // Baudrate festlegen
}
Die zweite Spalte ist nur für U2X also double Speed.
Ich habe mir gerade mal das Datenblatt angeschaut:
http://pdf1.alldatasheet.com/datasheet-pdf/view/80247/ATMEL/ATMEGA8.html
Wenn du auf Seite 157 schaust hast du ja eine Tabelle wie du das UBRR Register beschreiben musst, wenn du eine bestimmte Baudrate haben willst.
Bei deinem Quarztakt und deiner Baudrate musst du das Register mit 5 beschreiben (wenn du das U2X Bit auf 0 lässt).
Das heißt du musst nur schreiben:
UBRRL=0x05;
UBRRH=0x00;
und nicht:
UBRRL=0x05; // Baudrate festlegen
UBRRH=0xb; // Baudrate festlegen
Edit: Da war jemand ein paar Sekunden schneller ;)
Jap, wie ich eben schon schrieb. ;)
Schmidtbot
06.02.2012, 19:50
Besten Dank jetzt funktioniert es :-) aber dafür hab ich jetzt die nächste Frage:
Wieso empfang in nach dem Strings immer 4 mal 0xff, bevor das Linefeed kommt?
Hört sich nach konstantem String ( also char buffer[20] ) an, wo der nicht voll ist bzw.
void uart_write(char *s){
while(*s)
{
uart_send(*s);
s++;
}
}
Endet bei \0 und wenn er den nicht findet geht er bis zum Schluss durch.
Schmidtbot
07.02.2012, 16:31
Besten Dank nun funktioniert auch das richtig.
Jetzt hätte ich aber noch 2 Fragen :-) komm mir schon langsam unverschämt vor euch so zu löchern.
1: Was bedeutet genau [20] und muss ich das auch ändern?
2: Wenn ich ein LF stetzen will kann ich doch mit HTerm auf die \0 triggern, so dass hterm einen neuen Zeile beginnt. Doch leider funktioniert das bei mir nicht mein Favorit war ja bei HTerm auf "New line at Null " stelle doch irgendwie geht das bei keiner opiton richtig.
Das [20] bei char[20] definiert die Länge eines Arrays vom Typ char.
\0 ist nur das Null-Zeichen aus dem ASCII-Standard. Das wird benutzt um das Ende eines String (Zeichenkette) oder eines Arrays ( auch eine Zeichenkette wenn vom Typ char) zu erkennen.
Sprich irgendwann hat man sich darauf geeinigt, dass \0 die Zeichenfolge abschließt. Was aber nicht automatisch heisst, dass eine Zeile auch beendet wird. Das macht man je nach System mit einer Variation von \r oder \n, also Linefeed und Carriage-Return.
Versuch doch mal mittels deiner uart Funktion das Folgende :
uart_write ("Hallo\r\n") und stell bei hterm als Zeilenende CR+LF ein.
Schmidtbot
07.02.2012, 18:16
Genau so hab ich es auch im Tutorial gelesen mit \r \n.
Aber leider funktioniert es nicht. Ich hab jetzt eine Delay von 1 sec mit ein gebaut, dass ich es besser sehen kann. Das Funktioniert einwandfrei.
Nur eben das Linefeed nicht.
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 3686400UL
#include <util/delay.h>
#define Baud 38400
#define CR "\0\r\n"
void uart_init(void)
{
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
UBRRL=0x05; // Baudrate festlegen
UBRRH=0x00; // Baudrate festlegen
}
int uart_send(unsigned char c)
{
while (!(UCSRA & (1<<UDRE)))
{
// mach nichts
}
//senden
UDR=c;
return 0;
}
void uart_write(char *s)
{
while(*s)
{
uart_send(*s);
s++;
}
}
int main(void)
{
uart_init();
while(1==1)
{
uart_write("Das ist ein Test" CR);
_delay_ms(1000);
}
}
Nicht
uart_write("Das ist ein Test" CR);
sondern :
uart_write("Das ist ein Test\r\n");
Das #define CR "\0\r\n" zusammen mit zeichenkette+zeichenkette geht in die Hose. Da du letzendlich versuchst eine Adresse mit einer Konstanten zu addieren.
Schmidtbot
07.02.2012, 18:33
Perfekt jetzt funktioniert auch das. Besten Dank!!!
Wieso kann ich mir jetzt eigentlich das \0 sparren?
Wie gesagt, das schließt die Zeichenfolge ab. Wenn du eine Zeichenfolge mittels char[xy] definierst, passiert das automatisch.
StewieGriffin
24.11.2014, 20:17
Hallo,
ich habe diesen Code auf meinem ATmega8 ausprobiert und nutze dabei das "Debug Terminal" unter Windows 7.
Das Terminal zeigt mir auch im Abstand von 1 Sekunde immer neue Zeichen an, allerdings nur in Hex, Binär, Dec und etwas nicht lesbares in ASCII.
Meine Baudrate habe ich auf 9600 geändert, mein Quarz hat 8MHz. Ich erwartet eigentlich den Text "Das ist ein Test" in meinem Terminal.
Liege ich damit falsch oder ist noch etwas mehr dabei zu beachten?
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#define Baud 9600
void uart_init(void)
{
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
UBRRL=0x05; // Baudrate festlegen
UBRRH=0x00; // Baudrate festlegen
}
int uart_send(unsigned char c)
{
while (!(UCSRA & (1<<UDRE)))
{
// mach nichts
}
//senden
UDR=c;
return 0;
}
void uart_write(char *s)
{
while(*s)
{
uart_send(*s);
s++;
}
}
int main(void)
{
uart_init();
while(1==1)
{
uart_write("Das ist ein Test\r\n");
_delay_ms(1000);
}
}
Mit freundlichen Grüßen,
Stewie Griffin
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.