Array wird nicht kleiner, obwohl in Funktion definiert

OP #4750442
Lesenswert?
• ▲
▼
Ich experimantiere gerade mit den 1Wire Sensoren DS18x20 rum.

Hier ein Auszug aus dem Programm (vieles aus dem Forum zusammengeklaut 
;) ):

/**
* Liest die Adressen alle Sensoren aus und gibt sie zurück
*/
void scan_bus(uint8_t addresses[MAX_SENSORS][8]) {

    uint8_t id[8], diff;
    uint8_t i = 0, z = 0;
    char s[10];

    for (diff = SEARCH_FIRST; diff != LAST_DEVICE;) {
        diff = w1_rom_search(diff, id);

        for (z = 0; z < 8; z++) {
            addresses[i][z] = id[z];
  }
}

void read_temp() {
    uint8_t addresses[MAX_SENSORS][8];

    scan_bus(addresses);

  for (z = 0; z < MAX_SENSORS; z++) {
    if (!addresses[z][0]) {
      break;
    }
                // fürs debugging mal ausgeben:
    sprintf(s, "Sensor %d\t", z);
    uart_puts(s);
    for (uint8_t x = 0; x < 8; x++) {
      sprintf(s, "%02X:", addresses[z][x]);
      uart_puts(s);
    }
    uart_puts("\n\r");
  }


}

int main {
    while(1) {
        read_temp();
         _delay_ms(5000);
    }
}

Das tut auch erst mal ABER
wenn ich am Bus einen von zwei Sensoren ziehe, steht in addresses[1] 
plötzlich der Wert des ersten, erwarten würde ich aber 
00:00:00:00:00:00:00:00.
Stecke ich den wieder rein, dann steht in addresses[1] wieder der 
richtige Wert. Ziehe ich ihn wieder raus, na Ihr wisst schon ....

Zweite Frage:
Aus der Funktion w1_rom_search bekommme ich über uint8_t id[8] die 
HardwareAdresse. Die ich dann über so eine komische for-Schleife an 
addresses zuweise. Geht das nicht auch eleganter?
Ich denke an Pointer, habe ich aber nicht hin bekommen.
#4750464
Lesenswert?
• ▲
▼
Ich kann mir kaum vorstellen, dass in adresses[1][] überhaupt 
irgendetwas anderes als zufällige Werte drin stehen.
In scan_bus() wird i nicht erhöht, ist also immer 0, daher ändert sich 
immer nur adresses[0][].
Wozu char s[10] in scan_bus() deklariert wird bleibt auch ein Rätsel.

Generell ist es ja eher so, dass so ein Scan einmalig beim Start der 
Hardware gemacht wird. Ob das "plug-and-play" fähig ist müsste man 
erstmal prüfen.
Gast #4750486
Lesenswert?
• ▲
▼
Johannes A. schrieb:
> wenn ich am Bus einen von zwei Sensoren ziehe, steht in addresses[1]
> plötzlich der Wert des ersten, erwarten würde ich aber
> 00:00:00:00:00:00:00:00.

warum erwartest du das? Wer soll dort die 00:00 ... reinschreiben?

Du musst dir vermutlich selber merken, wie viele Device im Array gueltig 
sind.
OP #4750487
Lesenswert?
• ▲
▼
Konnte ich mir nicht vorstellen, habs trotzdem getestet.
Nein ein Reset ist nicht nötig. Ein Bus-Reset setzt keine Variablen 
zurück und wo nix ist, kannn nix antworten. Das ist ein Softwareproblem!
Ich habe ein Array das nicht wieder auf Null oder leer gesetzt wird, 
obwohl die Funktion ja verlassen wird.
OP #4750497
Lesenswert?
• ▲
▼
Habe gerade die Sensoren vertauscht, im Sinne von welcher gezogen wird 
und welcher drinn bleibt.
Da die Dinge in Reihenfolge der Adressen abgefragt werden und antworten, 
ist es je nach Adresse so, das entweder zwei mal die gleiche ausgegeben 
wird, (wenn vorher der Einzelne auf [1] stand) oder sich gar nichts 
ändert. Debugausgaben zeigen an, das wirklich vernüftige Daten 
ausgelesen werden. Also nix mit fehlendem Bus-Reset oder so.
Gast #4750504
Lesenswert?
• ▲
▼
Johannes A. schrieb:
> Da die Dinge in Reihenfolge der Adressen abgefragt werden und antworten,
> ist es je nach Adresse so, das entweder zwei mal die gleiche ausgegeben
> wird, (wenn vorher der Einzelne auf [1] stand) oder sich gar nichts
> ändert.

die 2. wir nicht ausgegeben, die schleife wird woher beeendet. Sie steht 
nur noch drin.

mache doch vorher man alles leer (memset)
OP #4750507
Lesenswert?
• ▲
▼
Das würde bedeuten, das das
    uint8_t addresses[MAX_SENSORS][8];
in read_temp() nur einmal im Leben des gesamten Programms ausgeführt und 
der Stack nicht aufgeräumt wird. Ist aber nicht mein Verständnis.
Sollte nicht bei jedem read_temp() die Variable neu erzeugt werden. Ich 
habe sich ja nicht static oder global gemacht.
Gast #4750513
Lesenswert?
• ▲
▼
mache doch einfach mal
1
void scan_bus(uint8_t addresses[MAX_SENSORS][8]) {
2

3
    uint8_t id[8], diff;
4
    uint8_t i = 0, z = 0;
5
    char s[10];
6

7
    memset(addresses, 0, sizeof( addresses) );
8
    for (diff = SEARCH_FIRST; diff != LAST_DEVICE;) {
9
        diff = w1_rom_search(diff, id);
10

11
        for (z = 0; z < 8; z++) {
12
            addresses[i][z] = id[z];
13
  }
14
}

oder lass scan_bus als return die anzahl der device ausgeben.
#4750515
Lesenswert?
• ▲
▼
Machs halt gleich richtig, und lasse dir von scan_bus() die Anzahl der 
gefundenen Devices zurückgeben
1
int scan_bus(uint8_t addresses[MAX_SENSORS][8]) 
2
{
3
  (...)
4
    i++;
5
  (...)
6

7
  return i;
8
}
9

10

11
void read_temp() {
12
  uint8_t addresses[MAX_SENSORS][8];
13
  int devices;
14

15
  devices = scan_bus(addresses);
16

17
  for (z = 0; z < devices; z++) {
18
   (...)
19
}

Dann kannst du auch
1
 if (!addresses[z][0]) {

rausschmeissen, ist ja eh nicht zuverlässig, wenn das oberste byte der 
Adresse mal zufällig 0 sein sollte...


Update:
Peter II schrieb:
> oder lass scan_bus als return die anzahl der device ausgeben.

Wenn sich 2 schon so einig sind... ;-)
OP #4750528
Lesenswert?
• ▲
▼
@Peter II

Dein Vorschlag tut nicht. Nix wird genullt. Bekomme aber eine 
Warnmeldung vom Compiler:
warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as 
the destination; did you mean to dereference it? 
[-Wsizeof-pointer-memaccess]
memset(addresses, 0, sizeof( addresses) );

@Peter II &  @(easylife)

Natürlich kann ich das so lösen, wie Ihr beide vorgeschlagen, das löst 
aber nicht mein Verstädnisproblem.
#4750536
Lesenswert?
• ▲
▼
Dein Verständnisproblem kann man natürlich auch nur ahnen.
Ich denke, du gehst davon aus, dass addresses[][] irgendwo genullt 
werden würde.
Das passiert aber im günstigsten Fall nur bei Programmstart (wovon man 
übrigens nicht ausgehen sollte).
scan_bus() überschreibt einfach nur Werte im Array, das in read_temp() 
deklariert wurde.
Beim erneuten Aufruf von scan_bus() bleiben die alten Werte natürlich 
erhalten, weil scan_bus ja weniger Adressen ins Array schreibt (bei dir 
momentan 1, d.h. die 2. Adresse bleibt erhalten).
OP #4750537
Lesenswert?
• ▲
▼
habe gerade folgendes gemacht:

in read_temp()

uart_puts("Init addresses[MAX_SENSORS][8] ...\t");
uint8_t addresses[MAX_SENSORS][8];
uart_puts("Init addresses[MAX_SENSORS][8] fertig\n\r");

Es wird wirklich uint8_t addresses[MAX_SENSORS][8]; jede mal neu 
ausgeführt. Offensichtlich werden aber Arrays im Ggs. zu anderen 
Variablen NICHT aufgeräumt bzw. ausgenullt. Bei int usw. soll das ja 
angeblich gemacht werden. C ist ne komische Sprache, oder ich hab was 
nicht verstanden.
Gast #4750538
Lesenswert?
• ▲
▼
Johannes A. schrieb:
> Es wird wirklich uint8_t addresses[MAX_SENSORS][8]; jede mal neu
> ausgeführt.

das ist überhaupt kein Befehl der ausgeführt werden kann.

Es ist eine Anweisung auf dem Stack platz für ein paar Byte 
einzurichten. Dabei wird überhaupt nicht genullt.

Dann müsste man schon
1
uint8_t addresses[MAX_SENSORS][8] = {0};

schreiben.
#4750541
Lesenswert?
• ▲
▼
Johannes A. schrieb:
> C ist ne komische Sprache, oder ich hab was
> nicht verstanden.

letzteres.
1
uint8_t addresses[MAX_SENSORS][8];

wird nicht ausgeführt, sondern reserviert Speicher.

Der Aufruf scan_bus(addresses) übergibt dann einen Pointer auf diesen 
Speicherbereich an scan_bus();

In C wird speicher nie automatisch initialisiert. Auch andere Variablen 
nicht.
Manche Compiler machen das zwar, davon darf man aber nicht ausgehen.

Update: ich halte mich jetzt hier raus, das ist ja beängstigend, wie 
Peter und ich im Mintentakt das gleiche sagen... ;-)
Gast #4750543
Lesenswert?
• ▲
▼
Joe F. schrieb:
> In C wird speicher nie automatisch initialisiert. Auch andere Variablen
> nicht.
doch, nur nicht bei lokalen Variablen. Globale werden immer 
initialisiert.

> Manche Compiler machen das zwar, davon darf man aber nicht ausgehen.
es ist genau definiert, was initialisiert werden muss und was nicht.
OP #4750583
Lesenswert?
• ▲
▼
uint8_t addresses[MAX_SENSORS][8] = {{0}};
hat das Problem gelöst.
Scheinbar habe ich das falsch verstanden.

Allerdings:

void test_var() {
  uint8_t z;
  char s[10];
  z++;
  sprintf(s, "%d\n\r", z);
  uart_puts(s);

}


von main periodisch aufgerufen, bringt immer 1
schreibe ich static uint8_t z dann wird der Wert hochgezählt.
Offenischtlich handhabt das der avr-gcc unterschiedlich.
Bekommen aber bei compilieren den Hinweis
In function ‘test_var’:
warning: ‘z’ is used uninitialized in this function

Damit gestehe icvh meinen Denkfehler ein ;)

Vielen Dank für Eure Mühe und Geduld mit mir!!!

Hat jemand vielleicht noch ein Lösung für meine zweite Frage oben?
Gast #4750588
Lesenswert?
• ▲
▼
Johannes A. schrieb:
> von main periodisch aufgerufen, bringt immer 1
> schreibe ich static uint8_t z dann wird der Wert hochgezählt.
> Offenischtlich handhabt das der avr-gcc unterschiedlich.

nein macht er nicht. Es steht nur zufällig eine 0 drin. Das ganze ist 
abhängig vom Stack-Inhalt. (um genau zu sein, wird z vermutlich nur ein 
Register sein, wo zufällig eine 0 drin steht).

Darauf verlassen kann man sich auf keine Fall.

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