string an den PC via Hyperterminal senden, nur zwei Zeichen!

Gast #1815977
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;
}
Persönliche Seite #1815997
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.
Persönliche Seite #1816014
Lesenswert?

Matze schrieb:
> Hallo zusammen,

...
1
> for (i=0;i<9; i++)
2
>   {
3
>   //while (!(UCSRA & (1<<UDRE)))  //warten bis senden möglich, wenn das
4
> aktiviert wird, sendet er gar nicht
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
Gast #1816021
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.
Gast #1816027
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.
Gast #1816038
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").
Gast #1816050
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
#1882372
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?

1
#define F_CPU 4000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4

5
 
6
#define BAUD 9600UL      // Baudrate
7
 
8
// Berechnungen
9

10
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
11
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
12
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
13
 
14
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
15
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
16
#endif 
17

18

19
int main(void)
20
{
21
 
22
   UBRRH = UBRR_VAL >> 8;
23
   UBRRL = UBRR_VAL & 0xFF;
24
   
25
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
26
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1
27

28
unsigned char s[] = "HalloWelt"; 
29
unsigned int i;  
30
   
31
   
32
for (i=0;i<9; i++)
33
{
34
    while (!(UCSRA & (1<<UDRE)))
35
  {
36
  }
37
  UDR=s[i];             
38
}
39

40
    return 0;
41
}


Gruß
Christian
#1882401
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.
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!
#1882431
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
#1882436
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)

1
#define F_CPU 4000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4

5
 
6
#define BAUD 9600UL      // Baudrate
7
 
8
// Berechnungen
9

10
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
11
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
12
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
13
 
14
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
15
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
16
#endif 
17

18
////////////////////////////////////////////////////////////////
19
// UART initialisieren
20
//
21
void uart_init()
22
{
23
   UBRRH = UBRR_VAL >> 8;
24
   UBRRL = UBRR_VAL & 0xFF;
25
   
26
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
27
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1
28
}
29

30
////////////////////////////////////////////////////////////////
31
// ein einzelnes Zeichen ausgeben
32
//
33
void uart_putc( char c )
34
{
35
  while (!(UCSRA & (1<<UDRE)))
36
  {
37
  }
38
  UDR = c;       
39
}
40

41
////////////////////////////////////////////////////////////////
42
// Einen String ausgeben
43
//
44
void uart_puts( const char * s )
45
{
46
  while( *s )
47
    uart_putc( *s++ );
48
}
49

50
////////////////////////////////////////////////////////////////
51
int main(void)
52
{
53
  uart_init();
54

55
  uart_putc( 'X' );
56

57
  while( 1 )
58
  {
59
    uart_puts( "Hallo Welt\r\n" );
60
    _delay_ms( 100 );
61
  }
62
}


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

1
#define F_CPU 4000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4

5
 
6
#define BAUD 9600UL      // Baudrate
7
 
8
// Berechnungen
9

10
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
11
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
12
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
13
 
14
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
15
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
16
#endif 
17

18
int main(void)
19
{
20
   UBRRH = UBRR_VAL >> 8;
21
   UBRRL = UBRR_VAL & 0xFF;
22
   
23
   
24
   UCSRB = (1<<RXEN)|(1<<TXEN);            //UART TX einschalten
25
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);     //Asynchron 8N1
26
   
27
   
28
while( 1 ) {
29
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren