Forum: Mikrocontroller und Digitale Elektronik Array an Array in Struktur übergeben


von Bastian (Gast)


Lesenswert?

Hallo,

ich hätte da mal eine Frage zu Thema Arrays und deren Übergabe an 
Funktionen.

Ich habe eine Schnittstellen-Funktion ( CAN_Send() ) welche eine 
CAN-Nachricht verschickt.

Wie die übergebenen Nachricht verschickt wird, hängt von dem verwendeten 
System ab. Ich benutze in diesem Fall einen AT90CAN und die „Universelle 
CAN Bibliothek“ von kreatives-chaos.com.
1
void CAN_Send(uint8_t *msg) // Array mit 8 Elementen wird übergeben 
2
{  
3
         // Struktur und Funktion aus der „Universelle CAN Bibliothek“
4
  can_t msg_transmit;  
5
  msg_transmit.id = 0x111; 
6
  msg_transmit.length = 8;
7
  //msg_transmit.data = msg;  // Wie geht es hier weiter?
8
  can_send_message(&msg_transmit);  
9
}

Wie übergebe ich denn dem data-Feld (auch ein uint8_t Array mit 8 
Elementen) in der Struktur msg_transmit am besten das an die Funktion 
CAN_Send übergebene Array?

Ich könnte jedes Element einzeln übergeben, oder?
1
msg_transmit.data[0] = msg[0];
2
msg_transmit.data[1] = msg[1];
3
.
4
.
5
.
6
msg_transmit.data[7] = msg[7];

Der Funktion CAN_Send wird ja ein Pointer übergeben, also die Adresse 
des ersten Elementes des Arrays. Richtig?
Dann könnte ich doch in das ersten Element des Arrays Data in der 
Struktur msg_transmit diese Adresse kopieren.
Würde das so funktionieren?
Mir ist aber leider nicht klar, wie die Syntax dazu aussehen soll?

Das hier hat mir leider auch nicht weitergeholfen:

http://home.fhtw-berlin.de/~junghans/cref/SYNTAX/struct.html#pointers

Vielleicht kann einer von euch mir auf die Sprünge helfen. Danke im 
Voraus!

von Karl H. (kbuchegg)


Lesenswert?

Bastian schrieb:

> Ich könnte jedes Element einzeln übergeben, oder?

zuweisen.
übergeben ist was anderes
>
>
1
> msg_transmit.data[0] = msg[0];
2
> msg_transmit.data[1] = msg[1];
3
> .
4
> .
5
> .
6
> msg_transmit.data[7] = msg[7];
7
>

ja, kannst du.
Du kannst aber auch ganz einfach eine Schleife dafür benutzen
1
   for( i = 0; i < 8; i++ )
2
     msg_transmit.data[i] = msg[i];

oder du kannst memcpy() dafür benutzen.

> Der Funktion CAN_Send wird ja ein Pointer übergeben, also die Adresse
> des ersten Elementes des Arrays. Richtig?

Genau das steht doch im Source Text.
Und ja. Das ist die Art und Weise, wie Arrays an Funktionen übergeben 
werden. In dem sie nicht wie alle anderen Werte als Kopie übergeben 
werden, sondern in dem der Funktion die Startadresse der Daten im 
Speicher mitgeteilt wird.

> Dann könnte ich doch in das ersten Element des Arrays Data in der
> Struktur msg_transmit diese Adresse kopieren.

Kannst du machen. Die Frage ist, ob die Funktion can_send_message dann 
damit was anfangen kann. Dann auf dem CAN Bus willst du ja nicht die 
Adresse im Speicher verschicken, auf der an deinem µC die Daten im 
Speicher liegen würden. An diese Daten kommt ja der Empfänger der Daten 
nicht heran. Mit der Adresse hat der also nichts angefangen. Der will 
schon die Daten selber haben. Also musst du ihm die auch geben.

> Würde das so funktionieren?

Die Frage an sich ist schon ok. Nur ist das keine Lösung. Selbst wenn du 
die Antwort dazu kennen würdest.
Wenn die Funktion can_send_message davon ausgeht, dass die zu 
versendenden Daten in die STruktur can_t einkopiert wurden, dann musst 
du die dort auch einfüllen. Oder aber du überarbeitest die Struktur und 
die Funktion can_send_message.

von Bastian (Gast)


Lesenswert?

Ich habe mal in der Bibliothek von kreatives-chaos.com rumgesucht.
Wenn ich das richtig Verstanden habe, wird für einen AT90CAN aus 
can_send_message() at90can_send_message(), was dann 
at90can_copy_message_to_mob() aufruft.
1
void at90can_copy_message_to_mob(const can_t *msg)
2
{
3
  // write DLC (Data Length Code)
4
  CANCDMOB = msg->length;
5
  
6
  #if SUPPORT_EXTENDED_CANID
7
  
8
  if (msg->flags.extended) {
9
    // extended CAN ID
10
    CANCDMOB |= (1 << IDE);
11
    
12
    CANIDT4 = (uint8_t)  msg->id << 3;
13
    
14
    uint32_t temp = msg->id << 3;
15
    uint8_t *ptr = (uint8_t *) &temp;
16
    
17
    CANIDT3 = *(ptr + 1);
18
    CANIDT2 = *(ptr + 2);
19
    CANIDT1 = *(ptr + 3);
20
  }
21
  else {
22
    // standard CAN ID
23
    CANIDT4 = 0;
24
    CANIDT3 = 0;
25
    CANIDT2 = (uint8_t)  msg->id << 5;
26
    CANIDT1 = (uint16_t) msg->id >> 3;
27
  }
28
  
29
  #else
30
  
31
  CANIDT4 = 0;
32
  CANIDT3 = 0;
33
  CANIDT2 = (uint8_t)  msg->id << 5;
34
  CANIDT1 = (uint16_t) msg->id >> 3;
35
  
36
  #endif
37
  
38
  if (msg->flags.rtr) {
39
    CANIDT4 |= (1<<RTRTAG);
40
  }
41
  else {
42
    const uint8_t *p = msg->data;
43
    for (uint8_t i = 0;i < msg->length;i++) {
44
      CANMSG = *p++;
45
    }
46
  }
47
}
48
49
// ----------------------------------------------------------------------------
50
uint8_t at90can_send_message(const can_t *msg)
51
{
52
  // check if there is any free MOb
53
  uint8_t mob = _find_free_mob();
54
  if (mob >= 15)
55
    return 0;
56
  
57
  // load corresponding MOb page ...
58
  CANPAGE = (mob << 4);
59
  
60
  // clear flags
61
  CANSTMOB &= 0;
62
  
63
  // ... and copy the data
64
  at90can_copy_message_to_mob( msg );
65
  
66
  // enable interrupt
67
  _enable_mob_interrupt(mob);
68
  
69
  ENTER_CRITICAL_SECTION;
70
  #if CAN_TX_BUFFER_SIZE == 0
71
    _free_buffer--;
72
  #else
73
    _transmission_in_progress = 1;
74
  #endif
75
  LEAVE_CRITICAL_SECTION;
76
  
77
  // enable transmission
78
  CANCDMOB |= (1<<CONMOB0);
79
  
80
  return (mob + 1);
81
}
82
83
#endif  // SUPPORT_FOR_AT90CAN__


Wir hier nicht auch einfach die Adresse des Pointers erhöht?
1
    const uint8_t *p = msg->data;
2
    for (uint8_t i = 0;i < msg->length;i++) {
3
      CANMSG = *p++;
4
    }

Könnte ich jetzt nicht msg.data (hier msg_transmit.data) auf den der 
Funktion CAN_Send() übergebenen Pointer "umbiegen"?

von Karl H. (kbuchegg)


Lesenswert?

Bastian schrieb:

> Könnte ich jetzt nicht msg.data (hier msg_transmit.data) auf den der
> Funktion CAN_Send() übergebenen Pointer "umbiegen"?

Kannst du.

Aber der Weg, das zu tun, beginnt damit, das man in der Struktur can_t 
erst mal das Array data durch einen Pointer ersetzt. Allerdings muss man 
dann quer durch alle Funktionen begutachten, ob das ueberall moeglich 
ist. In solchen Faellen geh ich dann her und aendere auch gleich den 
Namen des Members. dataPtr wuerde sich z.b. anbieten. Dann sucht mir 
naemlich der Compiler raus, wo data urspruenglich verwendet wurde und 
ich kann entscheiden, ob an diesen Stellen Codeaenderungen notwendig 
sind oder ob der Array/Pointer Dualismus zu meinem Vorteil arbeitet.

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.