mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART/USART Echo


Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe hier eine Anfängerfrage. Ich wollte über Terminal etwas(zb. 
'k') schicken und das gleich zurück bekommen. Kann mir jemand einen Tipp 
geben was ich ändern soll und/oder wo der Fehler ist.

Danke
[#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
//Usart
#define Baud 9600UL
#define UBRR_Val ((F_CPU/(16*Baud))-1)  


void Usart_Init(void);
void Usart_Transmit (void);
unsigned char Usart_Receive (void);


unsigned char data;
int main()
{
//Ausgang
DDRD|=(1<<PD1);
//Eingang
DDRD&=~(1<<PD0);
Usart_Init();
unsigned char data;

while(1)
{
Usart_Transmit();
Usart_Receive();
}
return 0;
}


//Usart
void Usart_Init(void)
{
//Baudrate einstellen
UBRR0H=(UBRR_Val>>8);
UBRR0L=UBRR_Val;
//Frame-Format:8 Bit Nutzsignal
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
//Sender und Eampfenger initialisieren
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
}


void Usart_Transmit (void)
{
//Daten senden
while (!(UCSR0A & (1<<UDRE0)));
UDR0=data;
}


unsigned char Usart_Receive (void)
{
//Daten empfangen
//Solange nichts ankommt, soll er nichts machen
while (!(UCSR0A & (1<<RXC0))); 
return UDR0;
}
 

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark schrieb:
> void Usart_Transmit (void)
> {
> //Daten senden
> while (!(UCSR0A & (1<<UDRE0)));
> UDR0=data;
> }
Es wäre sicher sinnvoll, der Sendefunktion auch das Zeichen zu 
übergeben, das gesendet werden soll - z.B. so:
void Usart_Transmit (unsigned char data)
{
//Daten senden
while (!(UCSR0A & (1<<UDRE0)));
UDR0=data;
}
Die nächste gute Idee ist es, das Zeichen, das die Empfangsfunktion 
liefert, auch zu benutzen:
while (1) {
 Usart_Transmit(Usart_Receive());
}
Wenn du stattdessen die globale Variable data benutzen willst, musst du 
sie zumindest mit dem return Wert von Usart_Receive füllen und dann 
deine alte Usart_Transmit aufzurufen.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn du stattdessen die globale Variable data benutzen willst, musst du
> sie zumindest mit dem return Wert von Usart_Receive füllen und dann
> deine alte Usart_Transmit aufzurufen.

meinst du so
while(1)
{

data=Usart_Receive();
Usart_Transmit();
}
return 0;
}

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Data würde ich nicht global machen sondern als Argument für Transmit

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark schrieb:
> meinst du so

Jo. Wenn du schon die Sache mit dem Argument nicht machen willst, dann 
eben so.

Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also ich sitze den ganzen Tag an dem Code. Es funktioniet leider nicht 
und ich finde den Fehler nicht. Ich wollte jetzt ASCII '1','2' und '3' 
senden und am Terminal empfangen. Anstatt die Hex-Werte 31, 32 und 33 zu 
erhalten, bekomme ich die Hex-Werte 67 ,B3, 06.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
//Usart
#define Baud 9600UL
#define UBRR_Val ((F_CPU/(16*Baud))-1) 

void Usart_Init(void);
void Usart_Transmit (unsigned char data_tx);
unsigned char Usart_Receive (void);

unsigned char data=0;
int main()
{
//Ausgang
DDRD|=(1<<PD1);
//Eingang
DDRD&=~(1<<PD0);
Usart_Init();
//unsigned char data;
while(1)
{
Usart_Transmit('1');
Usart_Transmit('2');
Usart_Transmit('3');
//Usart_Transmit(Usart_Receive());
_delay_ms(5000);
//
}
return 0;
}
//-----------------------------------
//Usart
void Usart_Init(void)
{
//Baudrate einstellen
UBRR0H=(unsigned char)(UBRR_Val>>8);
UBRR0L=(unsigned char)UBRR_Val;
//Frame-Format:8 Bit Nutzsignal
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
//Sender und Eampfenger initialisieren
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
}
//---------------------------------

void Usart_Transmit (unsigned char data_tx)
{
//Daten senden
//wurde vorherige Byte erfolgreich gesendet wurde und ob der UDR Puffer leer ist
while (!(UCSR0A & (1<<UDRE0)));
//sende Byte
UDR0=data_tx;
}
//------------------------------------
unsigned char Usart_Receive (void)
{
unsigned char data_Rx;
//Ein Zeichen (1Byte) ist über die seielle Schnittstelle in Usart angekommen
while (!(UCSR0A & (1<<RXC0))); 
//Zeichen wird ausgelesen
data_Rx= UDR0;
return data_Rx;
}


Danke Danke

Autor: Bastian Werner (jackfrost)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du ein Arduinoboard oder nur den nackten uC ? Wenn du nur den uC 
hast passen die Fuses ?

Gruß Jackfrost

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark schrieb:
> Anstatt die Hex-Werte 31, 32 und 33 zu
> erhalten, bekomme ich die Hex-Werte 67 ,B3, 06

Sowas ist zu 99% ein Problem mit der Taktfrequenz, denn das Programm 
sollte so klappen. Also checke die Fuses (ext. High Frequency Crystal 
wäre hier richtig) - nicht den internen RC Oszillator, denn der läuft 
mit 8MHz.

Du kannst auch mal direkt 0d103 in UBRR0L schreiben (UBRR0H bleibt auf 
null), das sollte auch die 9600 bit/s ergeben. Stelle auf jeden Fall 
sicher, das auch der Host auf 9600 Baud steht.
Wenn du aus Versehen mit dem internen Oszillator arbeitest, sollte es 
bei UBRR0L = 0d51 laufen.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Mark schrieb:
>> Anstatt die Hex-Werte 31, 32 und 33 zu
>> erhalten, bekomme ich die Hex-Werte 67 ,B3, 06
>
> Sowas ist zu 99% ein Problem mit der Taktfrequenz, denn das Programm
> sollte so klappen. Also checke die Fuses (ext. High Frequency Crystal
> wäre hier richtig) - nicht den internen RC Oszillator, denn der läuft
> mit 8MHz.
>
> Du kannst auch mal direkt 0d103 in UBRR0L schreiben (UBRR0H bleibt auf
> null), das sollte auch die 9600 bit/s ergeben. Stelle auf jeden Fall
> sicher, das auch der Host auf 9600 Baud steht.
> Wenn du aus Versehen mit dem internen Oszillator arbeitest, sollte es
> bei UBRR0L = 0d51 laufen.

Also ich verwende Arduino Uno. Sorry für die Frage (ich bin ein 
Anfänger), aber ich verstehe nicht was mit dem Fuses gemeint ist. Wie 
soll ich die Fuses checken?

VG

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark schrieb:
> Wie
> soll ich die Fuses checken?

Gegenfrage: Wie programmierst du den Uno denn? Wenn du da einen ISP 
Programmer benutzt, kann der auch Fuses auslesen. Wenn du den Arduino 
Bootlaoder nimmst, dann geht das nicht.
Der Uno ist normalerweise aber schon richtig auf den 16MHz Quarz 
gefused, so das du da nicht ran musst.
// illuminate the Uno/Duemilanove LED for exactly 1 second
DDRB |= (1<<PB5);
PORTB |= (1 << PB5);
_delay_ms(1000);
PORTB &= ~(1<<PB5);
Zum Test der Frequenz sollte mit obigem Beispiel die LED auf dem Board 
für genau 1 Sekunde leuchten.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich programmiere in AVR Studio 4 und benutze den AVRISP mkII. Tut mir 
leid, ich meinte eigentlich Arduino nano (Atmega328).

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Programmieradapter kann Fuses auslesen und verändern. Lies sie aus 
und poste einen Screenshot.

Autor: Mark (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Stefan U. schrieb:
> Dein Programmieradapter kann Fuses auslesen und verändern. Lies
> sie aus
> und poste einen Screenshot.

Hier ein Bild.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da du den Mikrocontroller über ISP programmierst (nicht über Bootloader) 
sollte die BOOTRST Fuse aus sein.

In deinem Fall ist sie an, das bewirkt, dass dein Mikrocontroller 
irgendeinen unbekannten Code ausführt, bevor dein eigentliches Programm 
gestartet wird. Und dieser Code bewirkt möglicherweise die Fehlfunktion.

Die anderen Fuses sehen Ok aus.

Eine kleine Erklärung zu Fuses: Betrachte sie als 
Konfigurationsparameter, die vor dem Programmstart aktiviert werden und 
nicht Bestandteil des Programmes (*.hex Datei) sind. Quasi so wie Jumper 
auf einer PC Komponente.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:

>
> Du kannst auch mal direkt 0d103 in UBRR0L schreiben (UBRR0H bleibt auf
> null), das sollte auch die 9600 bit/s ergeben.

Der Wert 103 ist doch ein Dezimal-Wert. Warum 0x103?

Autor: Mark (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Stefan U. schrieb:
> Da du den Mikrocontroller über ISP programmierst (nicht über
> Bootloader)
> sollte die BOOTRST Fuse aus sein.

Den hacken am BOOTRST ist jetzt weg, BOOTRST ist also aus. Zudem habe 
ich den Programmteil umgeschrieben gemäß:
void Usart_Init(void)
{
//Baudrate einstellen
UBRR0H=0x00;
UBRR0L=103;

//Frame-Format:8 Bit Nutzsignal
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
//Sender und Eampfenger initialisieren
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
}

Damit hat sich leider das Problem nicht gelöst. Wie im Bild zusehen ist, 
erhalte ich immer noch die falschen Hex-Werte.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreibe das Programm mal so um, dass es einfach fortlaufend 'A' Sendet, 
mit einigen hundert Millisekunden Pause zwischen jedem Buchstaben. 
Kommen dann am PC 'A' an, oder was anderes?.

: Bearbeitet durch User
Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark schrieb:
>> Du kannst auch mal direkt 0d103 in UBRR0L schreiben (UBRR0H bleibt auf
>> null), das sollte auch die 9600 bit/s ergeben.
>
> Der Wert 103 ist doch ein Dezimal-Wert. Warum 0x103?

Nicht 0x103 - ich habe doch extra 0d103 geschrieben, damit es klar wird, 
das es dezimal ist. 0x103 würde doch auch in ein 8-bit Register gar 
nicht reinpassen.
103 ist einfach der ausgerechnete Wert für Baudrate 9600 bei 16MHz Takt.

Ok, klappt trotzdem nicht. Beschreib uns doch mal, wie du TX des AVR mit 
RX des PCs verbindest und was da für Hardware dazwischen ist.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:

> Ok, klappt trotzdem nicht. Beschreib uns doch mal, wie du TX des AVR mit
> RX des PCs verbindest und was da für Hardware dazwischen ist.

ok, danke. Mein MC ist über den DELOCK Adapter USB Seriell 1x9 Pin mit 
dem PC verbunden.

Autor: Mark (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Pin 2 (RxD) ist mit Pin PD1 des Contollers und Pin 3 (TxD) ist mit Pin 
PD0 (Rxd) des Controllers verbunden.

Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan U. schrieb:
> Schreibe das Programm mal so um, dass es einfach fortlaufend 'A'
> Sendet,
> mit einigen hundert Millisekunden Pause zwischen jedem Buchstaben.
> Kommen dann am PC 'A' an, oder was anderes?.

Ich bin deinem Rat gefolgt. Ich habe die while-Schleife geändert. Ich 
bekomme anstatt 0x41 den Hex-Wert 5F.
while(1)
{
Usart_Transmit('A');
_delay_ms(100);
}

Autor: Werner P. (wpfundstein)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ein USB RS232 Adapter. Den kannst Du nicht verwenden und dich 
freuen wenn dein µC keinen Schaden genommen hat.

Du brauchst einen USB UART TTL Adapter.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner P. schrieb:
> Du brauchst einen USB UART TTL Adapter.

Nö, braucht er nicht, der ist auf dem Nano in Form eines FT232RL schon 
drauf. Und die genannten Pins (PD0/PD1) hängen da auch schon dran. Er 
braucht ein stinknormales USB-Kabel.

Autor: Werner P. (wpfundstein)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie ich ihn verstanden habe verbindet er die µC Pins direkt. Und dann 
hat er mit seinem RS232 Adapter ein Problem.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner P. schrieb:
> So wie ich ihn verstanden habe verbindet er die µC Pins direkt.
> Und dann hat er mit seinem RS232 Adapter ein Problem.

Das hab ich nicht bestritten.

Nur was soll er mit zwei USB UART TTL Adaptern, die auch noch an den 
gleichen Pins hängen? Man könnte natürlich die entsprechenden 
Widerstände vom Board kratzen und den Onboard Chip damit totlegen.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TE nur zur Erklärung:
1. ist dein Adapter auf einen Pegelbereich von etwa -10V bis +10V am TX 
und RX Anschluss gedacht und
2. ist die Polarität der RS232 Signale genau anders rum als bei UART am 
MC.

Das kann also nicht gehen. Entweder nimmst du das USB Interface, das 
schon auf dem Uno drauf ist, wie o.a. oder du besorgt dir besagtes 
USB-TTL Adapter.

: Bearbeitet durch User
Autor: Mark (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner P. schrieb:
> Das ist ein USB RS232 Adapter. Den kannst Du nicht verwenden und
> dich
> freuen wenn dein µC keinen Schaden genommen hat.
>
> Du brauchst einen USB UART TTL Adapter.

Hallo Leute ihr habt vollkommen recht. Es liegt tatsächlich an dem 
Adapter. Ich hatte irgendwo noch einen USB UART TTL Adapter. Diesen habe 
ich jetzt angeschlossen und dazu die Treiber-Software runtergeladen. Und 
es funktionert jetzt.. Danke dass ihr euch die Zeit genommen habt und 
mir geholfen habt.

VG

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.