Forum: Compiler & IDEs ASM zu C (Taschenrechner) IV


von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

So ich hab jetzt mal ein paar kleine Fehler beseitigt. Den
Variablenspeicher hab ich erstmal kleiner gemacht...nur wenn ich jetzt
die Daten anfordere wird der Header ununterbrochen gesendet:


es hängt also hier:
1
    //wenn status SEND_HEADER
2
    if(State0 == SEND_HEADER) {
3
      
4
      //Summe zurücksetzen
5
      Summe0 = 0;
6
      for (i=0; i<50; i++) {
7
        
8
        //wenn i nciht gleich 11 oder 49 sende den Header
9
        if((i != 11) && (i != 49)) {
10
          Transmit0(SendHeader[i]);
11
          Summe0 = Summe0+SendHeader[i];
12
        //wenn i 11 ist sende den Variablennamen
13
        }else if(i==11) {
14
          Transmit0(VarName0);
15
          Summe0 = Summe0+VarName0;
16
        //wenn i 49 ist Checksumme berrechnen und senden
17
        }else if(i==49) {
18
          Checksumme0 = Bruteforce(Summe0);
19
          Transmit0(Checksumme0);
20
        }
21
      
22
      }
23
      
24
      //Summe zurücksetzen
25
      Summe0 = 0;
26
      
27
      //Status auf ACK1 setzen
28
      State0 = ACK1;
29
    
30
    }

Alter Thread:
Beitrag "UART Problem (Assembler zu C) III"

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dann stimmt vielleicht deine state machine nicht.

Du hast ja seit dem letzten Mal als ich in die Source reingesehen habe 
etliches geändert. Damals war es nur ein Empfangen seitens des µC und 
eine Senden seitens des Casio. Inzwischen bist du wohl schon beim Senden 
seitens des µC...

Vielleicht nimmst du dir die Zeit und skizzierst die state machine auf 
Papier (dann Einscannen) oder gleich in einer Grafik. Mit der Skizze ist 
es etwas einfacher sich reinzudenken, als mit einem Codeschnippsel.

von Flo S. (tuxianer)


Lesenswert?

ja das Empfangen scheint jetzt gut zu klappen nur das Senden eben nicht. 
Ich mals mal auf.

Vom Prinzip gehts Aber so:

Wenn 15 Empfangen: Sende 13

Header Empfangen

Wenn Stelle x im Header "R" ist -->State0=Request

warten bis 06 empfangen wurde -->State=Send_Header

Header Senden und an Stelle 12 Variablen Namen einfügen und an 50. 
Stelle Checksumme

und da hängts

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

So ich habe die Skizze von Karl Heinz mal erweitert.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ups. Das Diagramm kann ich mit dem PDF nicht nachvollziehen.

Mir fällt nur auf, dass du ab dem Codeteil hinter dem Kommentar 
"AUSWERTUNG0" nicht mehr mit der if...else Struktur arbeitest. Ich hätte 
das nach oben gezogen.

Der folgende Codeteil (und der entsprechende von ACK2 udn REQUEST) 
wartet entgegen dem Diagramm nicht auf ein 0x06. Hier wird sofort auf 
SEND_DATA umgestellt.
1
      //ACK1
2
      else if(State0 == ACK1) {
3
      
4
        //Nur die 0x06 aufnhemen!
5
      
6
        State0 = SEND_DATA;
7
        //WARTESCHLEIFE!!!!!!!
8
        _delay_ms(4.35);
9
      
10
      }

Deine Bruteforce() habe ich nicht geprüft, denn diesen Codeschnippsel 
kann man wesentlich straffer schreiben:
1
    //wenn status SEND_HEADER
2
    if(State0 == SEND_HEADER) 
3
    {
4
      unsigned char Summe0;        // falls oben abweichende Definition
5
      unsigned char Checksumme0;   // falls oben abweichende Definition
6
7
      Summe0 = 0;
8
      SendHeader[12-1] = VarName0; // kennen wir schon
9
10
      for (i=0; i<(50-1); i++)     // 49 Bytes, Checksumme später!
11
      {
12
         Transmit0(SendHeader[i]);
13
         Summe0 += SendHeader[i];
14
      }
15
16
      /*
17
       * Alle 50 Bytes des Headers inkl. des Checksumbytes 
18
       * addieren. Dann durch 256 dividieren. Der Rest dieser 
19
       * Division (Modulo in manchen Programmietsprachen)
20
       * muss 0x3A sein (aus GTRprotokoll.pdf)
21
       *
22
       * Addieren der ersten 49 Bytes s.o.
23
       * Division durch 256 implizit durch Typ unsigned char
24
       * 50.tes Byte (Checksumme) jetzt berechnen und senden
25
       */
26
      Checksumme0 = 0x3a;
27
      Checksumme0 -= Summe0;
28
      Transmit0(Checksumme0);
29
30
      //Status auf ACK1 setzen
31
      State0 = ACK1;
32
    }

von Flo S. (tuxianer)


Lesenswert?

hallo,
also ganz nach oben ziehen geht ja nicht, da der eine Teil ja nur 
ausgeführt wird, wenn ein byte empfangen wurde. Ich kann natürlich die 
ganzen Auswertung Algorithmen mittels if..else schreiben das ist sicher 
besser. ACK wartet doch gewissermaßen auf die 0x06. Die while läuft ja 
so lange leer, bis ein Zeichen empfangen wurde. Es kann nur ein 0x06 
kommen also muss das nur aufgenommen und nicht ausgewertet werden.

Und wiso deklarierst du die Variablen nochmal lokal da unten?

Die Stelle müsstest du mir nochmal erklären:
1
      Checksumme0 = 0x3a;
2
      Checksumme0 -= Summe0;
3
      Transmit0(Checksumme0);

Vielen Danke erstmal!

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so ich habs mal auch für Send_Data nach deinem Schema gemacht. Ich hoffe 
das klappt so. Mal ne andere Frage uint8_t ist das gleiche wie unsigned 
char oder?

von Flo S. (tuxianer)


Lesenswert?

ok ich habs nochmal getestet und es scheint alles korrekt abzulaufen nur 
bei den Daten wird eine 0 zuviel gesendet. Am Anfang da muss ich noch 
rausfinden, woran das liegt.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Florentin S. wrote:
> Und wieso deklarierst du die Variablen nochmal lokal da unten?

Ich war zu faul nachzusehen, wie die Variablen von dir definiert waren. 
Damit die Checksummenberechung von mir funktioniert, brauche ich 
unsigned char (d.h. 8-Bit vorzeichenlose) Variablen. Dadurch spare ich 
die Division durch 256.

> Die Stelle müsstest du mir nochmal erklären:
>
>       Checksumme0 = 0x3a;
>       Checksumme0 -= Summe0;
>       Transmit0(Checksumme0);

Die "Formel" kannst du leicht ableiten. Laut Doku soll gelten:

Summe (Bytes 1 bis 49) + Checksumme (Byte 50) = 0x3a

Also:

Checksumme (Byte 50) = 0x3a - Summe (Bytes 1 bis 49)

> Mal ne andere Frage uint8_t ist das gleiche wie unsigned char oder?

uint8_t ist ein typedef für unsigned char. Steht in einem Includefile 
drin (inttypes.h?)

Ich bin hoffnungslos veraltet und benutze meistens die alten, 
ursprünglichen Typen, damit ich zwischen verschiedenen Compilern nicht 
umswitchen muss. Besser für die Lesbarkeit und Portabilität ist es 
jedoch die neue Schreibweise zu verwenden.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Vielen Dank! Es läuft das Programm! Also auf die Formel bin ich noch gar 
nicht gekommen. Das kommt davon, wenn man sich nix auf Papier notiert. 
Also vielen Dank für alles! Im Anhang die lauffähige Version.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

mist einwas geht noch nicht. das ganze klappt nur für die Variable A. 
Bei B klappts nicht mehr.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du meinst einmal geht es und dann (bei der nächsten Variable) nicht 
mehr?

Dann stimmt wahrscheinlich was mit einer Initialisierung nicht.

Ich würde alle Variablen der state machine und die diversen Zähler, 
Hilfsvariablen und Puffer peinlich genau kontrollieren, ob sie korrekt 
initialisiert werden.

Der grösste Effekt dürfte sein, dass beim erstmaligen Benutzen eine 
saubere 0 in den uninitialisierten Variablen drin steht und nach 
Benutzung diese Variablen möglicherweise "verschmutzt" sind.

Speziell zum Teil

  //Counter zur?cksetzen
  DataCounter0 = 0;
  HeaderCounter0 = 0;
  EndCounter0 = 0;
  State0 = IDLE;

  DataCounter1 = 0;
  HeaderCounter1 = 0;
  EndCounter1 = 0;
  State1 = IDLE;

Da würde ich

  //Counter zur?cksetzen
  DataCounter0 = 0;
  HeaderCounter0 = 0;
  EndCounter0 = 0;

  DataCounter1 = 0;
  HeaderCounter1 = 0;
  EndCounter1 = 0;

jeweils in den IDLE State reinziehen.

von Flo S. (tuxianer)


Lesenswert?

also ich hab schon nen Standard Wert reingeladen:
1
  //Deafault_Werte
2
  for (i=0; i<16; i++) {
3
  
4
  Daten0[i]=Default[i];
5
  Daten1[i]=Default[i];
6
  
7
  }
8
  
9
  //Deafault_Werte
10
  for (i=16; i<32; i++) {
11
  
12
  Daten0[i]=Default[i];
13
  Daten1[i]=Default[i];
14
  
15
  }

Ich habe mich wahrscheinlich blöd ausgedrückt. Es geht nicht nur einmal. 
Variable A geht wunderbar. B Senden geht auch nur beim Empfangen von B 
meckerts.

Es kann also entweder hier ran liegen:
1
     //Speichern0
2
    if(State0 == SAVE) {
3
      uint8_t Address0;
4
      uint8_t x;
5
      x = 0;
6
      //Adresse in Databestimmen für Variablennamen
7
      Address0 = VarName0-'A';
8
      Address0 = Address0 * 16;
9
      //Empfangene Daten an entsprechende Stelle speichern
10
      for (i=Address0; i<(Address0+16); i++) {
11
      Daten0[x] = Data0[i]; 
12
      x++;
13
      }
14
      
15
      //Status auf IDLE verringern
16
      State0 = IDLE;
17
      
18
    }


oder beim Senden:
1
    
2
    //wenn Status SEND_DATA
3
    else if(State0 == SEND_DATA) {
4
    
5
      uint8_t Summe0;
6
      uint8_t Checksumme0;   
7
      uint8_t Address0;
8
      
9
      //Summe zurücksetzen
10
      Summe0 = 0;
11
      
12
      //Addresse berrechnen, wo die varriable gespeichert ist
13
      Address0 = VarName0 - 'A';
14
      Address0 = Address0 * 16;
15
        
16
      //Daten Senden  
17
      for (i=Address0; i < (Address0+15); i++) {
18
19
        Transmit0(Daten1[i]);
20
        Summe0 += Daten1[i];
21
      }
22
      
23
      
24
      //Checksumme berrechnen und senden
25
      Checksumme0 = 0x3a;
26
      Checksumme0 -= Summe0;
27
      Transmit0(Checksumme0);
28
    
29
      //Status auf ACK2 setzen
30
      State0 = ACK2;
31
    }

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich denke es hapert an der Stelle, die du mit Speichern0 kommentiert 
hast. Wie kommst du darauf, dass du mehr als 16 Bytes in Data0[] hast? 
Ich sehe im Zustand REC_DATA nur ein Füllen von exakt 16 Bytes.

Willst du vielleicht was anderes machen und hast in beiden Abschnitten 
die Reihenfolge vertauscht. Also soll es wie folgt sein?

Empfangen:
16 Bytes aus Data0 in Daten0 auffüllen, so dass in Daten0 jeweils die 16 
Bytes jeder Variable hintereinander stehen.

Senden
Die Daten aus einer Variablen, so wie sie oben in Daten0 gespeichert 
wurde, in 16 Bytes Paketen als Data0 ausgeben.

Dann müsste doe Kopiererei in Sepichern0 so ablaufen
   for(i=0, i<16; i++)
      Datenß[i+Adresse0] = Data0[i];

Und beim Senden
   for(i=0, i<16; i++)
      Data0[i] = Daten0[i+Adresse0];

Obacht: Du hast noch keine Abfrage auf einen Überlauf des Puffers Daten0 
drin. du hast 100 Bytes reserviert, d.h. du musst Sicherstellen, dass 
Adresse0 maximal den Wert 5 (Varname0 max. 'E') annimmt.

von Flo S. (tuxianer)


Lesenswert?

ich glaub ich hab einfach nur x und i vertauscht...ich meld mich gleich 
nochmal!

von Flo S. (tuxianer)


Lesenswert?

ja das wars und das resetten oben war für b auch falsch? Manchmal sieht 
man den Wald vor lauter Bäumen nicht,

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

gut ich hab nochmal alles korrigiert. Scheint jetzt zu klappen. Als
nächstes werde ich mich an einen Timeout Timer machen.

von Flo S. (tuxianer)


Lesenswert?

Ich hab mir jetzt mal über den Timer Gedanken gemacht. Ich werde es so 
machen, das immer wenn ein Zeichen empfangen wird der Timer 
zurückgesetzt wird. Und wenn er überläuft wird ja ein Interrupt 
ausgelöst. In diese Routine setze ich den Status wieder auf Idle. geht 
das noch eleganter zu lösen oder ist das so ok? Nimmt man da nen 8 Bit 
Timer und zählt die Überlaufe? Oder nimmt man gleich nen 16 Bit Timer?

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so ich habs mal reingepackt. Ich hab jetzt 2 8 Bit Timer. Timeout sind 2
Sekunden.

von Flo S. (tuxianer)


Lesenswert?

ich hab heut mal probiert mit 2 Rechnern zu gleich an den µC zu senden 
und es funktioniert leider nicht... bei einem Rechner gehts beim 2. 
nicht.

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.