UART übergabe eines #defines

Gast #3263990
Lesenswert?

Im Header File
1
#define val   "PF10301*25\r\n"


Aufruf im Main
1
USART_TRANSMIT(val);



Funktion
1
void USART_TRANSMIT(char* adr)
2
{
3
  for(int i=0; i<sizeof(adr);i++)
4
  {
5
  
6
  while ( !( UCSR0A & (1<<UDRE0)) );
7
  
8
  UDR0 = adr[i];    
9
  }
10

11
}

Am PC gibt er mir aber leider nur die ersten beiden Characters aus.
Was is falsch?
#3264009
Lesenswert?

Nachzulesen in jedem noch so grindigem C-Buch, im Kapitel über 
Stringverarbeitung, bzw. schon vorher im Kapitel über Arrays:

Eine Funktion kann die Größe eines ihr übergebenen Arrays nicht 
feststellen!

Das betrifft alle Strings insofern, als eine Funktion die Länge des 
Strings nicht am Pointer festmachen kann, sondern auf andere Hilfen 
angewiesen ist. Genau aus diesem Grund gibt es in C die Konvention, das 
alle Strings mit einem \0 Character enden. Und es gibt spezielle 
String-Funktionen, die genau dieses wissen und ihre Operation darauf 
abstimmen.

zb. die Funktion strlen() welche, die tatsächliche Länge eines Strings 
fetsstellt.


Das war die ultra-ultra-ultra Kurzform. Dein C-Buch hat noch viele 
Seiten mehr über diesen Umstand und die Zusammenhänge zu berichten.
Was? Du hast kein C-Buch?  - Selber schuld. Kauf dir eines.
#3264016
Lesenswert?

Und nein.
Ein #define wird nicht 'übergeben'

Ein #define macht eine Textersetzung. Ob du da schreibst
USART_TRANSMIT(val);

oder ob du schreibst
USART_TRANSMIT("PF10301*25\r\n");

ist Jacke wie Hose, weil der Präprozessor sowieso aus der ersten Form 
durch die angeordnete Textersetzung die 2.te Form macht, ehe dann der 
C-Compiler zum Zug kommt.

Auch hier wieder: nachzulesen in jedem noch so grindigem C-Buch.
#3264018
Lesenswert?

qwer schrieb:
> Jop, einfach blamabel.

Allerdings.
Denn die Frage nach der Stringlänge stellt sich gar nicht
1
void USART_TRANSMIT_CHAR( char c )
2
{
3
  while ( !( UCSR0A & (1<<UDRE0)) )
4
    ;
5
  UDR0 = c;    
6
}
7

8
void USART_TRANSMIT(char* adr)
9
{
10
  while( *adr != '\0' )
11
    USART_TRANSMIT_CHAR( *adr++ );
12
}

So schreibt man das. Kein Mensch benötigt dazu die tatsächliche 
Stringlänge in Zahlenform.
Und als Nebeneffekt fällt dann auch noch eine Funktion ab, die einzelne 
Character ausgeben kann.
Gast #3270054
Lesenswert?

Hallo,

ich habe ein ähnliches Problem. Mit dem Unterschied, dass ich gerne 
mehrere Byte empfangen würde.

Hätte es so probiert:
1
unsigned char USART1_RECEIVE()
2
{
3
  UDR1 = 0xFF;
4
  int i=0;
5
  
6
  while( *UDR1 != '\0' )
7
    
8
    {
9
      while ( !(UCSR1A & (1<<RXC1)) )
10
      {;}
11
      BUFFER[i]=UDR1;
12
      i++;
13
    }
14
  
15
  return BUFFER;
16
  
17
}

Leider kommt folgende Fehlermeldung und ich weiß nicht mehr weiter

Error  1  invalid type argument of unary '*' (have 'int')
Warning  2  return makes integer from pointer without a cast [enabled by 
default]

Grüße
Gast #3270092
Lesenswert?

Hanno schrieb:
> Dann so?
> unsigned char USART1_RECEIVE()

nein, die ließt ohne zu warten das erste zeichen ein.

warum nicht so?


[c]
do {
  while ( !(UCSR1A & (1<<RXC1)) );

  BUFFER=UDR1;
  if ( BUFFER == 0 ) {
     break;
  }
  BUFFER++;
} while( auf maximal länge prüfen! )

  return BUFFER;
Gast #3270096
Lesenswert?

Nachtrag:

1
char* pos = BUFFER;
2
do {
3
  while ( !(UCSR1A & (1<<RXC1)) );
4

5
  pos = UDR1;
6
  if ( BUFFER == 0 ) {
7
     break;
8
  }
9
  pos++;
10
} while( auf maximal länge prüfen! )
11

12
  return BUFFER;

aber sauber ist das noch lange nicht, denn es macht wenig sinn eine 
globale variable als return zu übergeben. Besser ist es der funktion 
selber buffer als Paramter zu übergeben und auch die maximale länge.
#3270097
Lesenswert?

Hanno schrieb:
> Dann so?

schon ein bischen besser

> unsigned char USART1_RECEIVE()
> {
>   BUFFER = 0xFF;

warum willst du da BUFFER etwas zuweisen? Und vor allen Dingen: warum 
0xFF;
Du hast doch noch gar kein Zeichen, welches du im Buffer speichern 
könntest.

Ausserdem ist BUFFER ein Array. D.h. es besteht (bei dir) aus 128 
einzelnen Variablen, die alle denselben Namen tragen, nämlich Buffer, 
und nur durch den Arrayindex unterschieden werden.

Welche dieser 128 'Variablen' ist denn gemeint, wenn du einfach nur 
BUFFER schreibst?

>   while( *BUFFER != '\0' )

Das ist zwar im C-Sinne nicht ganz falsch, aber ich bin recht sicher, 
dass es nicht das ist was du haben willst. (Soll heissen: syntaktisch 
ist das korrekt. Aber laut Duden ist "Das U-Boot frisiert das Mondlicht" 
auch korrektes Deutsch. Selbst wenn der Satz keinen Sinn ergibt)

Wieder: BUFFER, das sind 128 Variablen!

Ausserdem: wie kannst du denn prüfen, ob BUFFER (egal welches) den Wert 
\0 hat? Einer der 128 BUFFER Variablen wurde ja noch gar nichts 
zugewiesen!

>   BUFFER=UDR1;

BUFFER ist ein Array!

>     {
>       while ( !(UCSR1A & (1<<RXC1)) )
>       {;}

Öhm.
Diese Schleife hier wartet darauf, dass ein Zeichen an der UART 
hereinkommt. D.h. du hast hier die Reihenfolge genau verkehrt rum

Du musst ZUERST darauf warten, dass du ein Zeichen bekommst, und erst 
DANN kannst du dir dieses Zeichen aus UDR1 abholen.

>       BUFFER++;

BUffer ist ein Array. Das kannst du nicht inkrementieren!
Gast #3270778
Lesenswert?

1
unsigned char USART1_RECEIVE()
2
{
3
  int i=0;
4
  while ( !(UCSR1A & (1<<RXC1)) )      /* Warte auf Daten am RX */
5
    {
6
      while( *UDR1 != '\0' )      /* Prüfe ob Ende des Strings erreicht */
7
      {;}
8
      if(i>128){break;}        /*Pufferüberlauf vorbeugen*/
9
      BUFFER[i]=UDR1;          /*Daten im Puffer ablegen*/
10
      i++;              
11
    }
12

13
  //return BUFFER;  Muss ich ja nicht returnen, weil ich so drauf zugreifen kann oder?
14
}
15
  
16
}

So müssts dann passen oder?
Gast #3270785
Lesenswert?

Mir fällt gerade ein, ich wollte ja mehrere Bytes einlesen können.

So wie grad geschrieben geht das ja nicht.

Ich lese jetzt ein, solange der Buffer nicht voll ist und solange kein 
'\0' empfangen wurde. Hoffe ich jedenfalls.
1
/* Es werden solange Bytes eingelesen, bis '\0' empfangen wurde*/
2

3

4
unsigned char USART1_RECEIVE()
5
{
6
  int i=0;
7
  BUFFER[0]=1;
8
  while( BUFFER[i] != '\0' && i<128)        /* Prüfe ob Ende des Strings erreicht */  /*Pufferüberlauf vorbeugen*/
9
  {
10
      while ( !(UCSR1A & (1<<RXC1)) )      /* Warte auf Daten am RX */
11
      {;}
12
      BUFFER[i]=UDR1;              /*Daten im Puffer ablegen*/
13
      i++;
14
  }
15
}
Gast #3270808
Lesenswert?

aber jetzt
1
/* Es werden solange Bytes eingelesen, bis '\0' empfangen wurde*/
2

3

4
unsigned char USART1_RECEIVE()
5
{
6
  int i=0;                  /*Laufvariable initialisieren*/
7
  do 
8
  {      
9
    while ( !(UCSR1A & (1<<RXC1)) )      /* Warte auf Daten am RX */
10
    {;}
11
    BUFFER[i]=UDR1;              /*Daten im Puffer ablegen*/
12
    i++;                  /*Laufvariable inkrementieren*/
13
  }  while (BUFFER[i] != '\0' && i<128);    /* Prüfe ob Ende des Strings erreicht */  /*Pufferüberlauf vorbeugen*/
14
  
15
  return *BUFFER;    
16
}
Gast #3270827
Lesenswert?

Hanno schrieb:
> Wie gebe ich den ganzen Vektor zurück?

warum verwendest du überhaupt ein unsigned char und kein char?
1
unsigned char* USART1_RECEIVE()
2
{
3
   return BUFFER;
4
}

Warum willst du überhaupt eine globale Variabel zurückgeben, diese 
kannst du eh von überall aus nutzen?
#3270863
Lesenswert?

1
char USART1_get_char()
2
{
3
  while ( !(UCSR1A & (1<<RXC1)) )
4
  {;}
5

6
  return UDR1;
7
}
8

9
void USART1_get_string()
10
{
11
  uint8_t i=0;
12
  char c;
13

14
  do 
15
  {      
16
    c = USART1_get_char();
17
    BUFFER[i] = c;
18
    i++;
19
  }  while ( c != '\0' && i < sizeof(BUFFER));
20

21
  BUFFER[i-1] = '\0'; // sicherheitshalber, falls des Empfangene zu lang ist
22
}


(Deine Kommentare hab ich rausgeworfen, weil es sich um sinnlose 
Kommentare handelt. Ein Kommentar, der nur den C-Code in deutscher 
Schreibweise wiedergibt, ist sinnlos. Die Funktionen sind so kurz und so 
leicht zu durchschauen - da ist der Code sein eigener Kommentar)
Der Code erzählt mir das WIE, ein Kommentar erzählt mir das WARUM.

PS: Bist du sicher, dass der Sender einen String mit einem \0 zeichen 
abschliesst und das dann auch so über die UART schickt? Es ist zwar 
grundsätzlich möglich, aber reichlich ungewöhnlich.

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