Forum: Compiler & IDEs Ein kleines Schleifendurchlaufproblem und ich raffs ned


von Chris T. (chris0086)


Lesenswert?

Hallo Leute, ich hab ein Kleines Problem und zwar wird in meiner 
Schleife warscheinlich nicht richtig umgewandelt und dann nicht richtig 
gerechnet.
Hier erstmal der Code:
1
void USART_readline(char *daten)
2
   {
3
  char  NextChar;
4
     unsigned char DataCntTmp = 0;
5
     uint16_t NextInt;
6
     uint16_t Checksumme = 0;
7
     while (1)
8
     {
9
       NextChar = USART_getchar();
10
       NextInt = atoi(NextChar);
11
12
13
14
         if (NextInt == Checksumme) /* Hier steht die checksumme am Ende */
15
         {
16
           /* Ende des Strings erreicht,
17
              also Schleife verlassen */
18
           USART_Transmit(NextChar);
19
20
           return;
21
22
         }
23
         else /* Normales Zeichen, anhängen an die Zeichenkette */
24
         {
25
           daten[DataCntTmp] = NextChar;
26
           DataCntTmp++;
27
           Checksumme = Checksumme + NextInt;
28
           USART_Transmit(Checksumme);
29
         }
30
       }
31
32
   }
also die Schleife soll chars empfangen und in ein array speichern, 
leider läuft die Schleife gleich nach dem ersten String durch und wird 
beendet obwohl nach dem ersten Durchgang NextInt != Checksumme sein 
sollte.
Denn wenn ich ihm Hex 45 schicke dann sollte NextInt auf keinen Fall den 
Wert 0 haben weil ihr über atoi(nextchar) ja der Wert 45 zugewiesen wird 
und somit die Schleife nicht durch return verlassen werden.
aber das tut sie offensichtlich. Da nach dem ersten Zeichen die 
Programmausführung auserhalb der Schleife weiter  geht.

Irgendwas haut mit der atoi Funktion nicht hin
NextInt ist nämlich danach immernoch 00 obwohl es 45 sein müsste oder 
auf jeden fall ungleich 0.
Ich hoffe ihr habt mein Problem verstanden und könnt mir helfen

von Jörg G. (joergderxte)


Lesenswert?

a) Lies nochmal ganz genau nach, was *atoi()* macht (und warum du da 
eine Warnung vom compiler bekommst)
b) Du bist dir ganz sicher, das die Checksumme einmal in der Nachricht 
vorkommt? (besonders weil du da uint16 mit uint8 vergleichst)
c) Finde noch den Unterschied zwischen 'char', 'char *' und 'char[]' 
heraus.

rtfcbuch, Jörg

von Chris T. (chris0086)


Lesenswert?

zu a)
Prototyp: int atoi ( const char *ntpr);
Wandelt den Anfangsteil einer Zeichenfolge, auf die nptr zeigt, in eine 
int- Zahl um.
zu b)
sind doch beides uint16_t, aber werds in int ändern.
Ja die Checksumme sind einfach alle bytes aufsummiert und die kommt 
irgendwann in der Zeichenkete vor und ist das Endzeichen. Die Zeichen 
die empfangen werden sind alles hex-Ziffern.
zu c)
char ist ein Variablen typ, char[] ist ein array und char * ist ein 
Pointer oder?

Wo liegt jetzt mein Denkfehler ich seh ihn nämlich nicht.

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> zu a)
> Prototyp: int atoi ( const char *ntpr);
> Wandelt den Anfangsteil einer Zeichenfolge, auf die nptr zeigt, in eine
> int- Zahl um.

Exakt.
Und jetzt schaun wir mal was du machst
1
NextInt = atoi(NextChar);

Welchen Datentyp hat NextChar?
In deiner Beschreibung sprichst du von einer Zeichenfolge. Ist NextChar 
eine Zeichenfolge? Kann es aufgrund seines Datentyps überhaupt eine 
Zeichenfolge sein?

von Chris T. (chris0086)


Lesenswert?

ist vom typ char, also brauch ich da irgendwie einen pointer oder wie 
sieht das aus?

von Karl H. (kbuchegg)


Lesenswert?

PS: Das ganze Protokoll sieht seltsam aus.
Da werden solange Zeichen empfangen, bis sich mit dem nächsten Byte die 
Checksumme ergibt, die als erstes übertragen wurde. Irgendwie kommt mir 
das schon sehr restriktiv vor. Da stelle ich mir das Generieren eines 
beliebigen Datensatzes schon teuflisch schwer vor. Wenn sich zufällig in 
den Daten das richtige byte an der richtigen Stelle befindet, dann kann 
es durchaus vorkommen, dass die Checksumme schon vor Ende des 
Datensatzes bereits erreicht ist und die Leseroutine bricht vorzeitig 
ab.

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> ist vom typ char, also brauch ich da irgendwie einen pointer oder wie
> sieht das aus?

atoi will einen String haben!
Du hast keinen String. Du hast ein einzelnes Zeichen!
Ergo: atoi ist das falsche Werkzeug.

http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

(Und das ist nur ein klitzekleiner Auszug aus dem was man wissen muss um 
in C Stringverarbeitung zu machen. Der ganze auch noch wichtige Rest 
findet sich in jedem noch so grindigen C-Buch)

von Chris T. (chris0086)


Lesenswert?

nicht ganz richtig.
Mit Checksumme = Checksumme + NextInt; wird ja immer das folgende Byte 
zur Checksumme hinzuaddiert.
So sieht eine Anweisung aus die der MC empfangen und (vorerst) speichern 
soll:
4D4105530001000200E9

E9 ist die Checksumme alle Bytes aufaddiert...

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> nicht ganz richtig.
> Mit Checksumme = Checksumme + NextInt; wird ja immer das folgende Byte
> zur Checksumme hinzuaddiert.
> So sieht eine Anweisung aus die der MC empfangen und (vorerst) speichern
> soll:
> 4D4105530001000200E9
>
> E9 ist die Checksumme alle Bytes aufaddiert...

Ah. ok.
Aber das macht es auch nicht besser. Eher sogar schlimmer.

von Chris T. (chris0086)


Lesenswert?

wie würdest du es machen wenn ich fragen darf?
An den Zeichenketten die der MC empfängt kann ich nix ändern die kommen 
von einer Steuerung. aber ich brauch diese hexwerte in einem Array 
sodass ich auf jedes einzelne zugreifen kann.
Das ist natürlich jetzt nicht alles in der Funktion aber ich will mich 
herantasten und und wenn das eine funktioniert will ich zum nächsten 
gehen. deswegen auch der schlechte code...

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:

> An den Zeichenketten die der MC empfängt kann ich nix ändern die kommen
> von einer Steuerung.

Aber diese Steuerung wird ja wohl eine Protokollbeschreibung haben. Ich 
will einfach nicht glauben, dass die Protokollbeschreibung lautet: Lies 
solange dahin, bis die Summe der Bytes mit dem empfangenen Byte 
übereinstimmt.
Wenn dem tatsächlich so ist, sollte man dem der die Steuerung gemacht 
hat mal mit dem nassen Fetzen aufsuchen.

Angenommen die zu übertragenden Daten wären:

4D4105930001000200

Du rechnest du jetzt noch eine schöne Checksumme aus und hängst sie 
hinten drann.
Aber dein Lesecode
4D  ist noch ok.   Checksumme bisher 4D
41  auch noch ok.  Checksumme bisher 8E
05  auch noch ok.  Checksumme bisher 93
93 oops. Das ist identisch zur bisherigen Checksumme, woraufhin deine 
Leseroutine den Datensatz als beendet erklärt :-)

von Chris T. (chris0086)


Lesenswert?

Das Protokoll der Steuerung ist nicht offen aber ich hab dir noch etwas 
unterschlagen, hab ich glatt vergessen.
Das dritte byte gibt die länge der nachfolgenden Zeichen ohne Checksumme 
an also bei
4D4105530001000200E9

4D41 Steurkommandos
05 anzahl der nachfolgenden Zeichen ohne checksumme
5300010002 Nutzzeichen
00E9 Checksumme( tut mir leid sind 2 bytes)+ich hoffe jetzt wirds besser 
das ist jetzt aber alles

wurde alles durch probieren mit terminalprogramm und nem Delphi programm 
rausgefunden, ( da bin ich mehr firm drin)

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> Das Protokoll der Steuerung ist nicht offen aber ich hab dir noch etwas
> unterschlagen, hab ich glatt vergessen.
> Das dritte byte gibt die länge der nachfolgenden Zeichen ohne Checksumme
> an

Ah, Na also.
Dann mach deine Schleife über diese Anzahl und benutze die Checksumme 
danach um zu kontrollieren, ob die Übertragung richtig war.

> 00E9 Checksumme( tut mir leid sind 2 bytes)+ich hoffe jetzt wirds besser
> das ist jetzt aber alles

Und als Zahl kriegst du die so

  Checksumme = Byte1 * 256 + Byte2;

und benutze unbedingt unsigned char (oder uint8_t) für die Bytes.

von Chris T. (chris0086)


Lesenswert?

Ok ich schau mal ob ichs hinbekomme, danke erstmal für deine Hilfe aber 
jetzt geh ich erstmal das Bett aufsuchen. Danke Vielmals

von Chris T. (chris0086)


Lesenswert?

Kannst du mir das mit der Checksumme am obigen Beispiel nochmal 
erklären? komm da nicht auf 00E9 wenn ich die ersten beiden bytes 
nehme...

von Karl H. (kbuchegg)


Lesenswert?

Punkt 1:
  wenn du es mit Bytes zu tun hast, dann ist unsigned char (oder
  uint8_t) der Datentyp der Wahl

Punkt 2:
  In C ist ein char (bzw. signed char bzw. unsigned char) im Grunde
  auch nur ein Integer, mit dem man genauso rechnen kann, wie mit
  allem anderen. Das ist anders als in den meisten anderen
  Programmiersprachen, bei denen ein Character ausschliesslich
  zur Speicherung und Verarbeitung von tatsächlichen ASCII-Zeichen
  reserviert ist.

Hast du also 2 Bytes

  uint8_t Byte1 = 0xDE;
  uint8_t Byte2 = 0x89;

dann kannst du die beiden zu einem uint16_t zusammensetzen:

  uint16_t Wert = Byte1 * 256 + Byte2;

oder was gleichwertig ist:

  uint16_t Wert = ( Byte1 << 8 ) | Byte2;

(Beides wird vom Compiler höchst wahrscheinlich gleich übersetzt, da 
alles unsigned ist und die Multiplikation eine Operation mit einer 2-er 
Potenz darstellt).

Wert enthält dann 0xDE89

von Karl H. (kbuchegg)


Lesenswert?

So ungefähr würde ich die Funktion ansetzen:
1
unsigned char USART_readcommand(char *command, unsigned char *daten)
2
{
3
  unsigned char  NextByte;
4
  unsigned char  Len;
5
  unsigned char  i;
6
  unsigned int   CheckSummCalc;
7
  unsigend int   CheckSummRead;
8
9
  command[0] = USART_getchar();   // CommandoByte 1
10
  command[1] = USART_getchar();   // CommandoByte 2
11
12
  // ev. einen String aus den Commandobytes machen, die sehen
13
  // wie sinnvolle ASCII Codes aus
14
  command[2] = '\0';               
15
16
  // ev. hier prüfen, ob das Commando gültig ist
17
  // if( strcmp( command, "MA" ) != 0 )   // alles ausser MA ist nicht gültig
18
  //   return FALSE;
19
20
  // Anzahl der Datenbytes lesen
21
  Len = USART_getchar();
22
23
  // Jetzt kommen die Datenbytes
24
  CheckSummCalc = 0;
25
  for( i = 0; i < Len; ++i )
26
  {
27
    NextByte = USART_getchar();
28
29
    CheckSummCalc += NextByte;
30
    daten[i] = NextByte;
31
  }
32
33
  // Daten sind gelesen. Jetzt kommen noch 2 Bytes Checksumme
34
  CheckSummRead = USART_getchar();
35
  CheckSummRead = ( CheckSummRead << 8 ) + USART_getchar();
36
37
  // Wenn die übertragene Checksumme nicht mit der selbst berechneten
38
  // übereinstimmt, dann ist irgendwo ein Fehler passiert
39
  if( CheckSummRead != CheckSummCalc )
40
    return FALSE;
41
42
  return TRUE;
43
}

Welche Bytes genau in die empfängerseitige Checksummenberechnung 
einfliessen, musst du dir noch ansehen.

von Chris T. (chris0086)


Lesenswert?

hm sieht eigentlich gut aus aber das mit der Checksumme stimmt irgendwie 
nicht, er gibt jedenfalls immer false zurück wenn ich ihm 
4D4105530001000200E9 schicke...

Wenn ich mir die Checksumme ausgeben lasse:
1
CheckSummRead = USART_getchar();
2
  CheckSummRead = ( CheckSummRead << 8 ) + USART_getchar();
3
4
  if( CheckSummRead != CheckSummCalc )
5
    USART_Transmit(CheckSummCalc);
6
    return 0;
7
8
  return 1;
9
}
steht Hex 56 drin.

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> hm sieht eigentlich gut aus aber das mit der Checksumme stimmt irgendwie
> nicht, er gibt jedenfalls immer false zurück wenn ich ihm
> 4D4105530001000200E9 schicke...
>
> Wenn ich mir die Checksumme ausgeben lasse:
>
1
> CheckSummRead = USART_getchar();
2
>   CheckSummRead = ( CheckSummRead << 8 ) + USART_getchar();
3
> 
4
>   if( CheckSummRead != CheckSummCalc )
5
>     USART_Transmit(CheckSummCalc);
6
>     return 0;
7
> 
8
>   return 1;
9
> }
10
>
> steht Hex 56 drin.

Ich sagte doch, dass du noch kontrollieren musst, welche Bytes in die 
Checksummenberechnung einfliessen müssen.

Wenn du den Code ansiehst, habe ich nur die Datenbytes in die Berechnung 
mit eingehen lassen:

4D 41 05 53 00 01 00 02 00 E9
   0x53 + 0x00 + 0x01 + 0x00 + 0x02   ergibt 0x56

Aber anscheinend werden KommandoBytes und Länge auch mit eingerechnet, 
da

0x4D + 0x41 + 0x05 + 0x53 + 0x00 + 0x01 + 0x00 + 0x02 = 0xE9

das richtige Ergebnis ergibt.

Diese Änderung im Code wirst du doch wohl noch alleine hinkriegen.

von Chris T. (chris0086)


Lesenswert?

ah ok habs noch geändet und funzt jetzt DANKE Dir , jetzt kann ich mich 
an die nächsten Probleme wagen...

von Chris T. (chris0086)


Lesenswert?

Und ich hab ein weiteres Problem:
Also hab ein GrafikDisplay am Controller hängen was mir die Daten 
anzeigt die die eigentliche Steuerung an den Controller sendet.
Bei trockenübungen mit Kommandos vom PC klappt auch alles aber wenn ich 
den Controller an die Steuerung anschließe dann rattern die Daten so 
schnell rüber das ich nichts auf dem Display erkennen kann da ständig 
neue Sachen angezeigt werden, also die Daten kommen zu schnell rüber 
weil der MC die Quittierungsstrings so shcnell sendet, ich bräuchte 
jetzt eine Verzögerung für die Quittierungsstrings, von sagen wir mal 1 
Sekunde.
Wie kann man das am schnellesten und einfachsten machen?
Habe das mit den Timern gelesen nur habe ich damit noch nix gemacht,
oder kann man auch immer ne schleife zählen lassen bis 100000 damit er 
beschäftigt ist?  Wär aber bestimmt quick and dirty
Hier mal noch mein Code zum Antwortstring und Anzeige auf Display falls 
gewünscht:
1
//Sonst hier weiter: Antwortstring generieren und senden
2
3
     //Kommando für Temperaturwerte schicken (nur einmal)
4
          if(TempKommando == 0 && Steuerdaten[1] == 31)
5
          {
6
            TempKommando = Tempanfordern();
7
            goto Kommunikation;
8
          }
9
10
     Steuerdatenalt[0]=Steuerdaten[0];
11
     Steuerdatenalt[1]=Steuerdaten[1];
12
     Steuerdaten[5]= Steuerdaten[0]+Steuerdaten[1]+2;
13
14
     for(zaehler=0; zaehler<=5 ;zaehler++)
15
       {
16
         USART_Transmit(Steuerdaten[zaehler]);
17
18
19
       }
20
     //Anzeige der Nutzdaten auf LCD
21
22
   wait_while_chip_is_busy();
23
   if(zeile >= 64)
24
   {
25
     zeile = 0;
26
     lcd_clear();
27
   }
28
     lcd_set_cursor(0,zeile);
29
30
     for(zaehler=0;zaehler<=Datenlaenge;zaehler++)
31
     {
32
       lcd_putc(small_font,Nutzdaten[zaehler]);
33
       wait_while_chip_is_busy();
34
       lcd_set_cursor(zaehler*5,zeile);
35
       wait_while_chip_is_busy();
36
     }
37
     zeile+=8;
38
     //Anzeige Ende

von Karl H. (kbuchegg)


Lesenswert?

Dein Hauptproblem ist die Unsitte, den Schirm ständig löschen zu müssen. 
Das ist erstens langsam und führt zweitens bei schnellen Datenänderungen 
zu flackern bzw. dazu, dass man überhaupt nichts mehr lesen kann.

Entscheide dich wo am Schirm Daten dargestellt werden und schreibe 
dorthin ohne jedesmal den Schirm komplett zu löschen. Daten sollen sich 
überschreiben und nicht vorher gelöscht werden müssen. Bei schnellen 
Datenänderungen kann man dann zwar ebenfalls nicht viel lesen, aber 
sobald sich der erhaltene Wert stabilisiert hat man dann ein wunderbar 
stehendes Bild, bei dem sich der angezeigte Wert ab und zu mal ohne 
Zeitverzug ändert.

Aber wenn du eine Quick&Dirty Warterei brauchst ....

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

#include <util/delay.h>

...

  _delay_ms( 1000 );    // 1000 Millisekunden = 1 Sekunde

von Chris T. (chris0086)


Lesenswert?

Jetzt hab ich mal ne Frage nachdem mein Controller nicht mit der 
Steuerung reden will.
Kann ich über die isp Schnittstelle sehen was auf der Seriellen 
Schnittstelle geschrieben wird?
Hab ein mysmart usb programmer, wär nicht schlecht weil ich ned weis ob 
die Steuerung was zurück sendet, weil mit dem Pc funktionierts aber mit 
dem controller nicht...
Wenn man das direkt anzeigen lassen könnte wär das nicht schlecht

von Karl H. (kbuchegg)


Lesenswert?

Christian Hohmann schrieb:
> Jetzt hab ich mal ne Frage nachdem mein Controller nicht mit der
> Steuerung reden will.
> Kann ich über die isp Schnittstelle sehen was auf der Seriellen
> Schnittstelle geschrieben wird?
> Hab ein mysmart usb programmer, wär nicht schlecht weil ich ned weis ob
> die Steuerung was zurück sendet, weil mit dem Pc funktionierts aber mit
> dem controller nicht...
> Wenn man das direkt anzeigen lassen könnte wär das nicht schlecht

Du musst deine Teststrategien noch verfeinern.

Bei so etwas benutzt man den PC zum Testen von beidem

* zuerst kommt die Steuerung an den PC und mit einem Terminalprogramm
  'spielt' man ein wenig mit der Steuerung und sieht sich an, was sie
  so sendet und ob/wie sie auf Kommandos reagiert

* dann kommt der µC an den PC und mit sieht wieder im Terminalprogramm
  nach, wie der µC reagiert wenn man ihm die Steuerung über das
  Terminalprogramm vorgaukelt und ob er die richtigen Kommandos
  sendet

und erst dann verbindet man Steuerung und µC und da beide Komponenten 
unabhängig voneinander ihre Funktionstüchtigkeit gezeigt haben und in 
ihrem Verhalten bekannt sind und aufeinander abgestimmt wurden wird die 
Kommunikation auf Anhieb klappen. Zudem hat man mit der 'erst mal beide 
an den PC' Methode auch verifiziert, ob die physikalischen Parameter 
sowohl der Steuerung als auch des µC stimmen (Baudrate, Handshake, 
sonstige Einstellungen)

von Chris T. (chris0086)


Lesenswert?

Hab ich ja eigentlich alles gemacht, ich arbeite mit nem usb zu seriell 
wandler und dem Programm hterm. Habe das Gefühl das wenn ich den PC an 
der Steuerung habe nur die Hälfte des Strings angezeigt wird und beim 
nächsten string der Rest des Vorherigen, das ist mir mit dem Lappi 
eigentlich erstmal egal da ich eh den gleichen Antwortstring zurück 
sende, aber der MC weis das ja ned und er kommt ´mit seiner Checksumme 
durcheinander und macht ned weiter.
Wie ist das eigentlich mit dem Empfangspuffer des MC macht der wenn noch 
daten im empfangspuffer liegen trotzdem mit seinem Programm weiter oder 
muss ich sicherstellen das dieser leer ist bevor er weiter im Programm 
geht?

Ich musss das nochmal mit der Steuerung mit nem pc mit richtiger 
serieller Schnittstelle probieren, wie da die Daten nun kommen.

von Christian Hohmann (Gast)


Lesenswert?

So ich habe jetzt mal meinen pc mit dran gehängt um zu sehen ob die 
Kommunikation zwischen den beiden klappt, aber ich hab jetzt ein Problem 
wie ich die erste antwort der steuerung verarbeiten soll:
Also folgendes:
ICh schicke initialisierungskommando:
52 61 01 01 00 B5 (Ra)
darauf antowrtet die Steurung aber mit gleich 2 Befehlen hinterienander:
52 61 01 01 00 B5     4D 41 05 53 00 01 00 02 00 E9 (Ra...) und (MA...)
jetzt schreibt die mir natürlich den eingangsbuffer vom controller voll 
mit dem ersten Befehl den ich eigenlich ignorieren kann und nur am 2ten 
interessiert bin , später werden auch nur immer ein Befehl gesendet aber 
bei der initialiserung ist eben dieser blöde befehl davor gesetzt.
Wie kann ich dem Controller am einfachsten sagen das er die ersten 5 
Zeichen ignorieren soll, das er das aber nur einmal tun soll?
Hier nochmal mein leider wieder etwas wild gewordener Quellcode:
1
//Daten empfangen Routine
2
unsigned char USART_readcommand(unsigned char *Nutzdaten, char *Steuerdaten, int h)
3
{
4
  unsigned char  NextByte;
5
  unsigned char  Len;
6
  unsigned int   i;
7
  unsigned int   CheckSummCalc;
8
  unsigned int   CheckSummRead;
9
  CheckSummCalc = 0;
10
  Steuerdaten[0] = USART_getchar();   // CommandoByte 1
11
  CheckSummCalc += Steuerdaten[0];
12
  Steuerdaten[1] = USART_getchar();   // CommandoByte 2
13
  CheckSummCalc += Steuerdaten[1];
14
15
16
  // Anzahl der Datenbytes lesen
17
  Len = USART_getchar();
18
  CheckSummCalc += Len;
19
  // Jetzt kommen die Datenbytes
20
  /*
21
                    lcd_clear();
22
                    lcd_set_cursor(0,0);
23
                    wait_while_chip_is_busy();
24
                    */
25
  for( i = 0; i < Len; ++i )
26
  {
27
    NextByte = USART_getchar();
28
    CheckSummCalc += NextByte;
29
    Nutzdaten[i] = NextByte;
30
/*
31
32
                    lcd_set_cursor(i*5,1);
33
                    lcd_putc(small_font,Nutzdaten[i]);
34
                    wait_while_chip_is_busy();
35
*/
36
  }
37
38
  // Daten sind gelesen. Jetzt kommen noch 2 Bytes Checksumme
39
  CheckSummRead = USART_getchar();
40
  CheckSummRead = ( CheckSummRead << 8 ) + USART_getchar();
41
  if(h==0)
42
  {
43
  Steuerdaten[0] = USART_getchar();
44
  Steuerdaten[1] = USART_getchar();
45
  }
46
  h=1;
47
48
  if( CheckSummRead != CheckSummCalc )
49
  {
50
51
    return 0;
52
  }
53
  return Len;
54
}
55
56
//Funktion Temperatur anfordern
57
unsigned char Tempanfordern()
58
{
59
  unsigned int j;
60
  unsigned char Tempstring[8];
61
  Tempstring[0]=0X52;
62
  Tempstring[1]=0X62;
63
  Tempstring[2]=0X03;
64
  Tempstring[3]=0X00;
65
  Tempstring[4]=0X00;
66
  Tempstring[5]=0X01;
67
  Tempstring[6]=0X00;
68
  Tempstring[7]=0XB8;
69
  for(j=0; j<=7 ;j++)
70
    {
71
      USART_Transmit(Tempstring[j]);
72
73
    }
74
  return 1;
75
}
76
77
78
79
int main(void)
80
{
81
    UCSRB |= (1<<TXEN);                // UART TX einschalten
82
    UCSRB |= (1<<RXEN);
83
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1
84
85
    UBRRH = UBRR_VAL >> 8;
86
    UBRRL = UBRR_VAL & 0xFF;
87
88
89
    // LCD Initialisieren
90
91
            lcd_init();
92
            lcd_clear();
93
94
    while (!bit_is_set(UCSRA, UDRE))
95
  ;
96
//Globale Daten:
97
  char Steuerdaten[8];
98
  char Steuerdatenalt[2];
99
  int zaehler;
100
  int TempKommando = 0;
101
  int h =0;
102
    unsigned char Nutzdaten[60];
103
    for(zaehler=0;zaehler<60;zaehler++)
104
    {
105
      Nutzdaten[zaehler]='\0';
106
    }
107
108
    uint16_t Datenlaenge = 0;
109
    int zeile = 0;
110
111
//Initialisierungsstring senden:
112
113
  Steuerdaten[0]=0X52;
114
  Steuerdatenalt[0]=0X52;
115
  Steuerdaten[1]=0X61;
116
  Steuerdatenalt[1]=0X52;
117
  Steuerdaten[2]=0X03;
118
  Steuerdaten[3]=0X00;
119
  Steuerdaten[4]=0X00;
120
  Steuerdaten[5]=0X01;
121
  Steuerdaten[6]=0X00;
122
  Steuerdaten[7]=0XB7;
123
  for(zaehler=0; zaehler<=7 ;zaehler++)
124
  {
125
    USART_Transmit(Steuerdaten[zaehler]);
126
127
  }
128
129
  /*Steuerdaten[0]=0X4D;
130
  Steuerdaten[1]=0X41;
131
  Steuerdaten[2]=0X01;
132
  Steuerdaten[3]=0X01;
133
  Steuerdaten[4]=0X00;
134
  Steuerdaten[5]=0X90;
135
136
    for(zaehler=0; zaehler<=5 ;zaehler++)
137
    {
138
      USART_Transmit(Steuerdaten[zaehler]);
139
140
    }
141
*/
142
//Initialisierung Ende
143
144
145
146
//Daten empfangen und Bestätigungskommando schicken
147
Kommunikation:
148
     Datenlaenge = USART_readcommand(Nutzdaten, Steuerdaten,h);
149
    /* while(Datenlaenge == 0)  //Wenn Checksumme nicht übereinstimmt, nochmal senden
150
     {
151
       USART_Transmit(66);
152
       char CheckSummealt;
153
       CheckSummealt=Steuerdatenalt[0]+Steuerdatenalt[1]+0X01+0X01;
154
       for(zaehler=0; zaehler<2 ;zaehler++)
155
         {
156
157
           USART_Transmit(Steuerdatenalt[zaehler]);
158
         }
159
160
       for(zaehler=2; zaehler<=4 ;zaehler++)
161
          {
162
163
        USART_Transmit(Steuerdaten[zaehler]);
164
          }
165
       USART_Transmit(CheckSummealt);
166
       Datenlaenge = USART_readcommand(Nutzdaten, Steuerdaten,h);
167
     }
168
*/
169
     //Sonst hier weiter: Antwortstring generieren und senden
170
171
172
     //Kommando für Temperaturwerte schicken (nur einmal)
173
          if(TempKommando == 0 && Steuerdaten[1] == 31)
174
          {
175
            TempKommando = Tempanfordern();
176
            goto Kommunikation;
177
          }
178
179
     Steuerdatenalt[0]=Steuerdaten[0];
180
     Steuerdatenalt[1]=Steuerdaten[1];
181
     Steuerdaten[5]= Steuerdaten[0]+Steuerdaten[1]+2;
182
183
     for(zaehler=0; zaehler<=5 ;zaehler++)
184
       {
185
         USART_Transmit(Steuerdaten[zaehler]);
186
187
188
       }
189
     //Anzeige der Nutzdaten auf LCD
190
191
             wait_while_chip_is_busy();
192
             if(zeile >= 64)
193
             {
194
               zeile = 0;
195
               lcd_clear();
196
             }
197
               lcd_set_cursor(0,zeile);
198
199
               for(zaehler=0;zaehler<=5;zaehler++)
200
               {
201
                 lcd_putc(small_font,Steuerdaten[zaehler]);
202
                 wait_while_chip_is_busy();
203
                 lcd_set_cursor(zaehler*5,zeile);
204
                 wait_while_chip_is_busy();
205
               }
206
               zeile+=8;
207
               _delay_ms( 100 );  //mal ein bisschen warten
208
               //Anzeige Ende
209
210
     goto Kommunikation;
211
[

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.