Vermtliches Pointer Problem

Gast #1742999
Lesenswert?

Hallo Leute, kann mal bitte jemand in den Code gucken und mir sagen, 
warum die werte in dem Struct nicht aktualisiert werden, bzw. nur 
unvollständig ich bekomme es irgendwie einfach nicht zum laufen...

Dankeschön
1
void ADC_Messung ()
2
{
3
  if (ADCprescaler >6)
4
  {
5
    PORT_CS_ADC_STEU &= ~( 1 << PIN_CS_ADC_STEU );
6
    SPCR =  (1<<SPE)  |  //SPI- Enable
7
        (1<<MSTR)  |
8
        (1<<SPR1);  //Set Master
9

10
    _delay_ms(10);
11

12
    switch (nextChannel)
13
    {
14
      case TempCh1:  read_adc(&(Ch1.Temperatur[2]));
15
              Ch1.Temperatur[2]&=0x0F;
16
              read_adc(&(Ch1.Temperatur[1]));
17
              read_adc(&(Ch1.Temperatur[0]));
18
              nextChannel=ULast1;
19
              break;
20
      case CurrCh1:  read_adc(&Ch1.Strom[2]);
21
              Ch1.Strom[2]&=0x0F;
22
              read_adc(&Ch1.Strom[1]);
23
              read_adc(&Ch1.Strom[0]);
24
              nextChannel=ULast1;
25
              break;
26
      case ULast1:  read_adc(&Ch1.Spannung[2]);
27
              Ch1.Spannung[2]&=0x0F;
28
              read_adc(&Ch1.Spannung[2]);
29
              read_adc(&Ch1.Spannung[2]);
30
              nextChannel=TempCh1;
31
              break;
32
      /*case TempCh2:  Ch2.Temperatur[2]=0x0F & read_adc();
33
              Ch2.Temperatur[1]=read_adc();
34
              Ch2.Temperatur[0]=read_adc();
35
              nextChannel=CurrCh2;
36
              break;
37
      case CurrCh2:  Ch2.Strom[2]=0x0F & read_adc();
38
              Ch2.Strom[1]=read_adc();
39
              Ch2.Strom[0]=read_adc();
40
              nextChannel=ULast2;
41
              break;
42
      case ULast2:  Ch2.Spannung[2]=0x0F & read_adc();
43
              Ch2.Spannung[1]=read_adc();
44
              Ch2.Spannung[0]=read_adc();
45
              nextChannel=TempCh1;
46
              //luefterregelung(&msb,&Ch1.PWM_Fan,1,&Ch1.temp_old,&Ch1.t_delta_sum);
47
              break;*/
48
    }
49
    PORT_CS_ADC_STEU |=  ( 1 << PIN_CS_ADC_STEU );
50
    _delay_ms(1);
51
    SPDR=nextChannel;
52
    while ( ! ( SPSR&(1<<SPIF) ) );
53
    SPDR=nextChannel;
54
    while ( ! ( SPSR&(1<<SPIF) ) );
55

56
    uint16_t msb=Ch1.Temperatur[2]<<11;
57
    msb|=Ch1.Temperatur[1]<<3;
58
    msb|=Ch1.Temperatur[0]>>3;
59
    ADCprescaler=0;
60
    uart_sendc('A');
61
//    uart_sendc(&Ch1.Temperatur[2]);
62
//    uart_sendc(&Ch1.Temperatur[1]);
63
//    uart_sendc(&Ch1.Temperatur[0]);
64
//    uart_sendc('B');
65
//    uart_sendc(&Ch1.Spannung[2]);
66
//    uart_sendc(&Ch1.Spannung[1]);
67
//    uart_sendc(&Ch1.Spannung[0]);
68

69
    //Einstellen des mächsten Kanals
70

71

72

73
  }
74
}
75

76
void read_adc (uint8_t *value)
77
{
78
  PORT_CS_ADC_STEU &= ~( 1 << PIN_CS_ADC_STEU );
79
  SPCR =  (1<<SPE)  |  //SPI- Enable
80
      (1<<MSTR)  |
81
      (1<<SPR1);  //Set Master
82
  SPDR=0b10101010;
83
  while ( ! ( SPSR&(1<<SPIF) ) );
84
  *value=SPDR;
85
}
#1743023
Lesenswert?

Antny schrieb:
> Hallo Leute, kann mal bitte jemand in den Code gucken und mir sagen,
> warum die werte in dem Struct nicht aktualisiert werden,

welche Struct?

> bzw. nur
> unvollständig

Welche werden aktualisiert, welche nicht?

> ich bekomme es irgendwie einfach nicht zum laufen...

Das könnte an deiner Codeformatierung liegen.
Viel zu dicht.


Das sieht seltsam aus:

>     switch (nextChannel)
>     {
>       case TempCh1:  read_adc(&(Ch1.Temperatur[2]));
>               Ch1.Temperatur[2]&=0x0F;
>               read_adc(&(Ch1.Temperatur[1]));
>               read_adc(&(Ch1.Temperatur[0]));
>               nextChannel=ULast1;
>               break;

beim nächsten Aufruf gehts also weiter mit ULast1


>       case CurrCh1:  read_adc(&Ch1.Strom[2]);
>               Ch1.Strom[2]&=0x0F;
>               read_adc(&Ch1.Strom[1]);
>               read_adc(&Ch1.Strom[0]);
>               nextChannel=ULast1;
>               break;

auch hier gehts beim nächsten mal weiter mit ULast1


>       case ULast1:  read_adc(&Ch1.Spannung[2]);
>               Ch1.Spannung[2]&=0x0F;
>               read_adc(&Ch1.Spannung[2]);
>               read_adc(&Ch1.Spannung[2]);
>               nextChannel=TempCh1;
>               break;

und wieder von vorne, beim nächsten mal mit TempCh1.

Wenn du ausserhalb nie nextChannel auf CurrCh1 setzt, wirst du den Fall 
das nextChannel irgendwann CurrCh1 ist, nie haben. Damit sind schon mal 
Ch1.Strom[2], [1], [0] ohne Werte. Ich vermute mal im Fall TempCh1 
sollte nextChannel eigentlich auf CurrCh1 gesetzt werden und nicht auf 
ULast1

Aus Analogiegründen sieht auch das seltsam aus:

>       case ULast1:  read_adc(&Ch1.Spannung[2]);
>               Ch1.Spannung[2]&=0x0F;
>               read_adc(&Ch1.Spannung[2]);
>               read_adc(&Ch1.Spannung[2]);
>               nextChannel=TempCh1;
>               break;

In allen anderen Fällen verteilst du die ADC Ergebnisse jeweils auf [2], 
[1], [0]. Nur hier nicht. Hier landen alle 3 Ergebnisse in [2], die 
letzte Zuweisung gewinnt.
Gast #1743034
Lesenswert?

Hallo danke für die schnelle Antwort, joa das ist "richtig" so weil ich 
den Code gerade komplett durchgeplügt habe um das System zu verstehen 
was da schief geht, allerdings bisher erfolglos.

Hier nocheinmal der komplette Code, TempCh1 usw. sind defines, später 
wenn es irgendwann mal laufen sollte... ist die switch/case- Struktur 
dazu gedacht periodisch die Kanäle durchzuscannen und die Structs zu 
aktualisieren.
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include "uart.h"
4
#include "config.h"
5
#include "twi.h"
6
#include <util/delay.h>
7
#include <avr/interrupt.h>
8
#define Startbit 2
9
#define Single_Ended 1
10

11
struct KanalMesswerte {
12
   uint8_t Temperatur[3];
13
   uint8_t Strom[3];
14
   uint8_t Spannung[3];
15
   uint8_t PWM_Fan;
16
   uint16_t temp_old;
17
   int16_t t_delta_sum;
18
}Ch1={"","","",PWM_Start,0},Ch2={"","","",PWM_Start,0};
19

20
uint8_t nextChannel=TempCh1; //Erster Kanal, welcher gelesen wird
21
volatile uint8_t ADCprescaler=0;
22

23

24
//Schreiben und konfigurieren des ADC's
25
void ADC_Messung ()
26
{
27
  if (ADCprescaler >6)
28
  {
29
    PORT_CS_ADC_STEU &= ~( 1 << PIN_CS_ADC_STEU );
30
    SPCR =  (1<<SPE)  |  //SPI- Enable
31
        (1<<MSTR)  |
32
        (1<<SPR1);  //Set Master
33

34
    _delay_ms(10);
35

36
    switch (nextChannel)
37
    {
38
      case TempCh1:  read_adc(&(Ch1.Temperatur[2]));
39
              Ch1.Temperatur[2]&=0x0F;
40
              read_adc(&(Ch1.Temperatur[1]));
41
              read_adc(&(Ch1.Temperatur[0]));
42
              nextChannel=TempCh1;
43
              break;
44
//      case CurrCh1:  read_adc(&Ch1.Strom[2]);
45
//              Ch1.Strom[2]&=0x0F;
46
//              read_adc(&Ch1.Strom[1]);
47
//              read_adc(&Ch1.Strom[0]);
48
//              nextChannel=ULast1;
49
//              break;
50
//      case ULast1:  read_adc(&Ch1.Spannung[2]);
51
//              Ch1.Spannung[2]&=0x0F;
52
//              read_adc(&Ch1.Spannung[2]);
53
//              read_adc(&Ch1.Spannung[2]);
54
//              nextChannel=TempCh1;
55
//              break;
56
      /*case TempCh2:  Ch2.Temperatur[2]=0x0F & read_adc();
57
              Ch2.Temperatur[1]=read_adc();
58
              Ch2.Temperatur[0]=read_adc();
59
              nextChannel=CurrCh2;
60
              break;
61
      case CurrCh2:  Ch2.Strom[2]=0x0F & read_adc();
62
              Ch2.Strom[1]=read_adc();
63
              Ch2.Strom[0]=read_adc();
64
              nextChannel=ULast2;
65
              break;
66
      case ULast2:  Ch2.Spannung[2]=0x0F & read_adc();
67
              Ch2.Spannung[1]=read_adc();
68
              Ch2.Spannung[0]=read_adc();
69
              nextChannel=TempCh1;
70
              //luefterregelung(&msb,&Ch1.PWM_Fan,1,&Ch1.temp_old,&Ch1.t_delta_sum);
71
              break;*/
72
    }
73
    PORT_CS_ADC_STEU |=  ( 1 << PIN_CS_ADC_STEU );
74
    _delay_ms(1);
75
    SPDR=nextChannel;
76
    while ( ! ( SPSR&(1<<SPIF) ) );
77
    SPDR=nextChannel;
78
    while ( ! ( SPSR&(1<<SPIF) ) );
79

80
    uint16_t msb=Ch1.Temperatur[2]<<11;
81
    msb|=Ch1.Temperatur[1]<<3;
82
    msb|=Ch1.Temperatur[0]>>3;
83
    ADCprescaler=0;
84
    uart_sendc('A');
85
    uart_sendc(&Ch1.Temperatur[2]);
86
    uart_sendc(&Ch1.Temperatur[1]);
87
    uart_sendc(&Ch1.Temperatur[0]);
88
//    uart_sendc('B');
89
//    uart_sendc(&Ch1.Spannung[2]);
90
//    uart_sendc(&Ch1.Spannung[1]);
91
//    uart_sendc(&Ch1.Spannung[0]);
92

93
    //Einstellen des mächsten Kanals
94

95

96

97
  }
98
}
99

100
void read_adc (uint8_t *value)
101
{
102
  PORT_CS_ADC_STEU &= ~( 1 << PIN_CS_ADC_STEU );
103
  SPCR =  (1<<SPE)  |  //SPI- Enable
104
      (1<<MSTR)  |
105
      (1<<SPR1);  //Set Master
106
  SPDR=0b10101010;
107
  while ( ! ( SPSR&(1<<SPIF) ) );
108
  *value=SPDR;
109
}
110

111

112

113

114

115
//Interrupt alle 37 ms
116
ISR(TIMER0_OVF_vect)
117
{
118
  TCNT0 = 0;
119
  ADCprescaler++;
120

121
}
#1743064
Lesenswert?

Ich kann mir nicht vorstellen, dass dich hier

    uart_sendc(&Ch1.Temperatur[2]);


das Low-Byte der Adresse interessiert, an der Ch1.Temperatur[2] 
gespeichert ist.

Hat dein Compiler da gar nichts dazu gesagt, dass die Funktion einen 
char haben möchte und du ihm aber einen unsigned char* (mit der Betonung 
auf *) anbietest?
#1743075
Lesenswert?

Johann L. schrieb:
> Antny schrieb:
>
>
1
> struct KanalMesswerte {
2
>     uint8_t Temperatur[3];
3
>     uint8_t Strom[3];
4
>     uint8_t Spannung[3];
5
>     uint8_t PWM_Fan;
6
>     uint16_t temp_old;
7
>     int16_t t_delta_sum;
8
> }Ch1={"","","",PWM_Start,0},Ch2={"","","",PWM_Start,0};
9
>
>
> Was sollen denn dies Initialiser??? Du initialisierst ein uint8-Array
> mit char*?

Ist zwar ein wenig seltsam, letzten Endes werden dadurch nur 
Temperatur[0], Strom[0] und Spannung[0] mit '\0' initialisiert, die 
anderen haben keine definierten Werte.

ist auch nichts anders als

   char Dummy[20] = "Hallo World";
Gast #1743173
Lesenswert?

@Mark uups richtig, der Ordnung halber...
@Karl- Heinz mensch auf dich ist immer noch Verlass, bei meinen ersten 
Gehversuchen mit dem µP hast du mir schon super das mit Bittoggeln mit 
Hilfe von und/ oder erklärt, und jetzt wieder den Fehler gefunden 
dankeschön :)
#1743240
Lesenswert?

Andreas Ferber schrieb:
> Doch, die Variablen haben static storage duration, deshalb werden alle
> nicht explizit aufgeführten Elemente implizit mit 0 initialisiert.

Bzw., um mich selbst zu ergänzen: selbst bei automatic storage duration 
werden bei teilweiser Initialisierung (sei es wegen weniger Elementen in 
einer Initializer-Liste oder eben auch einem Stringliteral) die 
restlichen Elemente implizit mit 0 initialisiert (bzw. NULL-Pointer bei 
Pointertypen). Siehe Absatz 21 in Abschnitt 6.7.8 im C99-Standard.

Andreas
#1743254
Lesenswert?

Ingrid^2: die Initialisierung des uint8_t-Arrays mit einem Stringliteral 
ist allerdings eigentlich nicht zulässig, nur "array of character 
type" darf so initialisiert werden, und "character type" sind 
ausschliesslich "char", "signed char" und "unsigned char".

Vermutlich wird man aber den Bastard C-Compiler From Hell suchen müssen, 
um einen zu finden, bei dem der Unterschied in diesem Fall wirklich 
relevant wird.

Andreas
Persönliche Seite #1743261
Lesenswert?

Andreas Ferber schrieb:
> ist allerdings eigentlich nicht zulässig, nur "array of character
> type" darf so initialisiert werden, und "character type" sind
> ausschliesslich "char", "signed char" und "unsigned char".

wird daran liegen das uint8_t eigentlich ein unsigned char ist. 
(typedef)

Über den Sinn und Unsinn, einen Zahlenwert mit dem NUL-Symbol zu 
initialisieren, kann man sich streiten :-D
#1743263
Lesenswert?

Andreas Ferber schrieb:

> Doch, die Variablen haben static storage duration, deshalb werden alle
> nicht explizit aufgeführten Elemente implizit mit 0 initialisiert.

Ah ja. Du hast natürlich recht.
Darauf hab ich jetzt nicht geachtet.

Ich geh normalerweise nach dem Grundsatz vor:
Wenn ich initialisiere, dann alles.

Das ist mir nämlich zu mühsam, bei einer Strukturänderung im Nachhinein 
wieder abzählen zu müssen, was ich initialisiert habe, was der Compiler 
für mich macht und was keine Initialisierung bekommt.
#1743266
Lesenswert?

Florian Löffler schrieb:

> Über den Sinn und Unsinn, einen Zahlenwert mit dem NUL-Symbol zu
> initialisieren, kann man sich streiten :-D

Ich denke das Problem wird gewesen sein, dass die korrekte Syntax nicht 
bekannt war
1
struct KanalMesswerte {
2
   uint8_t Temperatur[3];
3
   uint8_t Strom[3];
4
   uint8_t Spannung[3];
5
   uint8_t PWM_Fan;
6
   uint16_t temp_old;
7
   int16_t t_delta_sum;
8
}
9

10
 Ch1 = { { 0, 0, 0 },
11
         { 0, 0, 0 },
12
         { 0, 0, 0 },
13
         PWM_Start,
14
         0,
15
         0
16
       },
17

18
 Ch2 = { { 0, 0, 0 },
19
         { 0, 0, 0 },
20
         { 0, 0, 0 },
21
         PWM_Start,
22
         0,
23
         0
24
       };

Das ich von solchen 'all in one line' Rundumschlägen nicht viel halte, 
genausowenig von diesem 'möglichst alles in eine Deklaration quetschen 
und am besten noch ein typedef davor' Kompaktschreibweisen, sollte 
diejenigen die meinen Stil mittlerweile kennen, nicht weiter wundern.
#1743287
Lesenswert?

Karl heinz Buchegger schrieb:
> Ich geh normalerweise nach dem Grundsatz vor:
> Wenn ich initialisiere, dann alles.
>
> Das ist mir nämlich zu mühsam, bei einer Strukturänderung im Nachhinein
> wieder abzählen zu müssen, was ich initialisiert habe,

In aller Regel benutze ich bei struct-Initializern inzwischen 
grundsätzlich Designatoren, damit die Initialisierung komplett 
unabhängig von der Abfolge der struct-Felder wird. Erspart schonmal ein 
paar Fehlerquellen.

> was der Compiler
> für mich macht und was keine Initialisierung bekommt.

Wie gesagt, selbst bei automatischen Variablen, sobald auch nur ein 
einziges Feld initialisiert wird, wird der gesamte Rest (rekursiv) in 
jedem Fall auf 0 initialisiert, exakt wie es bei statischen Objekten der 
Fall wäre. Oder anders: ein "teilweise" initialisiertes Aggregate gibt 
es in C nur im Zusammenhang mit dynamischer Speicherverwaltung, in allen 
anderen Fällen wird entweder ganz oder garnicht initialisiert.

Andreas

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren