Forum: Mikrocontroller und Digitale Elektronik Protokoll über Uart


von Peter (Gast)


Lesenswert?

Hallo Zusammen!

Trotz langem probieren und noch viel längerem Suchen wende ich mich an 
euch und erbitte eure Hilfe.

Ich sende von einem Arduino Board an einen Atmega8 mittels Uart Char und 
zwar in folgender Form:


Startbyte (Ascii 50)
Datenlänge (Ascii 51-60)
ID-Byte (Ascii 61 bis 99)
Datenbyte 1 (Ascii 100 bis 200)
Datenbyte 2 (Ascii 100 bis 200)
Datenbyte 3 (Ascii 100 bis 200)
....
Datenbyte n (Ascii 100 bis 200)
Checksum (noch nicht implementiert --> Ascii 0)
Endbyte (Ascii 250)

Vom Arduino wird in Abständen von ca. 100ms gesendet.

Ziel ist es, Basierend auf dem ID Byte verschiedene Daten zu senden. ID 
61 sollte z.B. ADC Informationen des Arduinos übertragen, die dann vom 
ATmega8 verarbeitetet werden. Der ATmega8 sendet NIE an das Arduino 
Board zurück.

Ich verwende die Uart Routine von Peter Fleury.

Ich hab mir das abarbeiten der Daten am µC wie folgt vorgestellt:
- Auslesen aus dem Ringbuffer so lange, bis ein Startbyte erhalten wird.
- Dann die Datenlänge, ID Byte und die Datenbytes in ein Array 
schreiben.
- Warten bis das Endbyte kommt.
- Befehl verarbeiten.

In meinen Programm sieht das wie folgt aus (bist jetzt ist nur das 
Schreiben auf ein LCD Display mit der Befehl ID 51 eingeführt)
1
#ifndef F_CPU
2
#define F_CPU 7372800UL
3
#endif
4
5
#ifndef UART_BAUD_RATE
6
#define UART_BAUD_RATE 4800
7
#endif
8
9
#include <stdlib.h>
10
#include <avr/io.h>
11
#include <util/delay.h>
12
#include <avr/interrupt.h>
13
#include <avr/pgmspace.h>
14
#include "lcd-routines.h"
15
#include "uart.h"
16
17
const unsigned int cell_MAG_output = 9;
18
const unsigned int cell_MOT_output = 9;
19
const unsigned int cell_PELT_output = 7;
20
const unsigned int cell_MOT2_output = 17;
21
const unsigned int cell_T_Ist_output = 16;
22
const unsigned int cell_pump_output = 17;
23
24
const unsigned int Uart_STX =50;
25
const unsigned int Uart_ID = 51;
26
const unsigned int Uart_ETX = 254;
27
const unsigned int Uart_ADC_offset = 100;
28
const unsigned int Uart_LEN_offset = 61;
29
30
void WriteLCD (int *val_array);
31
void GetSignal (int *val_array);
32
33
int main(void)
34
{
35
36
  int cmd_val[10];
37
  
38
  sei();      //Interrupts enabled
39
  lcd_init();
40
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
41
  lcd_string("Starte");
42
    while(1)
43
    {  
44
    GetSignal(cmd_val);
45
46
    WriteLCD(cmd_val);
47
    }
48
49
}

Also, mit der Funktion GetSignal(int *val_array) möchte ich den 
Ringbuffer nach einer gesendeten Befehlskette überprüfen.
1
void GetSignal (int *val_array) {
2
  unsigned int c;
3
  unsigned int counter = 0;
4
    
5
    //Suchen nach StartByte
6
    do 
7
    {
8
      c = uart_getc();
9
    } while (c != Uart_STX);
10
    
11
    lcd_string("Start gefunden");
12
13
    //Informations Bytes einholen
14
    counter = 0;
15
16
    do 
17
    {
18
      c = uart_getc();
19
      val_array[counter] = c;
20
      counter ++;
21
    } while (c != Uart_ETX);
22
    lcd_string("Ende");     //DIESER PUNKT WIRD NIE ERREICHT
23
24
}

Das Problem: Ich komme aus der 2ten Schleife (c != Uart_ETX) nie mehr 
heraus! Ich hab schon mit nem LogicAnalyser überprüft, ob das Endbyte 
kommt. Und es wird wirklich gesendet.

Ich finde Einfach den Fehler nicht!
Ihr seid meine letzte Hoffnung, bevor ich noch durchdreh :)

Vielen Dank im Voraus!
lg Peter

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

>       c = uart_getc();

Sieh dir bitte das Beispiel an, welches P. Fleury seinen UART Routinen 
beigelegt hat.
In a Nutshell: Du kannst nicht einfach hergehen und den Returnwert von 
uart_getc() so direkt verwenden!

uart_getc() wartet nicht, bis ein Zeichen auf der UART vorliegt. Wenn 
nichts da ist, dann kommt uart_getc() sofort zurück und meldet 
pflichtbewusst: Ich hab nichts.

Du jedoch gehst in deinem Code her und ignorierst das. Du tust so, als 
ob du jedesmal wenn uart_getc() zurückkommt ein Zeichen hättest.

Und da du dieses machst, bügelst du dir hier

>       val_array[counter] = c;
>       counter ++;

in weiterer Folge den Speicher nieder. Irgendeinen Speicher. Speicher, 
den du nicht niederbügeln dürftest, der nicht zu deiner Variablen 
gehört.

Ab dem Zeitpunkt werden dann keine Wetten mehr angenommon, was in deinem 
Programm alles passiert oder nicht passiert. Wenn dein fehlerhaftes 
Programm aktiv den Speicher sabotiert, sind alle Wetten sinnlos. Alles 
kann passieren.


> bevor ich noch durchdreh

Nicht durchdrehen!
Statt dessen die Funktionsdoku lesen und das beigelegte Beispiel 
studieren!

von Amateur (Gast)


Lesenswert?

@Peter

>Checksum (noch nicht implementiert --> Ascii 0)

...ist das Wirklich sinnvoll, wenn der Empfänger sowieso nicht 
antwortet?

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.