gcc array an mehrdimensionales array zuweisen

#7829746
Lesenswert?

Ich möchte per Pointer auf arrays zugreifen. Mehrere Arrays - also mehrere pointer in ein Pointer-array. Wie?

1
    u8  wr_bat_volt [] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
2
    u8* wr_bat_pow = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
3
    u8* wr_soc = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
4

5
  
6
  volatile uint8_t *reg[] = { &wr_bat_volt, &wr_bat_pow, &wr_soc };
7
....
8

9

10
void main(void)
11
//
12
{
13

14
    wr_bat_pow[1]=0xff;//<==geht
15
       //*reg[1][1] = 0xFF; //<==geht nicht
16
    *reg[8*1+1]=6;//??

Danke für Nachsicht und Unterstützung

Gast #7829763
Lesenswert?

Lösung:

1
#include <stdint.h>
2

3
typedef uint8_t u8;
4

5
u8 wr_bat_volt[] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
6
u8 wr_bat_pow[] = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
7
u8 wr_soc[] = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
8

9
u8* reg[] = {wr_bat_volt, wr_bat_pow, wr_soc};
10

11
int main()
12
{
13
    reg[0][0] = 0xFF; // overwrite first byte in wr_bat_volt
14
    reg[2][7] = 0xAA; // overwrite last byte in wr_soc
15
}

Tipp: Benutze die Qt Creator IDE. Sie zeigt neben den fehlerhaften Zeilen nützliche Hilfestellungen an. Sie hilft auch, Fehler zu vermeiden, die der Compiler nicht melden würde.

Du solltest vielleicht wissen, dass die Namen der Arrays (hier: wr_bat_volt, wr_bat_pow, wr_soc) bereits Zeiger sind. Deswegen sind die beiden folgenden Funktionen praktisch identisch:

1
void function1(u8* myArray)
2
{
3
    for (int i=1; i<7; i++)
4
    {
5
        u8 v=myArray[i];
6
    }
7
}
8

9
void function2(u8 myArray[])
10
{
11
    for (int i=1; i<7; i++)
12
    {
13
        u8 v=myArray[i];
14
    }
15
}
16

17
int main()
18
{
19
    function1(wr_bat_volt);
20
    function2(wr_bat_volt);
21
}
#7829831
Lesenswert?

Da hat man offensichtlich das Anfänger Tutorial übersprungen.

Denn Pointer auf Pointer (bzw Pointer auf Array, in C praktisch dasselbe) ist einer der Übergabeparameter für main auf allem was kein µC ist:

1
int main (int argc, char ** argv)
2
{ 
3
  //...
4
  return 0;
5
}

D.h. jedes Beispiel was die Aufruf Parameter eines Programms auswertet würde OP zeigen wie man das programmieren kann.

Die Sprache C ist ohne Literaturstudium mit totem Holz (Büchern) schwer verständlich.

#7830011
Lesenswert?

Karl K. schrieb:

u8* reg[] = {wr_bat_volt, wr_bat_pow, wr_soc};

danke, das war es.

Und warum der Zirkus? Hier reicht ein zweidimensionales Array.

1
u8 ups[3][8] = {
2
    { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 },
3
    { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 },
4
    { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 }
5
};
6

7
ups[2][4] = 0xAA;
#7830743
Lesenswert?

1
     private void button4_Click(object sender, EventArgs e)
2
     {
3
         string line;
4
         string txt01 = "";
5
          string txt02 = "";
6
        bool cpy = false;
7
         bool whl = true;
8
     using (StreamWriter outputFile = new StreamWriter(@"C:\Users\karl\Desktop\rs485\2025_sim\sharp_types.h"))
9
     {
10
       System.IO.StreamReader file = new System.IO.StreamReader(@"C:\ra_vc\avr_sim_3\Form1.cs");
11

12
         while ((line = file.ReadLine()) != null && whl == true)
13
         {
14
             if (line.Contains("//start_01"))cpy = true;
15
             if(cpy==true )
16
             {
17
                 if (line.Contains("u8[]"))
18
                 {
19
                         int x1 = line.IndexOf(']')+1;
20
                         int x2 = line.IndexOf('=');
21
                         txt02 += line.Substring(x1, x2-x1)+",";
22

23
                         line = line.Replace("[]", "");
24
                     line = line.Replace ("=","[] =");
25
                 }
26
                 txt01 += line;
27
                  outputFile.WriteLine(line);
28

29
             }
30
              if (line.Contains("//end_01"))
31
             {
32
                cpy = false;
33
                whl = false;
34
                     txt01 += "u8* reg[] = { " + txt02 + "};";
35
                     outputFile.WriteLine("");
36
                  outputFile.WriteLine("u8* reg[] = { " + txt02 + "};");
37
            }
38
         }
39

40
     }
41

42
  }

generiert

1
         //start_01
2
            u8 wr_bat_volt [] = { 0x00, 0x03, 0x02, 0x4B, 0x00, 0x01, 0xf4, 0x75 };
3
            u8 wr_bat_pow [] = { 0x00, 0x03, 0x02, 0x4E, 0x00, 0x01, 0xe4, 0x74 };
4
            u8 wr_soc [] = { 0x00, 0x03, 0x00, 0xD6, 0x00, 0x01, 0x64, 0x23 };
5
            u8 wr_grid_pw [] = { 0x00, 0x03, 0x02, 0x83, 0x00, 0x01, 0x75, 0x8b };
6
            u8 wr_pvolt [] = { 0x00, 0x03, 0x02, 0xA4, 0x00, 0x01, 0xc5, 0x80 };
7
            u8 wr_off [] = {0x00, 0x10, 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x00, 0x57, 0x90 };   
8
            u8 wr_on [] = {0x00, 0x10, 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x01, 0x96, 0x50 };
9
        u8 wr_onoff [] = { 0x00, 0x03, 0x00, 0x50, 0x00, 0x01, 0x85, 0xca };
10
        u8 bat_on [] = { 0x02, 0x03, 0x00, 0x01, 0x00, 0x14, 0x14, 0x36 };
11
        u8 bat_off [] = { 0x02, 0x03, 0x00, 0x01, 0x00, 0x13, 0x55, 0xf4 };
12
     //end_01
13

14
u8* reg[] = {  wr_bat_volt , wr_bat_pow , wr_soc , wr_grid_pw , wr_pvolt , wr_off , wr_on , wr_onoff , bat_on , bat_off ,};

und wird über #include "sharp_types.h" eingebunden.

Vielleicht etwas oversized. Aber der Aufwand zum Testen des Programms ist so groß, dass es direkt auf dem avr sehr mühselig wäre.

#7830834
Lesenswert?

Harald K. schrieb:

Ja, ganz toll. Und woher weiß das, was auf "u8* reg[]" zugreift, nun, wie lang eines der Elemente darin sind?

Bislang gibt es nur 8- und 11-Byte-Befehle. Alle Befehle zum Messen haben 8Byte, alle Befehle zum Regeln haben 11Byte. Ein Problem, die Länge zu unterscheiden, stellte sich bislang nicht. Falls es auftreten sollte müsste die Länge ergänzt werden.

1
       private void sub_read_wr()
2
       { 
3
           
4
           bat_volt = sub_wr_tx_rx(reg[0], 8);
5
           bat_kw =   sub_wr_tx_rx(reg[1], 8);
6
           soc = sub_wr_tx_rx(reg[2], 8);
7
           grid_pw = sub_wr_tx_rx(reg[3], 8);
8
           pvolt = sub_wr_tx_rx(reg[4], 8);
9
....
#7830905
Lesenswert?

Karl K. schrieb:

Harald K. schrieb:

Ja, ganz toll. Und woher weiß das, was auf "u8* reg[]" zugreift, nun, wie lang eines der Elemente darin sind?

Bislang gibt es nur 8- und 11-Byte-Befehle. Alle Befehle zum Messen haben 8Byte, alle Befehle zum Regeln haben 11Byte. Ein Problem, die Länge zu unterscheiden, stellte sich bislang nicht. Falls es auftreten sollte müsste die Länge ergänzt werden.

Pfuschen für Fortgeschrittene.

#7830918
Lesenswert?

Karl K. schrieb:

private void sub_read_wr() {

1
       bat_volt = sub_wr_tx_rx(reg[0], 8);
2
       bat_kw =   sub_wr_tx_rx(reg[1], 8);
3
       soc = sub_wr_tx_rx(reg[2], 8);
4
       grid_pw = sub_wr_tx_rx(reg[3], 8);
5
       pvolt = sub_wr_tx_rx(reg[4], 8);

Warum dann indiziert? der naive Ansatz wäre:

1
    bat_volt = sub_wr_tx_rx(wr_bat_volt, sizeof(wr_bat_volt));  
2
    bat_kw   = sub_wr_tx_rx(wr_bat_pow , sizeof(wr_bat_pow ));
#7830928
Lesenswert?

Klaus schrieb:

Pfuschen für Fortgeschrittene.

ja - und? Solange es funktioniert sind mir Regeln relativ egal.

Bruno V. schrieb:

Warum dann indiziert? der naive Ansatz wäre: bat_volt = sub_wr_tx_rx(wr_bat_volt, sizeof(wr_bat_volt)); bat_kw = sub_wr_tx_rx(wr_bat_pow , sizeof(wr_bat_pow ));

guter Vorschlag. Das Programm ist in der Entwicklung - werde ich vielleicht einbauen.

Frage: Mein c#-programm ist ja nun in der Lage, gcc-code zu generieren. Wahrscheinlich kann man auch make über c# aufrufen. Dann hätte man irgendwo eine Datei main.hex in Maschinensprache für den avr. Es besteht eine serielle Verbindung zwischen avr und PC über RS485.

Kann man über diese Verbindung main.hex mittels Bootlader auf den avr schreiben?

Persönliche Seite #7830978
Lesenswert?

Karl K. schrieb:

gcc-code

Unterscheide bitte mal "C" und "GCC"...

  • C ist die Programmiersprache
  • GCC ist eine Sammlung von Compilern, inklusive einem C-Compiler, der ebenfalls "GCC" genannt wird
  • Der GCC C Compiler hat wie alle anderen Compiler auch diverse spezifische Erweiterungen, d.h. Code der diese nutzt ist GCC-spezifisch, aber es ist dennoch C-Code
  • Die GCC-Compiler können Code für viele verschiedene Plattformen generieren, insbesondere x86/amd64 (PC), ARM, und auch AVR. Die Variante der GCC-Compiler-Sammlung für AVR wird AVR-GCC genannt

Du generierst also C-Code. Den kannst du auch auf dem PC ausführen, solange du keine AVR-spezifischen Dinge nutzt. Dein Problem in diesem Thread ist ein gewöhnliches C-Problem, kein GCC-Problem, daher ist sogar der Threadtitel verkehrt.

Karl K. schrieb:

Kann man über diese Verbindung main.hex mittels Bootlader auf den avr schreiben?

Du kannst einfach den avrdude aufrufen.

Moderator Persönliche Seite #7835713
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

1
> void function1(u8* myArray)
2
> {
3
>     for (int i=1; i<7; i++)
4
>     {
5
>         u8 v=myArray[i];
6
>     }
7
> }

Arrays beginnen in C mit dem Index 0 und nicht 1. Außerdem läuft bei Dir der Index i durch die Prüfung i<7 nur bis 6. Damit wird dann nicht nur das erste Element, sondern auch noch das letzte (achte Element) ignoriert.

Korrekt wäre also bei 8 Elementen:

1
    for (int i=0; i<8; i++)    // 0,1,2,3,4,5,6,7

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