Forum: Mikrocontroller und Digitale Elektronik I2C Problem wahrscheinlich Code fehler!?


von Tobias N. (silberkristall)


Lesenswert?

Ich habe einen ATMega128A mit einem EDIPTFT Touch Display via I2C 
verbunden. 2 Pullup widerstände von 4,7k pullen die I2C Leitungen.

Für das Display habe ich mir zwei funktionen erstellt. Das Senden 
funktioniert. Das Lesen nicht.

display.h
1
unsigned char SendDisplayData(char *buf);
2
unsigned char ReadDisplayData(void);
3
void DisplayReset(void);
4
unsigned char ReadDisplayBufferStatus(void);
5
void DisplayInit(void);
6
7
unsigned char *buf;

display.c
1
#include <stdint.h>
2
#include <string.h>
3
#include <i2c.h>
4
#include <util/delay.h>
5
#include <stdlib.h>
6
#include <display.h>
7
#include <avr/io.h>
8
9
void DisplayInit(void)
10
{
11
  // Reset Pin
12
  DDRD |= (1<<PD3);
13
  PORTD &= ~(1<<PD3);
14
  // SBUF Pin
15
  DDRD &= ~(1<<PD2);
16
  PORTD &= ~(1<<PD2);
17
}
18
19
unsigned char SendDisplayData(char *buf)
20
{
21
    unsigned int len = strlen(buf);
22
    unsigned char i, bcc, ret;
23
  int daten = 0;
24
    ret = i2c_start(DISPLAY_I2C_ADDR+I2C_WRITE);       // set device address and write mode
25
    if ( ret ) {
26
        /* failed to issue start condition, possibly no device found */
27
        i2c_stop();
28
        /* do some error reporting.. led or whatever */
29
    } else {
30
        /* issuing start condition ok, device accessible */
31
        i2c_write(0x11);                            // send DC1
32
        bcc = 0x11;
33
        i2c_write(len);
34
        bcc = bcc + len;
35
        for(i=0; i < len; i++) // Send buf
36
        {
37
            i2c_write(buf[i]);
38
            bcc = bcc + buf[i];
39
        }
40
        i2c_write(bcc); // Send checksum                      
41
        i2c_start(DISPLAY_I2C_ADDR+I2C_READ);       // set device address and read mode
42
        ret = i2c_readNak();                        // read one byte
43
        if (ret == DISPLAY_I2C_ACK)
44
        {
45
            daten = 1;
46
        } else {
47
            daten = 0;
48
        }
49
        i2c_stop();
50
    }
51
  return daten;
52
}
53
54
55
56
    unsigned char ReadDisplayData(void)
57
    {
58
        unsigned char bcc, ret, rettemp;
59
        unsigned char len = 2;
60
        ret = i2c_start(DISPLAY_I2C_ADDR+I2C_WRITE);      // set device address and write mode
61
        if ( ret ) {
62
            /* failed to issue start condition, possibly no device found */
63
            i2c_stop();
64
            /* do some error reporting.. led or whatever */
65
        } else {
66
            /* issuing start condition ok, device accessible */
67
            i2c_write(DISPLAY_I2C_DC2); // send DC2
68
            i2c_write(0x01);            // send 1
69
            i2c_write(0x53);            // send S
70
            bcc = DISPLAY_I2C_DC2 + 0x01 + 0x53;                // Set checksum
71
            i2c_write(bcc);            // Send checksum 
72
            bcc = 0;
73
            i2c_start(DISPLAY_I2C_ADDR+I2C_READ);      // set device address and read mode
74
            ret = i2c_readAck();                        // read ack byte
75
            if (ret == DISPLAY_I2C_ACK)
76
            {
77
                rettemp = i2c_readAck();
78
                bcc = bcc + rettemp;
79
                ret = i2c_readAck();            // read len
80
                bcc = bcc+ret;
81
                unsigned char *buf = malloc(ret * sizeof(char));
82
                len += ret;
83
                for (int i = 0; i < ret; i++)
84
                {
85
                    buf[i] = i2c_readAck(); // read data bytes
86
                    bcc = bcc + buf[i];
87
                }
88
                ret = i2c_readNak();    // read len
89
                if (ret != len) {
90
                    // Checksum not matching
91
                }
92
                return buf;
93
            } else {
94
                // No Ack
95
            }
96
            i2c_stop();
97
           
98
        }
99
        return 0;
100
    }
101
102
void DisplayReset(void)
103
  {
104
    PORTD &= ~(1<<PD3);
105
    PORTD &= ~(1<<PD3);
106
    PORTD &= ~(1<<PD3);
107
    PORTD |= (1<<PD3);
108
    
109
  }
110
111
unsigned char ReadDisplayBufferStatus(void)
112
  {
113
    int DisplayBufferStatus;
114
    if ( !(PIND & (1<<PIND2)) )
115
      {
116
        DisplayBufferStatus = 1;
117
      }
118
      else
119
      {
120
        DisplayBufferStatus = 0;
121
      }
122
      
123
    return DisplayBufferStatus;
124
  }

Das Display bekommt die Daten
1
SendDisplayData("#DL,");

in diesem format übermittelt.

Bei Touch eingaben legt das Display bei Daten im Sendebuffer einen PIN 
auf LOW. Diese abfrage funktioniert ebenfalls.

Sobald ich allerdings nun daten lesen will:
1
 readdata = ReadDisplayData();

stürzt nun entweder der µC ab oder aber ich bekomme zwar daten, mit 
denen sich allerdings nichts anfangen kann.

Ich erhalte dann z.b. Daten wie folgt: 217 1 255 1 193 1 141 1 ....

Immer eine 1 zwischen den Zahlen. Jedoch passen die Zahlen auch nicht. 
Also das Display würde ebenfalls wie man sendet antworten. Also z.b. mit

#TB1,0 oder halt mit den Dezimalzahlen 23 (für Escape, #) allerdings ist 
das erste zeichen eine völlig andere Zahl.

Ich verzweifel.

Kann mir da jemand weiter helfen?

von Tobias N. (silberkristall)


Lesenswert?

Keiner eine Idee?

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

ich bin zwar nicht gerade der C-Programmierer, aber dein malloc und die 
Übergabe des Puffers scheint mir etwas zweifelhaft.
Gib doch die empfangenen Werte erst mal direkt aus der Schleife z.B. per 
UART aus. Da die Länge der Daten die das Display maximal zurückliefern 
kann doch sicher bekannt ist ist es besser gleich einen festen Puffer zu 
definieren.

Sascha

von jo (Gast)


Lesenswert?

>unsigned char *buf = malloc(ret * sizeof(char));

warum dynamisch? und warum gibst du den speicher nicht wieder frei?

Gruß Jonas

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Und warum beachtest Du nicht die Warnungen, die Dir der Compiler um die 
Ohren haut? Oder hast Du die etwa deaktiviert?

Der ganze Code sieht so aus, als hättest Du ihn irgendwo kopiert und 
beim Zusammenpfuschen überhaupt nicht verstanden, wie er funktioniert.

von Tobias N. (silberkristall)


Lesenswert?

Beide, also Send und Read wurden mir geschrieben, daher verstehe ich das 
ganze generell nicht.

Das Send geht wie gesagt. Ich kann halt nur so das nötigste in C.

Es ging mal, dann wurde aber das ack im read nicht genommen. Dann hat er 
den code nochmal für mich abgeändert, seither klappt das nicht mehr.

Da ja das Send geht und das Read auch (also der Buffer ist dann wieder 
leer im Display) muss es am Code liegen.

von Tobias N. (silberkristall)


Lesenswert?

So,

ich habe jetzt mal ein wenig rumprobiert. Keine Chance. Wenn ich dich 
speicher hinterher mit free wieder lösche stürzt der µC direkt ab. Keine 
Chance was zu bewirken.

Und sonst bekomme ich halt nur utopische Daten.

Ich verzweifel :( Senden geht, empfangen naja, nur teilweise.

von Karl H. (kbuchegg)


Lesenswert?

Das
1
unsigned char ReadDisplayData(void)
2
{
3
...
4
                unsigned char *buf = malloc(ret * sizeof(char));
5
6
...
7
                return buf;

hast du so nie und nimmer durch den Compiler gebracht.
Ein Pointer auf unsigned char ist kein unsigned char. Die Funktion will 
aber einen unsigned char zurückgeben und keinen Pointer.

von Tobias N. (silberkristall)


Lesenswert?

Problem gelöst. Zwischen jedem lesenden Byte 6us warten und es klappt 1A

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.