lcd_write Fehlersuche

Gast #5131180
ich habe ein programm das alle 20sec Daten von einem controller auf 
einen anderen überträgt. Auf einem tft werden Text und Zahlenwerte 
angezeigt. Nach etwa einem Tag fällt die Übertragung des Textes aus - 
Zahlenwerte werden weiter angezeigt obwol Zahlen und text die gleiche 
Funktion benutzen. lcd_write("123test456"); wird nicht mehr angezeigt. 
Woran kann das liegen?

Das sind die Funktionen:
1
//==================================================
2
void lcd_write(uint8_t* str)
3
{
4
  uint8_t TempChar;
5
    do
6
    {
7
        TempChar = *str++;
8
        if(TempChar<' '||TempChar>130)return;
9

10
        lcd_char(TempChar);
11

12
           curposx =curposx+ f_width;
13
       if(frame)curposx++;
14
    }
15
    while ( *str != 0 );
16
}
17

18
//=============================================
19
void lcd_int3(uint16_t int1){
20
  uint8_t dum[4]={' ',' ',48,'\0'};
21
  u8 s1=0;
22

23
    if (int1>99){
24
        dum[0]=(int1/100+48);
25
    s1=1;
26
    }
27
        int1=int1%100;
28

29
    if (int1>9 || s1){
30
        dum[1]=(int1/10+48);
31
    }
32
        int1=int1%10;
33
        
34
        dum[2]=int1+48; 
35
   
36
        
37
     lcd_write(dum);
38
}
39
//==================================================
Gast
grundschüler schrieb:

> void lcd_write(uint8_t* str)
> {
>   uint8_t TempChar;
>     do
>     {
>         TempChar = *str++;
>         if(TempChar<' '||TempChar>130)return;
>
>         lcd_char(TempChar);
>
>            curposx =curposx+ f_width;
>        if(frame)curposx++;
>     }
>     while ( *str != 0 );
> }

Was passiert, wenn diese Funktion jemals einen Leerstring übergeben 
bekommt?
Gast
Direkt in dem Code sehe ich keinen Fehler (abgesehen von den 
überflüssigen Zeilen mit curposx). Hast du irgendwo einen Überlauf, der 
sich erst nach einem Tag beobachtbar macht? Oder läuft der Speicher 
voll? Sind die Texte auch immer mit '\0' abgeschlossen?
Gast
Thomas schrieb:
> Sind die Texte auch immer mit '\0' abgeschlossen?

Nein, das ist der einzige Unterschied zu Ziffernfolgen:

lcd_write("123test456");
./.
 uint8_t dum[4]={' ',' ',48,'\0'};
lcd_write(dum);

Aber durch '\' wird doch nur das Ende des strings angezeigt. Nach dem 
letzten Zeichen ist der string doch ohnehin zu Ende?




> Was passiert, wenn diese Funktion jemals einen Leerstring übergeben
> bekommt?

Weiß ich nicht, passiert eigentlich nicht.
Gast
grundschüler schrieb:

> lcd_write("123test456");

Bei einem solchen String-Literal ist die Null am Ende automatisch mit 
drin.

> Nach dem letzten Zeichen ist der string doch ohnehin zu Ende?

Nein. In C sind Strings zuende, wenn eine Null kommt. Wenn keine Null 
kommt, liest die Routine solange zufällig im Speicher weiter, bis eine 
kommt. Der Cursor wird dann natürlich sonstwohin gestellt.

> > Was passiert, wenn diese Funktion jemals einen Leerstring übergeben
> > bekommt?
> Weiß ich nicht

Dann geh der Frage mal nach. Ein bißchen Knobelei muß für Dich ja auch 
noch übrig bleiben. :-)
Gast
Nop schrieb:
> Bei einem solchen String-Literal ist die Null am Ende automatisch mit
> drin.

Das ist natürlich richtig, wusste ich früher auch mal.

Ich such ja erstmal eine Erklärung.

die lcd_write - Funktion müsste grundsätzlich in Ordnung sein.


"123test456" wird zur Laufzeit irgendwo in den RAM geschrieben. kann es 
sein dass sich der Ram dadurch verbraucht und irgendwann kein Platz für 
weiteren Text vorhanden ist?


Macht es Sinn, für solchen Text festen Speicher - u8 dum[] - anzulegen?
Gast
habe jetzt auf
1
u8 tst[]="wzb vl  rl  t0  t1  thm  elt  az ";
2
    lcd_goto(25,1);lcd_write(tst);
geändert.

Der im Ram abgelegte String wird korrekt geschrieben.

Es ist also kein Problem mit der Funktion lcd_write, sondern ein 
Speicherüberlaufproblem. Durch das ständige Schreiben von Text aus dem 
Programmcode entsteht ein Speicherüberlauf. Ist das normal oder ein 
Fehler in meinem Programm???????
Gast
Frank M. schrieb:
> immer eine while- und
> keine do-while-Schleife nehmen.

Danke für den Hinweis. Habe jetzt stark vereinfacht:
1
void lcd_write(uint8_t* str)
2
{
3
  while(*str>31)
4
    {
5
        lcd_char(*str++);
6
        curposx =curposx+ f_width;
7
    if(frame)curposx++;
8
    }
9
}

Bin gespannt, ob der Fehler jetzt weg ist.
Gast
ui schrieb:
> grundschüler schrieb:
>> while(*str>31)
>
> und was soll das bitte abfangen?

lcd_char holt Daten aus einem font. Der Font fängt mit ' '=32 an. Unter 
32 findet lcd_char im font nichts.
Gast
Bin - trotz geänderter lcd_write() - immer noch auf der Fehlersuche:
1
void test(u8 *str){
2
u8 tmp[]="xxx ";
3
u8 i;
4

5
for(i=0;i<3;i++){
6
  tmp[i]=*str++;
7
}
8

9
lcd_write(tmp);
10
}
11

12
.....
13

14
    lg(21,20);test("vl ");
15
    lcd_int4(owx_rx_buffer[17]);
16
    
17
    lg(22,20);lw("elt ");
18
    lcd_int4(kw_elt);
19
    
20
    lg(23,20);lw(thm);//u8 thm[]="thm ";
21
    lcd_int4(kw_therm);


nach ca. 2h wird nur noch die Variante thm angezeigt. Ich kann den code 
jetzt entsprechend ändern, würde aber gerne wissen, was falsch läuft.
Gast
Peter D. schrieb:
> wildgewordenen Pointer

das muss es sein. Kann eigentlich nur die onewire-empfangsroutine sein:
1
in der main:
2
...
3
while(1){
4
//================= owx polling ======================
5

6
if(owx_signal){//
7
led1_on;
8
//sub_owx_slave_polling();
9
u8 ret=  owx_empfangen(owx_rx_buffer);
10
...
11

12

13
volatile uint8_t owx_rx_buffer[30]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
14
//-------------------------------------------
15
uint8_t  owx_rx_byte(void){
16
uint8_t dat=0,i=0,abfr;
17
//u32 timeout;
18
  for(i=0;i<8;i++){
19
    dat=dat<<1;
20
    dly_med;
21
      if(owx_signal)
22
        abfr=0;
23
        else
24
        abfr=1;
25
    dly_short;
26
      if(owx_signal){
27
        if(abfr)dat++;
28
        while(owx_signal);
29
      }
30
      /*
31
      else{
32
      //???? error
33
      return;
34
      }
35
      */  
36
  }
37
return(dat);
38
}
39

40

41

42

43
//-------------------------------------------
44
uint8_t owx_empfangen(  
45
  uint8_t *buff    /* Pointer to data buffer */
46
){
47
uint8_t len,adr=0;
48
uint8_t  crc=0;
49
while(owx_signal);//Anfangssynchronisierung durch Master
50
dly_short;
51
 //adr
52
  *buff = owx_rx_byte();
53
  adr=*buff;
54
  crc=crc+1+*buff;
55
  *buff++;
56
  
57
//len
58
  *buff = owx_rx_byte();
59
  len=*buff-2;
60
  crc=crc+1+*buff;
61
  *buff++;
62

63
//4xheader + payload
64
do{
65
  *buff = owx_rx_byte();
66
  crc=crc+1+*buff;
67
  *buff++;
68
  } while (--len);
69

70
//crc
71
  *buff = owx_rx_byte();
72
  
73
 return crc;
Gast
Sicher, daß Du *buff++ meinst und nicht (*buff)++?

*buff++ liefert das zurück, worauf buff zeigt (was dann aber nicht 
verwendet wird) und erhöht dann den Zeiger buff.

Außerdem ist die Schleife bei 4xheader + payload schon wieder 
fußgesteuert und wird nicht klappen, wenn die empfangene Länge 0 ist.
Gast
Nop schrieb:
> Sicher, daß Du *buff++ meinst und nicht (*buff)++?

Das werd ich in Ruhe prüfen. Allerdings werden die Daten ja korrekt 
übertragen. Da ist es unwahrscheinlich, dass der Fehler in der 
Berechnungsroutine steckt. Eher pointer - aber ich finde keinen 
undefinierten.
Nop schrieb:
> Sicher, daß Du *buff++ meinst und nicht (*buff)++?

Nein, er meint eigentlich nur buff++.

grundschüler schrieb:
> Kann eigentlich nur die onewire-empfangsroutine sein:

In die Funktion würde ich auf jeden Fall mal einen Überlaufschutz 
einbauen. In ihrer jetzigen Form ist die in den Puffer geschriebene 
Menge von äußeren Einflüssen abhängig. Was ist z.B. wenn das Paket 
defekt ist und die Längeninfo im Paket daher zu groß ist?
Gast
Peter D. schrieb:
> len = 2

Das könnte der Fehler sein. len ist das 2.Feld und gibt die Anzahl der 
zu übertragenden bytes an. len-2 weil 2 bytes schon gelesen sind. Wenn 
da durch Übertragungsfehler ein Überlauf und damit ein Wert größer als 
der buffer steht, kann es zu Fehlern kommen. Ich werde da einen Abbruch 
einbauen für den Fall, dass len größer als der buffer wird.

Wer denkt denn an so was...
Gast
grundschüler schrieb:
> naja, ohne Eingrenzug des Problems wärs bei umfangreichem Code
> wahrscheinlich auch nicht gegangen.

Eingrenzung ja - auf lauffähigen Minimal-Code, der den Fehler beinhaltet 
und nicht auf irgendwelche Fragmente - aber nur irgendwelche Teile 
zeigen ist nicht nett.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.