mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik string an den PC via Hyperterminal senden, nur zwei Zeichen!


Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matze schrieb:
> Hallo zusammen,

...
> 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?
...

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

Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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").

Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Deine schnelle Hilfe!

Viele Grüße, Matthias.

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christian S. (kruemel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

#define F_CPU 4000000
#include <avr/io.h>
#include <util/delay.h>

 
#define BAUD 9600UL      // 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)
{
 
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
   
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1

unsigned char s[] = "HalloWelt"; 
unsigned int i;  
   
   
for (i=0;i<9; i++)
{
    while (!(UCSRA & (1<<UDRE)))
  {
  }
  UDR=s[i];             
}

    return 0;
}


Gruß
Christian

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
   while ( !(UCSRA & (1<<UDRE)) )     // <- hier ist der Ausdruck, der
                                      // die Schleife steuert

      ;                               // hier ist die davon abhängige Anweisung

ob du das dann so schreibst
   while ( !(UCSRA & (1<<UDRE)) )     // <- hier ist der Ausdruck, der
                                      // die Schleife steuert

   {                                  // der abhängige Teil ist jetzt ein
                                      // ein Codeblock, der hier halt zufällig
                                      // leer ist
   }

oder so
   while ( !(UCSRA & (1<<UDRE)) )     // <- hier ist der Ausdruck, der
                                      // die Schleife steuert
                                      
   {                                  // hier beginnt der Codeblock, der
                                      // vom while abhängt
 
     ;                                // und aus einer leeren Anweisung besteht

   }                                  // 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!

Autor: Christian S. (kruemel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

#define F_CPU 4000000
#include <avr/io.h>
#include <util/delay.h>

 
#define BAUD 9600UL      // 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 

////////////////////////////////////////////////////////////////
// UART initialisieren
//
void uart_init()
{
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
   
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1
}

////////////////////////////////////////////////////////////////
// ein einzelnes Zeichen ausgeben
//
void uart_putc( char c )
{
  while (!(UCSRA & (1<<UDRE)))
  {
  }
  UDR = c;       
}

////////////////////////////////////////////////////////////////
// Einen String ausgeben
//
void uart_puts( const char * s )
{
  while( *s )
    uart_putc( *s++ );
}

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

  uart_putc( 'X' );

  while( 1 )
  {
    uart_puts( "Hallo Welt\r\n" );
    _delay_ms( 100 );
  }
}


Steht alles so schön modularisiert im Tutorial.
Die 4Mhz stimmen?

Autor: Christian S. (kruemel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define F_CPU 4000000
#include <avr/io.h>
#include <util/delay.h>

 
#define BAUD 9600UL      // 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)
{
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
   
   
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1
   
   
while( 1 ) {
while (!(UCSRA & (1<<UDRE)))           /* warten bis Senden moeglich */
{
}

UDR = 'X';
_delay_ms(500);

} 
}

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

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.