Hallo zusammen,
könnt ihr mir bitte sagen warum nur die ersten beiden Zeichen meines
"HalloWelt" strings gesendet werden?
ich bin noch Anfänger in SAchen Mikrokontrollertechnik.
Vielen Dank für Eure Hilfe,
Matthias.
anbei mein Code
#include <avr/io.h>
// #include <util/delay.h> // wenn das aktiviert ist, dann sendet er
gar nichts, wißt ihr warum? brauche ich doch für delay funktionen,
nicht wahr?
#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt"
#define F_CPU 8000000UL
#endif
#define BAUD 4800UL // Baudrate
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 =
kein Fehler.
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu
hoch!
#endif
int main(void)
{
UCSRB |= (1<<TXEN);
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchron 8N1
UBRRH = UBRR_VAL >> 8;
UBRRL = UBRR_VAL & 0xFF;
unsigned char tab[] = "HalloWelt"; //Tabelle als String
unsigned int i;
for (i=0;i<9; i++)
{
//while (!(UCSRA & (1<<UDRE))) //warten bis senden möglich, wenn das
aktiviert wird, sendet er gar nicht
UDR=tab[i]; //sendet nur "Ha" warum?
//UDR=tab[5]; z.B. würde er senden,
wenn ich das direkt angebe, nur in der schleife nicht. :-(
}
return 0;
}
Du schreibst:
//while (!(UCSRA & (1<<UDRE))) //warten bis senden möglich, wenn das
aktiviert wird, sendet er gar nicht
Und da steckt der Fehler. Die Zeile muss rein, aber richtig, d.h. mit
einem Schleifenrumpf und zwar einem leeren. Ohne den wartet das while
nicht auf die sendebereite UART, sondern ballert blind und stur Zeichen
an die wahrscheinlich nach dem 2. Zeichen besetzte UART (Zeile
UDR=tab[i];). Schau dir den bewährten Code im Tutorial an.
>//while (!(UCSRA & (1<<UDRE))) //warten bis senden möglich, wenn das
4
>aktiviertwird,sendetergarnicht
5
>UDR=tab[i];//sendet nur "Ha" warum?
...
So schreibst Du ein neues Zeichen ins Schieberegister, bevor das alte
gesendet wurde.
Wenn Du "while (!(UCSRA & (1<<UDRE))) UDR=tab[i]; " benutzt, wird,
solange der Sender nicht frei ist ein Zeichen ins SR geschrieben. Daher
wird der TX auch nie frei...
Ich spende mal ein *;*: "while (!(UCSRA & (1<<UDRE)));" und schon sieht
alles besser aus. Für solche Sachen wird C geliebt ;-)
Falk
Hallo Stefan,
vielen Dank, dass Du mir geholfen hast! :-) Über Deine Hilfe bin ich
sehr froh. Jetzt kann ich weiter an diesem Problem arbeiten.
ich habe das schon solange probiert und es ging nie.
UCSRB |= (1<<TXEN);
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchron 8N1
UBRRH = UBRR_VAL >> 8; //diese beiden
UBRRL = UBRR_VAL & 0xFF;
Könntest Du mir vielleicht auch erklären wozu die letzten beiden Zeilen
sind?
Nur diese habe ich nicht richtig verstanden.
die oberen ja
das hat irgendetwas mit der Frequenzteilerberechnung zu tun meine ich.
Viele Grüße, Matthias.
Hallo Falk,
vielen Dank, dass Du mir geholfen hast! :-) Über Deine Hilfe bin ich
sehr froh. Jetzt kann ich weiter an diesem Problem arbeiten.
ich habe das schon solange probiert und es ging nie.
Es war nur ein einfaches ; :-)
Hast du eine Erklärung warum ich dieses nicht definieren darf?
#include <util/delay.h> ??
dann sendet er nämlich nur ein merkwürdiges Zeichen.
Ansonsten hätte ich hier noch eine Frage, wenn Du so nett wärst mir
diese auch zu beantworten.
UCSRB |= (1<<TXEN);
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchron 8N1
UBRRH = UBRR_VAL >> 8; //diese beiden unteren
UBRRL = UBRR_VAL & 0xFF;
Könntest Du mir vielleicht auch erklären wozu die letzten beiden Zeilen
sind?
Nur diese habe ich nicht richtig verstanden.
die oberen ja
das hat irgendetwas mit der Frequenzteilerberechnung zu tun meine ich.
Viele Grüße, Matthias.
Die stellen die Baudrate ein (Deine weiter oben definierten 4800Baud).
Die Formel, wie man aus Taktfrequenz und gewünschter Baudrate den
passsenden Wert für das UBRR Register errechnet, steht im Datenblatt.
Damit Du das nicht selber ausrechnen mußt, erledigen das ein paar Makros
beim Compilieren für Dich (die unter "// Berechnungen").
Matze schrieb:> Hast du eine Erklärung warum ich dieses nicht definieren darf?
delay.h benötigt einen Wert für F_CPU oder setzt einen
"Default-Wert" (glaube 3,xx MHz).
Der F_CPU - Wert geht in deine Berechnung ein, deine DEF mit
8 MHz wird übersprungen. Daher ist die Baudrate falsch
gesetzt.
=> erst deine Frequenz definieren dann delay.h einbinden
avr
Hallo,
möchte auch gerne Strings senden. Zeichen senden klappt nun mit Uart.
Habe hier jetzt auch mal das C Programm nachgebaut und das mit einer for
Schleife realisiert. Bei mir funktioniert es nicht.
Kommt nach meinem C Programmcode auch ein ; nach der while Schleife?
Würde ich das machen, würde doch nicht gewartet werden?
Christian S. schrieb:> möchte auch gerne Strings senden. Zeichen senden klappt nun mit Uart.
Du kannst also ein einzelnes Zeichen versenden?
> Habe hier jetzt auch mal das C Programm nachgebaut und das mit einer for> Schleife realisiert. Bei mir funktioniert es nicht.
Definiere bitte "funktioniert nicht".
Was genau funktioniert nicht? Sieht du was? Einzelne Zeichen? Falsche
Zeichen? Gar nichts?
>> Kommt nach meinem C Programmcode auch ein ; nach der while Schleife?> Würde ich das machen, würde doch nicht gewartet werden?
C-Buch!
Du brauchst eines! Ohne hat das wenig Sinn
while gehört zu den Compound Statemente, so wie auch if
Das bedeutet die Syntax lautet
"while" "(" Ausdruck ")"
Anweisung
Der erste Teil dürfte klar sein. Als ANweisung kann jede beliebige
Anweisung stehen. Das kann sein eine leere Anweisung, die mit einem
einzelnen ; geschrieben wird. Oder aber das können mehrere Anweisungen
sein, die als solche wieder in einen Block mittels { } verpackt werden.
Nun sagt allerdings niemand, dass ein Block zwingend aus mehreren
Anweisungen bestehen muss. Das kann auch nur eine Anweisung sein, das
kann aber auch gar keine Anweisung sein.
1
while(!(UCSRA&(1<<UDRE)))// <- hier ist der Ausdruck, der
2
// die Schleife steuert
3
4
;// hier ist die davon abhängige Anweisung
ob du das dann so schreibst
1
while(!(UCSRA&(1<<UDRE)))// <- hier ist der Ausdruck, der
2
// die Schleife steuert
3
4
{// der abhängige Teil ist jetzt ein
5
// ein Codeblock, der hier halt zufällig
6
// leer ist
7
}
oder so
1
while(!(UCSRA&(1<<UDRE)))// <- hier ist der Ausdruck, der
2
// die Schleife steuert
3
4
{// hier beginnt der Codeblock, der
5
// vom while abhängt
6
7
;// und aus einer leeren Anweisung besteht
8
9
}// und hier endet der Code Block
ist alles Jacke wie Hose. Entscheidend ist, das der vom while abhängige
Teil, der sog. Schleifenrumpf einfach nur leer ist. Egal wie man das
erreicht.
-> C-Buch!
Karl heinz Buchegger schrieb:> Du kannst also ein einzelnes Zeichen versenden?
Ja ich kann einzelne Zeichen versenden. Das funktioniert.
Karl heinz Buchegger schrieb:> Definiere bitte "funktioniert nicht".> Was genau funktioniert nicht? Sieht du was? Einzelne Zeichen? Falsche> Zeichen? Gar nichts?
Funktioniert nicht, heißt ich sehe am PC keine Zeichen, nichts.
Alles klar, es muss also eine leere Anweisung stehen, so wie auch beim
Senden von nur einem Zeichen. Steht ja bei mir auch im Quelltext. Mein
HalloWelt kommt aber trotzdem nicht an.
Viele Grüße
Christian
Christian S. schrieb:> Karl heinz Buchegger schrieb:>> Du kannst also ein einzelnes Zeichen versenden?>> Ja ich kann einzelne Zeichen versenden. Das funktioniert.
Gut.
Wie sieht das in Codeform aus?
>> Funktioniert nicht, heißt ich sehe am PC keine Zeichen, nichts.
Das ist ... unlogisch, Wengistens das erste 'H' müsstest du ja sehen, da
ja dein Einzelzeichenversenden funktioniert.
Modularisier doch mal ein wenig (und die for-Schleife ist auch Mist)
while(!(UCSRA&(1<<UDRE)))/* warten bis Senden moeglich */
30
{
31
}
32
33
UDR='X';
34
_delay_ms(500);
35
36
}
37
}
Das ist der Quellcode für ein Zeichen senden. Wie gesagt funktioniert.
Ich werde mir dann nochmal die put-Funktionen anschauen. Ich dachte das
es über die for-Schleife auch gehen sollte.
Danke für die Hilfe.
Viele Grüße
Christian