mikrocontroller.net

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


Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
    //wenn status SEND_HEADER
    if(State0 == SEND_HEADER) {
      
      //Summe zurücksetzen
      Summe0 = 0;
      for (i=0; i<50; i++) {
        
        //wenn i nciht gleich 11 oder 49 sende den Header
        if((i != 11) && (i != 49)) {
          Transmit0(SendHeader[i]);
          Summe0 = Summe0+SendHeader[i];
        //wenn i 11 ist sende den Variablennamen
        }else if(i==11) {
          Transmit0(VarName0);
          Summe0 = Summe0+VarName0;
        //wenn i 49 ist Checksumme berrechnen und senden
        }else if(i==49) {
          Checksumme0 = Bruteforce(Summe0);
          Transmit0(Checksumme0);
        }
      
      }
      
      //Summe zurücksetzen
      Summe0 = 0;
      
      //Status auf ACK1 setzen
      State0 = ACK1;
    
    }


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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:
  • preview image for SM.jpg
    SM.jpg
    114 KB, 134 Downloads

Bewertung
0 lesenswert
nicht lesenswert
So ich habe die Skizze von Karl Heinz mal erweitert.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
      //ACK1
      else if(State0 == ACK1) {
      
        //Nur die 0x06 aufnhemen!
      
        State0 = SEND_DATA;
        //WARTESCHLEIFE!!!!!!!
        _delay_ms(4.35);
      
      }

Deine Bruteforce() habe ich nicht geprüft, denn diesen Codeschnippsel 
kann man wesentlich straffer schreiben:
    //wenn status SEND_HEADER
    if(State0 == SEND_HEADER) 
    {
      unsigned char Summe0;        // falls oben abweichende Definition
      unsigned char Checksumme0;   // falls oben abweichende Definition

      Summe0 = 0;
      SendHeader[12-1] = VarName0; // kennen wir schon

      for (i=0; i<(50-1); i++)     // 49 Bytes, Checksumme später!
      {
         Transmit0(SendHeader[i]);
         Summe0 += SendHeader[i];
      }

      /*
       * Alle 50 Bytes des Headers inkl. des Checksumbytes 
       * addieren. Dann durch 256 dividieren. Der Rest dieser 
       * Division (Modulo in manchen Programmietsprachen)
       * muss 0x3A sein (aus GTRprotokoll.pdf)
       *
       * Addieren der ersten 49 Bytes s.o.
       * Division durch 256 implizit durch Typ unsigned char
       * 50.tes Byte (Checksumme) jetzt berechnen und senden
       */
      Checksumme0 = 0x3a;
      Checksumme0 -= Summe0;
      Transmit0(Checksumme0);

      //Status auf ACK1 setzen
      State0 = ACK1;
    }

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht 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:
      Checksumme0 = 0x3a;
      Checksumme0 -= Summe0;
      Transmit0(Checksumme0);

Vielen Danke erstmal!

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich hab schon nen Standard Wert reingeladen:
  //Deafault_Werte
  for (i=0; i<16; i++) {
  
  Daten0[i]=Default[i];
  Daten1[i]=Default[i];
  
  }
  
  //Deafault_Werte
  for (i=16; i<32; i++) {
  
  Daten0[i]=Default[i];
  Daten1[i]=Default[i];
  
  }


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:
     //Speichern0
    if(State0 == SAVE) {
      uint8_t Address0;
      uint8_t x;
      x = 0;
      //Adresse in Databestimmen für Variablennamen
      Address0 = VarName0-'A';
      Address0 = Address0 * 16;
      //Empfangene Daten an entsprechende Stelle speichern
      for (i=Address0; i<(Address0+16); i++) {
      Daten0[x] = Data0[i]; 
      x++;
      }
      
      //Status auf IDLE verringern
      State0 = IDLE;
      
    }



oder beim Senden:
    
    //wenn Status SEND_DATA
    else if(State0 == SEND_DATA) {
    
      uint8_t Summe0;
      uint8_t Checksumme0;   
      uint8_t Address0;
      
      //Summe zurücksetzen
      Summe0 = 0;
      
      //Addresse berrechnen, wo die varriable gespeichert ist
      Address0 = VarName0 - 'A';
      Address0 = Address0 * 16;
        
      //Daten Senden  
      for (i=Address0; i < (Address0+15); i++) {

        Transmit0(Daten1[i]);
        Summe0 += Daten1[i];
      }
      
      
      //Checksumme berrechnen und senden
      Checksumme0 = 0x3a;
      Checksumme0 -= Summe0;
      Transmit0(Checksumme0);
    
      //Status auf ACK2 setzen
      State0 = ACK2;
    }

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaub ich hab einfach nur x und i vertauscht...ich meld mich gleich 
nochmal!

Autor: Flo S. (tuxianer)
Datum:

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

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

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

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

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

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.