Forum: PC-Programmierung Array als Rückgabewert kann nicht angezeigt werden


von Stefan S. (humus)


Lesenswert?

Hallo Zusammen,

ich versuche gerade mittels SPI Zellspannung auszulesen. Diese kommen 
von einem LTC6804-1. Leider scheitere ich gerade an dem Rückgabewert 
oder besser gesagt an dem Pointer auf meine Daten. Lasse ich mir in der 
Funktion "void spi_write_read" die Werte auf dem LCD anzeigen sehe ich 
eine Zahl zwischen 0 und 2^16. Das ist gut soweit. Möchte ich aber den 
Speicherbereich in der die Funktion aufrufenden Schleife ansehen, ist 
der Wert für alle Spannung konstant 0.

Aufrufende Funktion:
1
/***********************************************//**
2
 \brief Read the raw data_spi from the LTC6804 cell voltage register
3
4
 The function reads a single cell voltage register and stores the read data_spi
5
 in the *data_spi point as a byte array. This function is rarely used outside of
6
 the LTC6804_rdcv() command.
7
8
 @param[in] uint8_t reg; This controls which cell voltage register is read back.
9
10
          1: Read back cell group A
11
12
          2: Read back cell group B
13
14
          3: Read back cell group C
15
16
          4: Read back cell group D
17
18
 @param[in] uint8_t total_ic; This is the number of ICs in the daisy chain(-1 only)
19
20
 @param[out] uint8_t *data_spi; An array of the unparsed cell codes
21
22
Command Code:
23
-------------
24
25
|CMD[0:1]        |  15   |  14   |  13   |  12   |  11   |  10   |   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
26
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
27
|RDCVA:            |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   1   |   0   |   0   |
28
|RDCVB:            |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   1   |   1   |   0   |
29
|RDCVC:            |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   1   |   0   |   0   |   0   |
30
|RDCVD:            |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   1   |   0   |   1   |   0   |
31
32
 *************************************************/
33
void LTC6804_rdcv_reg(uint8_t reg, //Determines which cell voltage register is read back
34
                                          uint8_t total_ic, //the number of ICs in the
35
                                          uint8_t *data_spi //An array of the unparsed cell codes
36
                                          )
37
{
38
  const uint8_t REG_LEN = 8; //number of bytes in each ICs register + 2 bytes for the PEC
39
  uint8_t cmd[4];
40
  uint16_t cmd_pec, cmd_pec_h;
41
42
  Lcd_Out(2,1, lcd_line2);
43
  //1
44
  if (reg == 1)     //1: RDCVA
45
  {
46
    cmd[1] = 0x04;
47
    cmd[0] = 0x00;
48
  }
49
  else if(reg == 2) //2: RDCVB
50
  {
51
    cmd[1] = 0x06;
52
    cmd[0] = 0x00;
53
  }
54
  else if(reg == 3) //3: RDCVC
55
  {
56
    cmd[1] = 0x08;
57
    cmd[0] = 0x00;
58
  }
59
  else if(reg == 4) //4: RDCVD
60
  {
61
    cmd[1] = 0x0A;
62
    cmd[0] = 0x00;
63
  }
64
65
  sprintf(lcd_line2, "rdcv_an Slave %x", cmd[1]);
66
 Lcd_Out(2,1, lcd_line2);
67
  //2
68
  cmd_pec = pec15_calc(2, cmd);
69
  cmd_pec_h = pec15_calc_h(2, cmd);
70
  cmd[2] = (uint8_t)(cmd_pec_h >> 8);
71
  cmd[3] = (uint8_t)(cmd_pec_h);
72
73
  //3
74
  wakeup_idle (); //This will guarantee that the LTC6804 isoSPI port is awake. This command can be removed.
75
76
  //4
77
  Chip_Select = 0;
78
  spi_write_read(cmd,4,data_spi,(REG_LEN*total_ic));
79
  Chip_Select = 1;
80
}
81
/*
82
  LTC6804_rdcv_reg Function Process:
83
  1. Determine Command and initialize command array
84
  2. Calculate Command PEC
85
  3. Wake up isoSPI, this step is optional
86
  4. Send Global Command to LTC6804 daisy chain
87
*/


Funktion "void spi_write_read":

1
/*******************************************************************************
2
 \brief Writes and read a set number of bytes using the SPI port.
3
4
@param[in] uint8_t tx_data_spi[] array of data_spi to be written on the SPI port
5
@param[in] uint8_t tx_len length of the tx_data_spi array
6
@param[out] uint8_t rx_data_spi array that read data_spi will be written too.
7
@param[in] uint8_t rx_len number of bytes to be read from the SPI port.
8
9
*******************************************************************************/
10
11
void spi_write_read(uint8_t tx_data_spi[],//array of data_spi to be written on SPI port
12
                                        uint8_t tx_len, //length of the tx data_spi arry
13
                                        uint8_t *rx_data_spi,//Input: array that will store the data_spi read by the SPI port
14
                                        uint8_t rx_len //Option: number of bytes to be read from the SPI port
15
                                        )
16
{
17
uint8_t i;
18
uint16_t spishit[3];
19
20
  for(i = 0; i < tx_len; i++)
21
  {
22
   SPI1_Write(tx_data_spi[i]);
23
24
  }
25
26
  for(i = 0; i < rx_len; i++)
27
  {
28
    rx_data_spi[i] = (uint8_t)SPI1_READ(0xFF);
29
  }
30
}

Die Displayausgabe habe ich entfernt. Kann mir jemand weiter helfen, 
warum ich in der aufrufenden Funktion die Werte aus "rx_data_spi" nicht 
anzeigen lassen kann?

VG und Danke

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wie wird LTC6804_rdcv_reg aufgerufen?

von Stefan S. (humus)


Lesenswert?

So:
1
/***********************************************//**
2
 \brief Reads and parses the LTC6804 cell voltage registers.
3
4
 The function is used to read the cell codes of the LTC6804.
5
 This function will send the requested read commands parse the data_spi
6
 and store the cell voltages in cell_codes variable.
7
8
 @param[in] uint8_t reg; This controls which cell voltage register is read back.
9
10
          0: Read back all Cell registers
11
12
          1: Read back cell group A
13
14
          2: Read back cell group B
15
16
          3: Read back cell group C
17
18
          4: Read back cell group D
19
20
 @param[in] uint8_t total_ic; This is the number of ICs in the daisy chain(-1 only)
21
22
 @param[out] uint16_t cell_codes[]; An array of the parsed cell codes from lowest to highest. The cell codes will
23
  be stored in the cell_codes[] array in the following format:
24
  |  cell_codes[0][0]| cell_codes[0][1] |  cell_codes[0][2]|    .....     |  cell_codes[0][11]|  cell_codes[1][0] | cell_codes[1][1]|  .....   |
25
  |------------------|------------------|------------------|--------------|-------------------|-------------------|-----------------|----------|
26
  |IC1 Cell 1        |IC1 Cell 2        |IC1 Cell 3        |    .....     |  IC1 Cell 12      |IC2 Cell 1         |IC2 Cell 2       | .....    |
27
28
  @return int8_t, PEC Status.
29
30
    0: No PEC error detected
31
32
    -1: PEC error detected, retry read
33
34
35
 *************************************************/
36
uint8_t LTC6804_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
37
           uint8_t total_ic, // the number of ICs in the system
38
           uint16_t cell_codes[][12] // Array of the parsed cell codes
39
           )
40
{
41
42
43
  const uint8_t NUM_RX_BYT = 8;
44
  const uint8_t BYT_IN_REG = 6;
45
  const uint8_t CELL_IN_REG = 3;
46
47
  uint8_t *cell_data_spi;
48
  uint16_t pec_error = 0;
49
  uint16_t parsed_cell;
50
  uint16_t received_pec;
51
  uint16_t data_spi_pec, data_spi_pec_h;
52
  uint8_t data_spi_counter=0; //data_spi counter
53
  uint8_t cell_reg;
54
  uint8_t current_ic;
55
  uint8_t current_cell;
56
57
  cell_data_spi = (uint8_t *) malloc((NUM_RX_BYT*total_ic)*sizeof(uint8_t));
58
                              //The pec_error variable is simply set negative if any PEC errors
59
  Lcd_Out(2,1, "rdcv_readcellvlt");
60
61
  //1.a
62
  if (reg == 0)
63
  {
64
    //a.i
65
    for(cell_reg = 1; cell_reg<5; cell_reg++)                      //executes once for each of the LTC6804 cell voltage registers
66
    {
67
      data_spi_counter = 0;
68
      LTC6804_rdcv_reg(cell_reg, total_ic,cell_data_spi );                //Reads a single Cell voltage register
69
70
      for (current_ic = 0 ; current_ic < total_ic; current_ic++)       // executes for every LTC6804 in the daisy chain
71
      {                                           // current_ic is used as the IC counter
72
73
        //a.ii
74
    for(current_cell = 0; current_cell<CELL_IN_REG; current_cell++)     // This loop parses the read back data_spi into cell voltages, it
75
        {                                           // loops once for each of the 3 cell voltage codes in the register
76
77
          parsed_cell = cell_data_spi[data_spi_counter] + (cell_data_spi[data_spi_counter + 1] << 8);//Each cell code is received as two bytes and is combined to
78
                                           // create the parsed cell voltage code
79
80
          cell_codes[current_ic][current_cell  + ((cell_reg - 1) * CELL_IN_REG)] = parsed_cell;
81
          data_spi_counter = data_spi_counter + 2;                       //Because cell voltage codes are two bytes the data_spi counter
82
                                          //must increment by two for each parsed cell code
83
        }
84
    //a.iii
85
        received_pec = (cell_data_spi[data_spi_counter] << 8) + cell_data_spi[data_spi_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th                                       //after the 6 cell voltage data_spi bytes
86
        data_spi_pec = pec15_calc(BYT_IN_REG, &cell_data_spi[current_ic * NUM_RX_BYT]);
87
  data_spi_pec_h = pec15_calc_h(BYT_IN_REG, &cell_data_spi[current_ic * NUM_RX_BYT]);
88
89
          sprintf(lcd_line1, "PECvgl=%x, %x", received_pec, data_spi_pec_h);                              //The pec_error variable is simply set negative if any PEC errors
90
          Lcd_Out(1,1, lcd_line1);
91
          Delay_ms(3000);
92
        if(received_pec != data_spi_pec_h)
93
        {
94
          pec_error = -1;
95
                                                                                                                   //The pec_error variable is simply set negative if any PEC errors
96
          Lcd_Cmd(_LCD_CLEAR);               // Clear display
97
          Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
98
          Delay_ms(1000);
99
          sprintf(lcd_line1, "PEC_ERR = %d", pec_error);                              //The pec_error variable is simply set negative if any PEC errors
100
          Lcd_Out(1,1, lcd_line1);                                          //are detected in the serial data_spi
101
        }
102
        data_spi_counter=data_spi_counter+2;                        //Because the transmitted PEC code is 2 bytes long the data_spi_counter
103
                                          //must be incremented by 2 bytes to point to the next ICs cell voltage data_spi
104
      }
105
    }
106
  }
107
 //1.b
108
  else
109
  {
110
  //b.i
111
    //....
112
  }
113
114
 //2
115
 FreeMem(cell_data_spi, sizeof(cell_data_spi));
116
return(pec_error);
117
}
118
/*
119
  LTC6804_rdcv Sequence
120
121
  1. Switch Statement:
122
    a. Reg = 0
123
      i. Read cell voltage registers A-D for every IC in the daisy chain
124
      ii. Parse raw cell voltage data_spi in cell_codes array
125
      iii. Check the PEC of the data_spi read back vs the calculated PEC for each read register command
126
    b. Reg != 0
127
      i.Read single cell voltage register for all ICs in daisy chain
128
      ii. Parse raw cell voltage data_spi in cell_codes array
129
      iii. Check the PEC of the data_spi read back vs the calculated PEC for each read register command
130
  2. Return pec_error flag
131
*/

In "cell_codes" sollten dann die Zellspannungen stehen. Am Ende des 
Code-Blocks sind die einzelnen Abschnitte kurz erklärt.

Was mir auch überhaupt nicht klar ist, wie der Eingabeparameter einer 
Funktion als Ausgabe dienen kann? Beispiel: Funktion "spi_write_read: 
@param[out] uint8_t rx_data_spi array that read data_spi will be written 
too."

: Bearbeitet durch User
von fb (Gast)


Lesenswert?

Jetzt fehlen noch die Definitionen von REG_LEN und NUM_RX_BYT

Stefan S. schrieb:
> Was mir auch überhaupt nicht klar ist, wie der Eingabeparameter einer
> Funktion als Ausgabe dienen kann? Beispiel: Funktion "spi_write_read:
> @param[out] uint8_t rx_data_spi array that read data_spi will be written
> too."

Der Kommentar ist etwas konfus.Besser wäre "@param[out] uint8_t* 
rx_data_spi ..."
'rx_data_spi' ist ein Pointer und über diesen kann die Funktion 
Speicherbereiche außerhalb ihres eigenen Gültigkeitsbereichs ändern und 
damit u.a. auch Werte an den Aufrufer übermitteln.

von Stefan S. (humus)


Lesenswert?

fb schrieb:
> Jetzt fehlen noch die Definitionen von REG_LEN und NUM_RX_BYT

-> const uint8_t NUM_RX_BYT = 8;
-> const uint8_t REG_LEN = 8;

Sind in den Funktionen LTC6804_rdcv und LTC6804_rdcv_reg definiert, 
wurden also nicht vergessen:).

fb schrieb:
> Der Kommentar ist etwas konfus.Besser wäre "@param[out] uint8_t*
> rx_data_spi ..."
> 'rx_data_spi' ist ein Pointer und über diesen kann die Funktion
> Speicherbereiche außerhalb ihres eigenen Gültigkeitsbereichs ändern und
> damit u.a. auch Werte an den Aufrufer übermitteln.

-> So habe ich  mir das gedacht, aber warum das nicht läuft bekomme ich 
nicht heraus.

: 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.