Forum: Compiler & IDEs XC16 v1.70- oder Ich mache komische Sachen mit Pointer


von Aaron K. (aaron_b_k)


Lesenswert?

Hi Leute,
ich habe ein Problem mit einer Funktion...

_Funktion in MPLAB_

Im Grunde sieht die Funktion so aus:
1
static char data_read_buf[100]; //buffer for queueing data to be read
2
static int read_cnt = 0; //counter icnrements through data_red_buf
3
4
void i2c_drv_read_data_get(int* data) {
5
6
    *data = data_read_buf[read_cnt++];
7
    if (read_cnt == 100)read_cnt = 0;
8
9
    return;
10
}

In das Read-Buffer werden Daten welche via I2C empfangen werden 
zwischengespeichert. Das Funktioniert soweit auch (das Array füllt sich 
mit Daten ungleich 0). Die oben dargestellte Funktion soll nun diese 
Daten element für element in "int* data" schreiben.
Auch das Inkrementieren durch die Elemente funktioniert tadellos.
Jedoch nimmt *data nicht die Werte aus data_read_buf an, sondern 
verbleibt bei 0.

Ich verwende hier einen PIC24hj128gp202 mit der MPLAB X IDE v5.50 mit 
dem xc16 v1.70 compiler.

Ich weiß jetzt nicht ob es am Debugger liegt. Kann die Werte leider nur 
im Debug-Modus auslesen, da ich sonst keine Daten/Info-Ausgänge habe.

_Funktion mit online Compiler klappt_

Ich habe eine ähnliche Funktion in einem online c-compiler testweise 
ausgewertet. Diese verhält sich so wie sie soll...
1
#include <stdio.h>
2
3
int data_array[]={0, 100, 200, 300, 400};
4
5
void foo(int* data){
6
    
7
    static int i=0;
8
    *data = data_array[i++];
9
    if(i>=5)i=0;
10
    
11
    return;
12
}
13
14
int main()
15
{
16
        
17
    int i=0;
18
    for(i=0;i<5;i++){
19
        int tmp;
20
        foo(&tmp);
21
        printf("%i\n", tmp);
22
    }
23
24
    return 0;
25
}

Diese Funktion gibt dann aus:

0
100
200
300
400

_eigentliche Frage_

Habe ich iwo einen Fehler gemacht? Kann mit jemand das Verhalten 
erklären?

von uff basse (Gast)


Lesenswert?

Aaron K. schrieb:
> Habe ich iwo einen Fehler gemacht?

Eine Deklaration
1
  int irgendwas;

ist fast immer scheisse wenn man die Registerbreite bzw. die
Architektur des Zielsystems nicht kennt. Kann dein online-
Compiler das riechen was du willst?

von Aaron K. (aaron_b_k)


Lesenswert?

An welcher Stelle genau sollte, das ein Problem darstellen?

Ich verwende bei beiden Beispielen nur int-Variablen, es wird nichts 
bitwise manipuliert, also ist dier Registerbreite doch völlig egal.

Bei meiner Frage gehts ja auch darum, warum es in der online IDE funzt, 
aber in MPLAB nicht. Ist ja an sich der selbe Code in beiden Fällen. Nur 
iwie tut die MPLAB-Funktion nicht was sie soll und ich weiß nicht warum 
...

von Mombert H. (mh_mh)


Lesenswert?

Aaron K. schrieb:
> Habe ich iwo einen Fehler gemacht? Kann mit jemand das Verhalten
> erklären?

Das ist schwer zu beantworten mit den Infos die du uns gegeben hast. 
Dein "online c-compiler" Beispiel weist einige Unterschiede auf zu 
deinem ursprünglichen Beispiel. Z.B. static char data_read_buf[] vs. int 
data_array[].

: Bearbeitet durch User
von Simon (Gast)


Lesenswert?

Aaron K. schrieb:
> Bei meiner Frage gehts ja auch darum, warum es in der online IDE funzt,
> aber in MPLAB nicht. Ist ja an sich der selbe Code in beiden Fällen. Nur
> iwie tut die MPLAB-Funktion nicht was sie soll und ich weiß nicht warum
> ...

Hast du denn data_read_buf[] mal mit Pseudo-Werten bei der 
Initialisierung gefüllt, und geguckt was dann passiert?
Bzw. was passiert mit data nach dem schreiben? Kann es sein, dass das 
Kopieren einfach weg-optimiert wird?

von DerEgon (Gast)


Lesenswert?

1
void i2c_drv_read_data_get(int* data) {
2
    *data = data_read_buf[read_cnt++];
3
    if (read_cnt == 100)read_cnt = 0;
4
    return;
5
}

Welchen Sinn soll das "return" hier haben? Was würde die Funktion 
machen, wenn das da nicht steht?

von Wilhelm M. (wimalopaan)


Lesenswert?

Aufruf aus ISR? non-volatile?

von Gelangweilter (Gast)


Lesenswert?

Aaron K. schrieb:
> In das Read-Buffer werden Daten welche via I2C empfangen werden
> zwischengespeichert.

Lass mich raten: Mit einem Interrupt?

von Aaron K. (aaron_b_k)


Lesenswert?

DerEgon schrieb:
>
1
> void i2c_drv_read_data_get(int* data) {
2
>     *data = data_read_buf[read_cnt++];
3
>     if (read_cnt == 100)read_cnt = 0;
4
>     return;
5
> }
6
>
>
> Welchen Sinn soll das "return" hier haben? Was würde die Funktion
> machen, wenn das da nicht steht?

Ist einfach eine gute Angewohntheit selbst bei einer Void-Funktion ein 
return reinzusetzen. Damit jeder weiß hier ist die Funktion zu ende und 
es wurde nichts vergessen (ende ist hier auch wirklich vorgesehen)

von Aaron K. (aaron_b_k)


Lesenswert?

Gelangweilter schrieb:
> Aaron K. schrieb:
>> In das Read-Buffer werden Daten welche via I2C empfangen werden
>> zwischengespeichert.
>
> Lass mich raten: Mit einem Interrupt?

Nope habe nicht einen einzigen Interrupt am laufen. Alles via Polling.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dann zeige mal den Caller, bisher haben wir nur den Callee gesehen.

von J. S. (jojos)


Lesenswert?

falsche/fehlende forward Deklaration beim Aufrufer?

: Bearbeitet durch User
von DerEgon (Gast)


Lesenswert?

Aaron K. schrieb:
> Ist einfach eine gute Angewohntheit selbst bei einer Void-Funktion ein
> return reinzusetzen.

Nee. Ist keine gute Angewohnheit, sondern überflüssig und irritierend. 
So, als ob der Programmierer sich nicht sicher ist, was er da eigentlich 
will.

Mit der gleichen Argumentation könntest Du hinter jedes if() auch einen 
leeren else-Zweig packen, um klarzumachen, daß der da nicht 
versehentlich vergessen wurde:
1
if (a == 4)
2
{
3
  printf("A ist vier\n");
4
}
5
else
6
{ };

Oder in einem switch-Statement jeden unbenutzten Wert einzeln aufführen 
und/oder einen leeren default-Zweig einfügen.

von Mombert H. (mh_mh)


Lesenswert?

Ich finde, dass es eine gute Angewohnheit ist (wenn es konsquent überall 
gemacht wird). Dann kann ich auf den ersten Blick sehen, wo die Ausgänge 
aus der Funktion sind und kann sehr einfach den Datenfluss 
zurückverfolgen, ohne jede Funktion von Anfang bis Ende durchgehen zu 
müssen.

von DerEgon (Gast)


Lesenswert?

Es ist überflüssig, denn auch das Ende einer Funktion ist ein "Ausgang". 
Immer.

von Gelangweilter (Gast)


Lesenswert?

Aaron K. schrieb:
> Nope habe nicht einen einzigen Interrupt am laufen. Alles via Polling.

Na dann, nächste Stufe:


Aaron K. schrieb:
> Im Grunde sieht die Funktion so aus:

Zeige die Originalfunktion, und nicht eine frei erfundene Lügenfunktion!

von Mombert H. (mh_mh)


Lesenswert?

DerEgon schrieb:
> Es ist überflüssig, denn auch das Ende einer Funktion ist ein "Ausgang".
> Immer.

Es gibt bei allen deinen Funktionen einen logischen und sinnvollen Weg 
die Funktion am Ende (letzte Zeile) zu verlassen?

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Dann zeige mal den Caller, bisher haben wir nur den Callee gesehen.

Sry. Was meinst du mit Caller/Callee?? Kann mit den Begrifflichkeiten 
nichts anfangen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Wilhelm M. schrieb:
>> Dann zeige mal den Caller, bisher haben wir nur den Callee gesehen.
>
> Sry. Was meinst du mit Caller/Callee?? Kann mit den Begrifflichkeiten
> nichts anfangen.

Caller = Aufrufer

von Aaron K. (aaron_b_k)


Lesenswert?

Gelangweilter schrieb:
> Aaron K. schrieb:
>> Nope habe nicht einen einzigen Interrupt am laufen. Alles via Polling.
>
> Na dann, nächste Stufe:
>
>
> Aaron K. schrieb:
>> Im Grunde sieht die Funktion so aus:
>
> Zeige die Originalfunktion, und nicht eine frei erfundene Lügenfunktion!

Das ist meine Originalfunktion.
1
static char data_read_buf[100]; //buffer for queueing data to be read
2
static int read_cnt = 0; //counter icnrements through data_red_buf
3
4
void i2c_drv_read_data_get(int* data) {
5
6
    *data = data_read_buf[read_cnt++];
7
    if (read_cnt == 100)read_cnt = 0;
8
9
    return;
10
}
11
12
int main(void) {
13
14
    TRISAbits.TRISA0 = OUTPUT;
15
    TRISAbits.TRISA1 = OUTPUT;
16
17
    i2c_drv_init();
18
19
    int i = 0;
20
    for (i = 0; i < 0xffff; i++)continue;
21
    for (i = 0; i < 0xffff; i++)continue;
22
    for (i = 0; i < 0xffff; i++)continue;
23
24
    int data_bridge = 0;
25
    int data_temperature = 0;
26
27
    while (1) {
28
29
        if (i2c_drv_manager() == 1) {
30
31
            for (i = 0; i < 0xffff; i++)continue;
32
33
            LATAbits.LATA1 = 1;
34
            pressure_sensor_start_measurement();
35
            LATAbits.LATA1 = 0;
36
37
            int tmp = 0;
38
            i2c_drv_read_data_get(&tmp);
39
            data_bridge = tmp << 8;
40
            i2c_drv_read_data_get(&tmp);
41
            data_bridge += tmp;
42
43
            i2c_drv_read_data_get(&tmp);
44
            data_temperature = tmp << 3;
45
            i2c_drv_read_data_get(&tmp);
46
            data_temperature += tmp >> 5;
47
48
            tmp = 0;
49
        }
50
    }
51
52
    return 1;
53
}
Der I2C_manager arbeitet im Grunde die I2C-Tasks ab. Der funktioniert 
soweit auch.

pressure_sensor_start_measurement setzt die Tasks die notwendig sind um 
Daten aus einem Sensor zu lesen. Auch das funktioniert soweit tadellos.

Das Problem entsteht wie gesagt erst an der Stelle, wo die Daten aus 
einem Software-Read-Buffer via Pointer an eine andere Adresse kopiert 
werden. (die void i2c_drv_read_data_get(int* data) Funktion). um genau 
zu sein macht dort soweit ich das bewerten kann nur die Zeile...

1
*data = data_read_buf[read_cnt++];

...Probleme. Da genau hier der Wert des Pointers 0 bleibt, während im 
Array an gegebener Stelle Werte ungleich 0 stehen.

[/c]

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Aaron K. schrieb:
>> Wilhelm M. schrieb:
>>> Dann zeige mal den Caller, bisher haben wir nur den Callee gesehen.
>>
>> Sry. Was meinst du mit Caller/Callee?? Kann mit den Begrifflichkeiten
>> nichts anfangen.
>
> Caller = Aufrufer

Ist das nicht der Fuktionsname?

Aber was ist dann ein CAllee??? Tippfehler?

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> int tmp = 0;
>             i2c_drv_read_data_get(&tmp);

Und was erwartest Du, was hier passiert?

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Wilhelm M. schrieb:
>> Aaron K. schrieb:
>>> Wilhelm M. schrieb:
>>>> Dann zeige mal den Caller, bisher haben wir nur den Callee gesehen.
>>>
>>> Sry. Was meinst du mit Caller/Callee?? Kann mit den Begrifflichkeiten
>>> nichts anfangen.
>>
>> Caller = Aufrufer
>
> Ist das nicht der Fuktionsname?
>
> Aber was ist dann ein CAllee??? Tippfehler?

Nein. Callee ist "der Aufgerufene"

von Programmierer (Gast)


Lesenswert?

Aaron K. schrieb:
> void i2c_drv_read_data_get(int* data) {
>     *data = data_read_buf[read_cnt++];
>     if (read_cnt == 100)read_cnt = 0;
>     return;
> }

Wäre diese Funktion nicht so viel einfacher:
1
int i2c_drv_read_data_get(void) {
2
  int c = read_cnt;
3
  read_cnt = read_cnt == 99 ? 0 : read_cnt + 1;
4
  return data_read_buf[c];
5
}

Wozu die Schnippselei mit dem Pointer?

Mombert H. schrieb:
> DerEgon schrieb:
>> Es ist überflüssig, denn auch das Ende einer Funktion ist ein "Ausgang".
>> Immer.
>
> Es gibt bei allen deinen Funktionen einen logischen und sinnvollen Weg
> die Funktion am Ende (letzte Zeile) zu verlassen?

Fast immer. Besser in den seltenen Fällen, wo das nicht so ist, ein "/* 
unreachable */" ans Ende schreiben. Besser den häufigen Standardfall 
einfach machen als überall etwas redundantes hinzuschreiben...

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> pressure_sensor_start_measurement setzt die Tasks die notwendig sind um
> Daten aus einem Sensor zu lesen. Auch das funktioniert soweit tadellos.

FreeRTos?

von Simon (Gast)


Lesenswert?

Welche Optimierung hast du eingeschaltet?
da
int data_bridge = 0;
int data_temperature = 0;

nicht weiter genutzt werden, könnte das ganze Gespeichere ignoriert 
werden.

versuche mal die beiden Variablen global und volatile zu deklarieren.

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Aaron K. schrieb:
>> int tmp = 0;
>>             i2c_drv_read_data_get(&tmp);
>
> Und was erwartest Du, was hier passiert?

Ich möchte die Daten in tmp zwischenspeichern und den beiden variablen 
data_bridge und data_temperature zuweisen.

Die empfangenen i2c Bytes sind wie folgt aufgabaut:
1
Bit   | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2
------|---|---|---|---|---|---|---|---|
3
Byte 1| Flags | High Byte Pressure    |
4
Byte 2| Low Byte Pressure             |
5
Byte 3| High ByteTemperature          |
6
Byte 4|Low Byte Te| Dont care         |

Ich muss dei Daten quasi wieder zusammenkleben. Lässt sich sicherlich 
ohne tmp lösen, ist so finde ich einfach und tuts auch.

von Aaron K. (aaron_b_k)


Lesenswert?

Simon schrieb:
> Welche Optimierung hast du eingeschaltet?
> da
> int data_bridge = 0;
> int data_temperature = 0;
>
> nicht weiter genutzt werden, könnte das ganze Gespeichere ignoriert
> werden.
>
> versuche mal die beiden Variablen global und volatile zu deklarieren.

Optimierungsstufe 0 also quasi keine Optimierung. Aber ich versuche das 
mal.

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Wilhelm M. schrieb:
>> Aaron K. schrieb:
>>> int tmp = 0;
>>>             i2c_drv_read_data_get(&tmp);
>>
>> Und was erwartest Du, was hier passiert?
>
> Ich möchte die Daten in tmp zwischenspeichern und den beiden variablen
> data_bridge und data_temperature zuweisen.

> Ich muss dei Daten quasi wieder zusammenkleben. Lässt sich sicherlich
> ohne tmp lösen, ist so finde ich einfach und tuts auch.

Wo wird denn Dein Buffer data_read_buf gefüllt. Das fehlt immer noch ...

von Simon (Gast)


Lesenswert?

Simon schrieb:
> versuche mal die beiden Variablen global und volatile zu deklarieren.
>
>
>
>       if (!have_newpost_anchor && (!topic_last_read_at ||
> topic_last_read_at < 1656070342000)) {
>         document.write('<a name="new" id="new"></a>');
>         have_newpost_anchor = true;
>       }

oder gucke dir den generierten Assembler-Code an, da siehst du auch gut 
was passiert.

von Simon (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Wo wird denn Dein Buffer data_read_buf gefüllt. Das fehlt immer noch ...
>
deshalb fragte ich:

Simon schrieb:
> Hast du denn data_read_buf[] mal mit Pseudo-Werten bei der
> Initialisierung gefüllt, und geguckt was dann passiert?
> Bzw. was passiert mit data nach dem schreiben? Kann es sein, dass das
> Kopieren einfach weg-optimiert wird?

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Aaron K. schrieb:
>> Wilhelm M. schrieb:
>>> Aaron K. schrieb:
>>>> int tmp = 0;
>>>>             i2c_drv_read_data_get(&tmp);
>>>
>>> Und was erwartest Du, was hier passiert?
>>
>> Ich möchte die Daten in tmp zwischenspeichern und den beiden variablen
>> data_bridge und data_temperature zuweisen.
>
>> Ich muss dei Daten quasi wieder zusammenkleben. Lässt sich sicherlich
>> ohne tmp lösen, ist so finde ich einfach und tuts auch.
>
> Wo wird denn Dein Buffer data_read_buf gefüllt. Das fehlt immer noch ...
1
//receive---------------------------------------------------------------------//
2
3
/*
4
 * triggers receiving of I2C1
5
 *
6
 * @since 1.0.0
7
 * @category hardware
8
 * @param {byte} ptr to location where the data will be stored
9
 * @returns {void}
10
 * @example 
11
 * 
12
 * int data;
13
 * ...
14
 * while(i2c_drv_receive_get_check!=TRUE)continue; //wait until data is ready
15
 * i2c_drv_receive_get(&data); //get data
16
 * 
17
 */
18
static int i2c_drv_data_get(void) {
19
20
    static int i = 0;
21
    data_read_buf[i++] = I2C1RCV;
22
    if (i == 100)i = 0;
23
24
    return TRUE;
25
}

Das Buffer wird hier gefüllt. Es geht aber wie gesagt darum, dass die 
Daten nicht an den Wert des Pointers kopiert werden. :)

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Wilhelm M. schrieb:

>> Wo wird denn Dein Buffer data_read_buf gefüllt. Das fehlt immer noch ...

>
1
> static int i2c_drv_data_get(void) {
2
> 
3
>     static int i = 0;
4
>     data_read_buf[i++] = I2C1RCV;
5
>     if (i == 100)i = 0;
6
> 
7
>     return TRUE;
8
> }
9
>
>
> Das Buffer wird hier gefüllt. Es geht aber wie gesagt darum, dass die
> Daten nicht an den Wert des Pointers kopiert werden. :)

Oh man, und wo / wie wird das aufgerufen?

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Aaron K. schrieb:
>> Wilhelm M. schrieb:
>
>>> Wo wird denn Dein Buffer data_read_buf gefüllt. Das fehlt immer noch ...
>
>>
1
> 
2
>> static int i2c_drv_data_get(void) {
3
>>
4
>>     static int i = 0;
5
>>     data_read_buf[i++] = I2C1RCV;
6
>>     if (i == 100)i = 0;
7
>>
8
>>     return TRUE;
9
>> }
10
>>
>>
>> Das Buffer wird hier gefüllt. Es geht aber wie gesagt darum, dass die
>> Daten nicht an den Wert des Pointers kopiert werden. :)
>
> Oh man, und wo / wie wird das aufgerufen?

Wie gesagt, dass funktioniert alles soweit... Es geht wirklich nur darum 
warum der Wert des Pointers nicht geändert wird. Aber falls es hilft 
schicke ich gerne noch den restlichen code :)
1
/*
2
 * manages events of i2c_drv. Has to be called periodically (higher frequency than i2c events)
3
 *
4
 * @since 1.0.0
5
 * @category hardware
6
 * @param {void}
7
 * @returns {void}
8
 * @example none
9
 */
10
int i2c_drv_manager(void) {
11
12
    static int i = 0;
13
14
    if (busy_flag == FALSE) {
15
        return 1;
16
    }
17
18
    switch (cmd_buf[i]) {
19
20
            //transmit
21
        case I2C_DRV_CMD_TX_START:
22
            if (i2c_drv_start_set_check() == TRUE) {
23
                break;
24
            } else {
25
                return 0;
26
            }
27
        case I2C_DRV_CMD_TX_RESTART:
28
            if (i2c_drv_restart_set_check() == TRUE) {
29
                break;
30
            } else {
31
                return 0;
32
            }
33
        case I2C_DRV_CMD_TX_STOP:
34
            if (i2c_drv_stop_set_check() == TRUE) {
35
                break;
36
            } else {
37
                return 0;
38
            }
39
        case I2C_DRV_CMD_TX_ACK:
40
            if (i2c_drv_ack_set_check() == TRUE) {
41
                break;
42
            } else {
43
                return 0;
44
            }
45
        case I2C_DRV_CMD_TX_NACK:
46
            if (i2c_drv_nack_set_check() == TRUE) {
47
                break;
48
            } else {
49
                return 0;
50
            }
51
        case I2C_DRV_CMD_TX_DATA:
52
            if (i2c_drv_data_set_check() == TRUE) {
53
                break;
54
            } else {
55
                return 0;
56
            }
57
58
            //recieve
59
        case I2C_DRV_CMD_RX_ACK:
60
            if (i2c_drv_ack_get_check() == TRUE) {
61
                i2c_drv_ack_get();
62
                break;
63
            } else {
64
                return 0;
65
            }
66
        case I2C_DRV_CMD_RX_NACK:
67
            if (i2c_drv_nack_get_check() == TRUE) {
68
                i2c_drv_nack_get();
69
                break;
70
            } else {
71
                return 0;
72
            }
73
        case I2C_DRV_CMD_RX_DATA:
74
            if (i2c_drv_data_get_check() == TRUE) {
75
                i2c_drv_data_get();
76
                break;
77
            } else {
78
                return 0;
79
            }
80
81
            //general
82
        case I2C_DRV_CMD_END:
83
            break;
84
    }
85
86
    //skip first cmt incremention, then increment every time
87
    static int first_flag = TRUE;
88
89
get_next_instruction:
90
    if (first_flag == TRUE) {
91
        first_flag = FALSE;
92
    } else {
93
        i += 1;
94
        if (i == 100)i = 0;
95
    }
96
97
    //transmit
98
    switch (cmd_buf[i]) {
99
100
        case I2C_DRV_CMD_TX_START:
101
            i2c_drv_start_set();
102
            return 0;
103
            break;
104
        case I2C_DRV_CMD_TX_RESTART:
105
            i2c_drv_restart_set();
106
            return 0;
107
            break;
108
        case I2C_DRV_CMD_TX_STOP:
109
            i2c_drv_stop_set();
110
            return 0;
111
            break;
112
        case I2C_DRV_CMD_TX_ACK:
113
            i2c_drv_ack_set();
114
            return 0;
115
            break;
116
        case I2C_DRV_CMD_TX_NACK:
117
            i2c_drv_nack_set();
118
            return 0;
119
            break;
120
        case I2C_DRV_CMD_TX_DATA:
121
            i2c_drv_data_set();
122
            return 0;
123
            break;
124
125
            //recieve
126
        case I2C_DRV_CMD_RX_ACK:
127
            if (i2c_drv_ack_get_check() == TRUE) {
128
                i2c_drv_ack_get();
129
                goto get_next_instruction;
130
                return 0;
131
                break;
132
            } else {
133
                return 0;
134
            }
135
        case I2C_DRV_CMD_RX_NACK:
136
            if (i2c_drv_nack_get_check() == TRUE) {
137
                i2c_drv_nack_get();
138
                goto get_next_instruction;
139
                return 0;
140
                break;
141
            } else {
142
                return 0;
143
            }
144
        case I2C_DRV_CMD_RX_DATA:
145
            if (i2c_drv_data_get_check() == TRUE) {
146
                i2c_drv_data_get();
147
                goto get_next_instruction;
148
                return 0;
149
                break;
150
            } else {
151
                return 0;
152
            }
153
154
            //general
155
        case I2C_DRV_CMD_END:
156
            busy_flag = FALSE;
157
158
            return 1;
159
            break;
160
    }
161
162
    return 1;
163
}

von Wilhelm M. (wimalopaan)


Lesenswert?

Ich vermute jetzt mal, dass Du eigentlich ein FIFO erstellen wolltest. 
Das gibt Dein Code aber nicht her. Wenn also die Daten vom I2C langsamer 
eintreffen als Deine main-loop, dann geht es eben nicht, weil der Leser 
aus der FIFO den Schreiber in die FIFO überholt.

Edit: Bzw. Deine main-loop wir ggf. sogar verlassen!

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
>  *
>  * @since 1.0.0
>  * @category hardware
>  * @param {void}
>  * @returns {void}
>  * @example none
>  */

Schönes Beispiel für falsche (Doku-) Kommentare

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Ich vermute jetzt mal, dass Du eigentlich ein FIFO erstellen wolltest.
> Das gibt Dein Code aber nicht her. Wenn also die Daten vom I2C langsamer
> eintreffen als Deine main-loop, dann geht es eben nicht, weil der Leser
> aus der FIFO den Schreiber in die FIFO überholt.

Dei Main kann nicht schneller sein als der manager daten bereitstellt. 
Da die Daten erst aus dem Buffer ausgelesen werden, wenn die letzte 
Nachricht über den Manager vollständig abgearbeitet wurde.

Und ja es ist Fifo/Ringbuffer. Aber auch das stellt kein Problem dar. 
Wie ich bereits erwähnt habe...

Ich möchte Daten aus einem Buffer, welche ungleich null sind an den Wert 
eines Pointers kopieren. Das funktioniert jedoch nicht, weil die Daten 
die als Wert des Pointers abgespeichert nach wie vor 0 betragen, obwohl 
im eigentliche Buffer Daten ungleich 0 sind...

Zugegeben das Fifo ist etwas eigensinnig gecodet. Aber es funktioniert 
beim debuggen tadellos :) Es handelt sich hierbei eher um eine 
Auswertung eines Sensors. Aus dem Grund sind solche Feinheiten (wie ein 
gut lesbares/wartbares FIFO) auf später aufgeschoben.

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Aaron K. schrieb:
>>  *
>>  * @since 1.0.0
>>  * @category hardware
>>  * @param {void}
>>  * @returns {void}
>>  * @example none
>>  */
>
> Schönes Beispiel für falsche (Doku-) Kommentare

Danke wird verbessert. Vier Augen sehen immernoch mehr als 2 ;)

von Aaron K. (aaron_b_k)


Lesenswert?

Wilhelm M. schrieb:
> Ich vermute jetzt mal, dass Du eigentlich ein FIFO erstellen wolltest.
> Das gibt Dein Code aber nicht her. Wenn also die Daten vom I2C langsamer
> eintreffen als Deine main-loop, dann geht es eben nicht, weil der Leser
> aus der FIFO den Schreiber in die FIFO überholt.
>
> Edit: Bzw. Deine main-loop wir ggf. sogar verlassen!
1
int main(void) {
2
3
    TRISAbits.TRISA0 = OUTPUT;
4
    TRISAbits.TRISA1 = OUTPUT;
5
6
    i2c_drv_init();
7
8
    int i = 0;
9
    for (i = 0; i < 0xffff; i++)continue;
10
    for (i = 0; i < 0xffff; i++)continue;
11
    for (i = 0; i < 0xffff; i++)continue;
12
13
    int data_bridge = 0;
14
    int data_temperature = 0;
15
16
    while (1) {
17
18
        if (i2c_drv_manager() == 1) {
19
20
            for (i = 0; i < 0xffff; i++)continue;
21
22
            LATAbits.LATA1 = 1;
23
            pressure_sensor_start_measurement();
24
            LATAbits.LATA1 = 0;
25
26
            volatile int tmp = 0;
27
            i2c_drv_read_data_get(&tmp);
28
            data_bridge = tmp << 8;
29
            i2c_drv_read_data_get(&tmp);
30
            data_bridge += tmp;
31
32
            i2c_drv_read_data_get(&tmp);
33
            data_temperature = tmp << 3;
34
            i2c_drv_read_data_get(&tmp);
35
            data_temperature += tmp >> 5;
36
37
            tmp = 0;
38
        }
39
    }
40
41
    return 1;
42
}

Wie kann der Main-Loop hier verlassen werden? Einmal in der While kein 
zurück mehr. Gibt kein Goto, Return oder break innerhalb der Schleife. 
Übersehe ich da was ???

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Wie kann der Main-Loop hier verlassen werden? Einmal in der While kein
> zurück mehr. Gibt kein Goto, Return oder break innerhalb der Schleife.
> Übersehe ich da was ???

Ja, mein Fehler. Hatte Deinen Code falsch im Kopf.

von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> Zugegeben das Fifo ist etwas eigensinnig gecodet. Aber es funktioniert
> beim debuggen tadellos :)

Ich kann kein FiFo erkennen.

Und was funktioniert beim Debuggen?

von Aaron K. (aaron_b_k)


Lesenswert?

So habe mein Fehler....

In der Main wird der Manager augerufen bevor eine Nachricht in Auftrag 
gegeben wird (pressur_sensor_start_measurement). Dadurch werden zu 
Beginn Daten aus dem Buffer ausgelesen die nocht nicht existent sind.

Ich dachte das ist nicht weiterschlimm (wie gesagt Testlauf) und habe es 
ignoriert. Was dabei logischerweise jedoch auch passiert ist, dass der 
Incrementor für die Buffer-Elemente so immer auf Daten verweist die noch 
nicht ausgelesen wurden...

Also um die Überschrift dieses Threads zu beantworten. Ich habe komische 
Sachen mit Pointern gemacht.

Danke für jeden Beitrag :)

P.S.: Jetzt klappt alles wie es soll :D

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Aaron K. schrieb:
> n der Main wird der Manager augerufen bevor eine Nachricht in Auftrag
> gegeben wird (pressur_sensor_start_measurement). Dadurch werden zu
> Beginn Daten aus dem Buffer ausgelesen die nocht nicht existent sind.

Genau das habe ich gesagt: Du hast keinen FiFo!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Aaron K. schrieb:
1
> int i = 0;
2
>     for (i = 0; i < 0xffff; i++)continue;
3
>     for (i = 0; i < 0xffff; i++)continue;
4
>     for (i = 0; i < 0xffff; i++)continue;

Du wirst Dich wundern, was Deine "Verzögerungsschleifen" bewirken, 
sobald Du den Optimierer einschaltest. Diese Schleifen werden dann 
nämlich gnadenlos wegoptimiert.

Übrigens ist das lediglich ein Feature Deines Compilers, wenn er diese 
Schleifen tatsächlich ohne Optmierung stehen lässt. Verlassen kannst Du 
Dich darauf nicht. Code, welcher keinen Effekt hat, kann nämlich vom 
Compiler immer wegoptimiert werden - egal in welcher 
Optimierungsstufe. Von daher sehe ich das mal als nicht-portablen Code 
an.

Aaron K. schrieb:
> Aber es funktioniert beim debuggen tadellos :)

Klar, weil dann eben Dein Code nicht die reinkommenden I2C-Daten 
"überholt", Wilhelm hat das Problem schon vorher einwandfrei erkannt.

Aaron K. schrieb:
> Wie gesagt, dass funktioniert alles soweit...

Wie Du nun gesehen hast, funktionierte das Füllen des Arrays doch nicht 
"soweit" korrekt, weil Du den Parameter "Zeit" einfach nicht 
berücksichtigt hast.

Deshalb ein Tipp für die Zukunft: Versuche zukünftig nicht mehr, den 
Leser durch Behauptungen, die sich im nachhinein als falsch 
herausstellen, in die Irre zu führen und lediglich den Codeschnipsel, wo 
Du den Fehler vermutest, zu posten. Du zwingst sonst den Leser, nur in 
Deine gewünschte Richtung zu denken. Das hat aber keinen Mehrwert - im 
Gegenteil: Du verzögerst damit die Problemfindung.

von Aaron K. (aaron_b_k)


Lesenswert?

Jo stimmt alles was du geschrieben hast. Die For-Schleifen werden später 
definitiv durch Timer-Routinen abgelöst. Das war nur der erste Versuch 
Daten aus dem Sensor zu bekommen. Und Timer initialisieren dauert zwar 
nicht lang aber ein paar For-Schleifen iwo reinzuschreiben tuts auch und 
dauert noch weniger lang :D

Zum Thema Thread schreiben. Tipp werde ich beherzigen. :)

: Bearbeitet durch User
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.