Forum: Mikrocontroller und Digitale Elektronik UART Daten Salat mit fleury lib


von Dani (Gast)


Lesenswert?

Hallo Zusammen,

Ich habe ein kleines Programm, das über UART eine Anfrage schickt und 
diese Empfangen soll, klappt auch soweit, zu mindest mit den einzelnen 
Bytes.

Mein UART Slave schickt die daten so: 
0x06,0x00,0x02,0x43,0x34,0x31,0x33,0x03
(0x06 ACK, 0x02 = STX , 0x03 = ETX, etc)

Die einzelne Ausgabe funktioniert auf UART1 da kann ich alles lesen, 
sobald ich aber die Daten in einen Buffer schreibe, kommt auf dem UART1 
aus dem Buffer nur müll und wirre zeichen.

Die While-Schleife wird korrekt beendet, da alle Zeichen empfangen und 
ausgegeben werden.

Aber ich möchte meine Empfangenen Daten in einem String haben und weiter 
verarbeiten können, was so nicht funktioniert. In diesem Falle sind die 
Daten einfach nur Zahlen.

Ist das denn so überhaupt korrekt?
1
#define F_CPU 8000000UL
2
#define UART_BAUD_RATE  9600
3
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <avr/sleep.h>
9
10
init_usart0(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
11
init_usart1(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
12
#define CR "\r\n"
13
14
unsigned const char *hexDigits = "0123456789ABCDFEF";
15
16
int main(void)
17
{
18
  uart0_putc(STX);
19
  uart0_puts("0464");
20
  uart0_putc(ETX);
21
22
  unsigned int response;
23
  char Buffer[32];
24
  
25
  while(1)
26
  {
27
    response = uart0_getc();
28
    
29
    if(response & UART_NO_DATA)
30
    {} 
31
    else 
32
    {
33
      Buffer[count] = (unsigned char)response;
34
      uart1_putc((unsigned char) response);
35
36
      if(response == ETX)
37
      break;
38
    }
39
  }
40
  
41
  uart1_puts("Empfangen"CR);
42
  uart1_puts(Buffer);
43
}


Grüße,
Daniel

von Peter II (Gast)


Lesenswert?

Wo kommt count her?

von Dani (Gast)


Lesenswert?

Peter II schrieb:
> Wo kommt count her?


Hallo,

Steht im Code drin, copy@paste hat es verschluckt, hab die Kommentare 
entfernt.
1
uint8_t count=0;

In der Main und
1
count++;

Unter Buffer[count]

Kanns leider via Handy nicht ändern :(

von Udo S. (urschmitt)


Lesenswert?

Dani schrieb:
> Kanns leider via Handy nicht ändern :(

Programmierst du auch via Handy?

von Karl H. (kbuchegg)


Lesenswert?

Dani schrieb:

> In der Main und
>
>
1
> count++;
2
>

Das wär die nächste Frage gewesen: und wo wird count erhöht.

Es macht relativ wenig Spass, wenn du nicht den Code postest, der 
tatsächlich läuft. Denn dann suchen wir nicht existente Fehler.

Hast du auch aus deinen Charactern einen String gemacht, indem du noch 
ein '\0' anhängst? Oder ist das auch wieder in deinem richtigen Code 
enthalten und nur hier im Forum sehen wir das nicht?

von Eric B. (beric)


Lesenswert?

Ja, wenn die gelesene Daten mit 0x06,0x00,0x02 anfangen wirst du nicht 
viel sehen da:

1) 0x00 den auszugebenen String terminiert
2) 0x06 und 0x02 non-printable ASCII sind.

von Dani (Gast)


Lesenswert?

Hallo,

Sorry, dafür das die hälfte gefehlt hat. (Wenn man es mal eilig hat)...
1
#define F_CPU 8000000UL
2
#define UART_BAUD_RATE  9600
3
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <avr/sleep.h>
9
10
init_usart0(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
11
init_usart1(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
12
13
#define CR "\r\n"
14
15
unsigned const char *hexDigits = "0123456789ABCDFEF";
16
17
int main(void)
18
{
19
  uart0_putc(STX);
20
  uart0_puts("0464");
21
  uart0_putc(ETX);
22
23
  unsigned int response;
24
  char Buffer[32];
25
  int count = 0;
26
 
27
  while(1)
28
  {
29
    response = uart0_getc();
30
    
31
    if(response & UART_NO_DATA)
32
    {} 
33
    else 
34
    {
35
      Buffer[count] = (unsigned char)response;
36
      uart1_putc((unsigned char) response);
37
      count++;
38
      
39
      if(response == ETX)
40
         break;
41
    }
42
  }
43
  
44
  uart1_puts("Empfangen"CR);
45
  uart1_puts(Buffer);
46
}

Das ist mein ganzer Code den ich habe, nein die Daten kommen so wie Sie 
mir von der Fleury übergeben werden in den Buffer, da ich in meinen 
Daten ein NULL Charakter habe, ist der denn nötig um den Buffer zu 
füllen?

Ich möchte mir ja nur den Buffer als ganzes ausgeben, anstatt in Bytes..

Grüße,
Daniel

von Dani (Gast)


Lesenswert?

Eric B. schrieb:
> Ja, wenn die gelesene Daten mit 0x06,0x00,0x02 anfangen wirst du
> nicht viel sehen da:
>
> 1) 0x00 den auszugebenen String terminiert
> 2) 0x06 und 0x02 non-printable ASCII sind.

Jupp ist mir klar, die sehe ich lediglich im hTerm und im Logic Analyzer 
:-)

Aber da sind ja auch Zahlen wie auch printable ASCII Codes drin

von Dani (Gast)


Lesenswert?

Hier mal ein Beispiel:

00 02 38 32 32 38 30 30 30 30 30 30 46 34 03
-> <NUL><STX>8228000000F4<ETX>

von Georg G. (df2au)


Lesenswert?

Was passiert mit count nach 32 Zeichen? Es wird nur einmal am 
Programmanfang mit 0 initialisiert. Wäre es nicht sinnvoller, das nach 
dem Senden von buffer erneut zu machen? So zeigt buffer[count] sehr 
schnell ins Nirwana.

von Dani (Gast)


Lesenswert?

Georg G. schrieb:
> Was passiert mit count nach 32 Zeichen? Es wird nur einmal am
> Programmanfang mit 0 initialisiert. Wäre es nicht sinnvoller, das nach
> dem Senden von buffer erneut zu machen? So zeigt buffer[count] sehr
> schnell ins Nirwana.

Hallo,

Ja ist schon klar das es sinnvoller ist, Problem ist aber das im Buffer 
nur Mist steht, der Counter bleibt immer unter 32, da die Länge nicht 
größer wie 16 Bytes wird und nur einmal aktuell zum test gesendet wird. 
Aber ich ändere das gleich im Code :-)

von Georg G. (df2au)


Lesenswert?

Mach doch (wie von Eric bereits gesagt) noch kleine Änderungen:

IST
Buffer[count] = (unsigned char)response;

WIRD
Buffer[count] = (unsigned char)(response & 0xff);

Dann bist du sicher, dass der "Flag Anteil" von response sauber 
abgetrennt wurde.

IST
> if(response == ETX)
>          break;

WIRD
if(response == ETX) {
           buffer[count] = 0x00;
           break;
           }

Dann hat uart_puts() ein sauberes String Ende.

Und zeig doch mal, was du als Ausgabe bekommst. Ist die Ausgabe immer 
die gleiche?

von Dani (Gast)


Lesenswert?

Hallo,

So habe den Code jetzt wie folgt geändert:
1
#define F_CPU 8000000UL
2
#define UART_BAUD_RATE  9600
3
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <avr/sleep.h>
9
10
11
12
#define STX 0x02
13
#define ETX 0x03
14
15
int main(void)
16
{
17
        init_usart0(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
18
        init_usart1(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
19
20
  uart0_putc(STX);
21
  uart0_puts("0464");
22
  uart0_putc(ETX);
23
24
  unsigned int response;
25
  char Buffer[32];
26
  
27
  int count = 0;
28
  
29
  while(1)
30
  {
31
    response = uart0_getc();
32
    
33
    if(response & UART_NO_DATA)
34
    {} 
35
    else 
36
    {
37
      Buffer[count] = (unsigned char)(response & 0xFF);
38
      //uart1_putc((unsigned char) response);
39
      count++;
40
41
      if(response == ETX)
42
      {
43
        count = 0;
44
        Buffer[count] = 0x00;
45
        break;
46
      }
47
    }
48
  }
49
  
50
  uart1_puts("Empfangen"CR);
51
  uart1_puts(Buffer);
52
}
53
54
void uart1_putc(unsigned char data)
55
{
56
  unsigned char temphead;
57
  
58
  temphead = (UART1_TxHead +1 ) & UART_TX_BUFFER_MASK;
59
  
60
  while (temphead == UART1_TxTail){}
61
  ;
62
  
63
  UART1_TxBuf[temphead] = data;
64
  UART1_TxHead = temphead;
65
  
66
  // Enable TX Interrupt
67
  UCSR1B |= _BV(UDRIE1);
68
}
69
70
unsigned int uart0_getc(void)
71
{
72
  unsigned char tmptail;
73
  unsigned char data;
74
  
75
  if(UART_RxHead == UART_RxTail)
76
    return UART_NO_DATA;
77
    
78
  tmptail = (UART_RxTail +1) & UART_RX_BUFFER_MASK;
79
  UART_RxTail = tmptail;
80
  
81
  data = UART_RxBuf[tmptail];
82
  return (UART_LastRxError << 8) + data;
83
}

So, mein hTerm sagt mir folgendes:
45 6D 70 66 61 6E 67 65 6E 0D 0A =>  Empfangen<\r><\n>

Mit NICHT auskommentiertem (uart1_putc((unsigned char) response)):
00 02 43 34 31 33 34 30 33 35 34 32 30 44 03 => <\0><2>C4134035420D<3>

Sobald es aber aus dem Buffer kommen soll, kommt mit dem Code jetzt 
aktuell nichts mehr...

von Dani (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal der Mitschnitt von UART Slave zu Atmega

von Dani (Gast)


Lesenswert?

Hallo,

So bin etwas weiter gekommen, habe nun ein bischen hin und her debuggt, 
das Problem an der Ausgabe des Buffers liegt wohl an dieser Funktion:
1
void uart1_puts(const char *s)
2
{
3
  while(*s)
4
    uart1_putc(*s++);
5
}

Wenn ich anstatt uart1_puts(Buffer); / uart1_putc(Buffer[3]) ausführe, 
kriege ich ein C in Putty.

Dann fiel mir beim durch steppen auf, das in der puts funktion 
uart1_putc niemals erreicht wird.

grübel

von holger (Gast)


Lesenswert?

>Dann fiel mir beim durch steppen auf, das in der puts funktion
>uart1_putc niemals erreicht wird.

Buffer selber plattgemacht würde ich da mal behaupten;)

      if(response == ETX)
      {
        count = 0;
        Buffer[count] = 0x00;

von Karl H. (kbuchegg)


Lesenswert?

Dani schrieb:
> Hallo,
>
> So bin etwas weiter gekommen, habe nun ein bischen hin und her debuggt,
> das Problem an der Ausgabe des Buffers liegt wohl an dieser Funktion:

Nope. Das Problem liegt in deinem Code bzw. darin, dass du etwas 
versuchst als String anzusehen, was kein String ist.

> *grübel*

Anstatt zu grübeln solltest du vielleicht erst mal die C Grundlagen 
lernen. Insbesondere wie Strings in C funktionieren. Sobald in deinen 
Datenbytes ein Byte mit dem Wert 0x00 vorkommt, kannst du das nicht mehr 
als String ansehen. Denn genau diese 0x00 bedeuten in einem String: hier 
ist der Text zu Ende.

Wenn das also die empfangenen Bytes sind:
1
00 02 43 34 31 33 34 30 33 35 34 32 30 44 03

dann ist für uart_puts der 'String' bereits hier
1
00 02 43 34 31 33 34 30 33 35 34 32 30 44 03
2
 ^
3
 |
4
 |

zu Ende. Den hier findet sich der Bytewert, der in einem String das 
Textende kennzeichnet. Selbst wenn du dir hier
1
      if(response == ETX)
2
      {
3
        count = 0;
4
        Buffer[count] = 0x00;
5
        break;
nicht selbst mutwillig deinen String zerstört hättest, würde trotzdem 
das erste Byte im Buffer immer noch ein '\0' (mit dem COde 0x00) sein 
und damit dort der String zu Ende sein.

Deine ganze Auswertung ist so ziemlicher Mist. WEnn die Daten mit einem 
Byte von 0x02 anfangen, dann wird alles vor diesem 0x02 ignoriert. Und 
das 0x02 brauchst du auch nicht speichern. Deine Empfangsroutine muss 
also zuallererst mal einen Status haben: Bin ich gerade beim EMpfang 
einer Antwort oder bin ich das nicht. Der Übergang von 'nicht' auf 
'Nachricht wird empfangen, Bytes müssen gespeichert werden' erfolgt 
genau dadurch, dass ein 0x02 aus der UART rauskommt. Erst dann wird 
alles nachfolgende gespeichert. Alles vorhergehende ist dagegen 
uninteressant.

Die Fleury Funktionen können da genau gar nichts dafür, wie nicht anders 
zu erwarten war. Dieses Nicht-Funktionieren ist schon auf deinem Mist 
gewachsen.

von Georg G. (df2au)


Lesenswert?

Versuch es doch mal so:

(ganz oben einfügen "int i;")

 if(response == ETX)
       {
         for (i = 0; i < count; i++) {
             uart_putc(Buffer[i]);
             }
         uart1_puts("Empfangen"CR);
         count = 0;
         break;
       }
     }
   }
 }

von Eric B. (beric)


Lesenswert?

probier mal das
1
#define INIT 0
2
#define RECEIVING 1
3
#define FINISHED 2
4
5
int main()
6
{
7
   unsigned int response;
8
   char Buffer[32];
9
   int count = 0;
10
   int rcv_state = INIT;
11
   
12
   /* Init UARTS */
13
   init_usart0(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
14
   init_usart1(UART_BAUD_SELECT (UART_BAUD_RATE, F_CPU));
15
16
   /* Send */
17
   uart0_putc(STX);
18
   uart0_puts("0464");
19
   uart0_putc(ETX);
20
21
   /* Receive */
22
   do {
23
      response = uart0_getc();
24
      
25
      if (!(response & UART_NO_DATA))
26
      {
27
         response &= 0xFF;
28
         
29
         switch(response)
30
         {
31
            case STX:
32
               rcv_state = RECEIVING;
33
               break;
34
            
35
            case ETX:
36
               rcv_state = FINISHED;
37
               break;
38
            
39
            default:
40
               if(rcv_state == RECEIVING)
41
               {
42
                  Buffer[count] = response;
43
                  count++;
44
                  if(count > 31) rcv_state = FINISHED;
45
               }
46
               break;
47
         }
48
      }
49
   } while (rcv_state != FINISHED);
50
51
   /* Print received data */
52
   uart1_puts("Received:")
53
   for(count = 0; count < 32; count ++)
54
   {
55
      uart1_putc(' ');
56
      uart1_putc("0123456789ABCDEF"[(Buffer[count] >> 4) & 0x0F]);
57
      uart1_putc("0123456789ABCEDF"[(Buffer[count]     ) & 0x0F]);
58
   }
59
   uart1_puts("\n");
60
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Deine ganze Auswertung ist so ziemlicher Mist.
Nicht nur das. Bevor wir es vergessen: für einen uC sollte die 
Hauptschleife niemals ein Ende haben. Was sollte er denn nach Ablauf 
des Programms machen?

@Dani
Ich weiß, was er macht. Aber weißt du es auch?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.