LTC2949 gibt keine Rückmeldung auf isoSPI

OP (Firma: NautiTronix) #7359733
Lesenswert?

Moin liebes Forum,

ich möchte euch gerne um Mithilfe bitten.

Ich bin gerade dabei ein BMS mit einem LTC2949 und einigen LTC6811-2 zu realisieren. Das ganze ist mit isoSPI als Multidrop aufgebaut. Der Master ist ein STM32F3 mit einem LTC6820 als Wandler. Leider ist der IC noch recht neu und es findet sich quasi nichts im Netz zu dem Thema.

Nunja, ich habe aber das Problem, dass sich weder die 6811, noch der 2949 angesprochen fühlen. Die Reaktion ist einfach mal gar keine. Die Adern vom isoSPI habe ich probehalber getauscht.

Im Anhang befinden sich der Schaltplan und ein paar Messungen von Pin 30 zu 29 am LTC2949. Die Signale kommen dem Datenblatt entsprechend am IC an, wie man sieht. Es macht auch keinen Unterschied, ob ich den LTC2949 durch einen Kurzschluss von SCL auf Masse vom sleep-Status abhalte.

Saft liegt an:

AVCC = DVCC = 12V

BYP1 = 2,5V

BYP2 = 3,3V

IBIAS = 2V

ICMP = 0,8V

Mir ist nur aufgefallen, dass das Quarz nicht arbeitet, beide Pins haben 0V.

Ein wiederholtes Senden des Frames macht keinen Unterschied. Das Frame habe ich zu Beginn auch stumpf aus dem Datenblatt kopiert, um Fehler ausschließen zu können, siehe Anhang (Seite 44)

Ich habe das Gefühl, ich sehe den Wald vor lauter Bäumen nicht.

Beste Grüße Robert

Angehängte Dateien:
#7359823
Lesenswert?

Das der Quarz nicht schwingt könnte schon daran liegen, dass der Baustein zunächst einmal seinen IDLE Modus verlassen muss. In der überwiegenden Zeit, wo nicht gemessen wird, dürfte der Quarz nicht schwingen, das wäre verschwendete Energie.

Weiterhin: An Deiner Stelle würde ich zunächst einmal eine Brücke zwischen zwei LTC6820 aufbauen, ob das überhaupt funktioniert. Das wäre ja der einfachste Anwendungsfall von isoSPI.

OP (Firma: NautiTronix) #7359835
Lesenswert?

Danke für die Rückmeldung. Das mit dem idle und dem Quarz ist gut möglich und kann zeigen, warum keine Rückmeldung kommt. Der 2949 käme demnach nicht aus dem idle. Dann stellt sich die Frage nach dem Warum. Sleep habe ich ja bereits sichergestellt, sonst wären BYP 1 und 2 auch aus.

Das Verwenden eines zweiten 6820 habe ich schon probiert. Dort werden die Signale vom Bus sauber ausgegeben. Die iso SPI Übertragung selbst scheint wohl nicht das Problem zu sein.

OP (Firma: NautiTronix) #7363857
Lesenswert?

Wie so oft saß das Problem vor dem Bildschirm. Ich hatte das 5. Byte beim DCMD Kommando falsch, also lesen und schreiben vertauscht. Das Schreiben des Registers REGSCTRL ist nicht unbedingt nötig, da die Standardwerte nach dem Start passen. Es schafft nur eine eindeutige Ausgangssituation.

Warum ich das Frame direkt aus dem Datenblatt nicht zum Laufen bekommen habe, verstehe ich rückwirkend auch nicht mehr.

Jetzt läufts. Für andere mit dem gleichen Problem anbei ein Beispiel. Der DMA muss natürlich nicht genutzt werden. Ich nutze ihn später und habe ihn gerade erstmal als Platzhalter im Code.

Konfiguration der Schnittstelle

1
  hspi3.Init.Mode = SPI_MODE_MASTER;
2
  hspi3.Init.Direction = SPI_DIRECTION_2LINES;
3
  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
4
  hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
5
  hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
6
  hspi3.Init.NSS = SPI_NSS_SOFT;
7
  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; // 1Mbaud
8
  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
1
int8_t LTC2949_Wakeup_isoSpi (LTC2949_t *dev)
2
{
3
  uint8_t data = 0x00;
4

5
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET);
6
  HAL_SPI_Transmit(dev->spi, &data, 1, 1);
7
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET);
8

9
  return 0;
10
}
11

12

13
int8_t LTC2949_Read_Reg (LTC2949_t *dev, uint8_t *data, uint8_t address, uint8_t length)
14
{
15
  // Compute the frame length and PECC
16
  uint8_t frame_length = 5 + length + 2;
17
  uint8_t pecc = length - 1;
18

19
  // Set pointers to various parts of the buffers
20
  uint8_t *tx_data_1 = dev->tx_buff;
21
  uint8_t *rx_data = dev->rx_buff + 5;
22
  uint16_t *tx_pec_1 = (uint16_t*) (dev->tx_buff + 2);
23
  uint16_t *rx_pec = (uint16_t*) (dev->rx_buff + 5 + length);
24

25
  // Variables for storing the received PEC and checking for errors
26
  uint16_t rx_pec_calc;
27
  uint8_t rx_pec_error = 0;
28

29
  // Configure the MOSI frame
30
  tx_data_1[0] = 0xFE; // Direct Read/Write Command
31
  tx_data_1[1] = address;
32
  *tx_pec_1 = swap_bytes(pec15(tx_data_1, 2));
33

34
  tx_data_1[4] = (1 << 7) + (0 << 6); // read command
35
  tx_data_1[4] += (((pecc >> 3) & 0x1) ^ ((pecc >> 2) & 0x1)) << 5;
36
  tx_data_1[4] += ((pecc >> 3) & 0x1) << 4;
37
  tx_data_1[4] += ((pecc >> 2) & 0x1) << 3;
38
  tx_data_1[4] += (((pecc >> 1) & 0x1) ^ ((pecc >> 0) & 0x1)) << 2;
39
  tx_data_1[4] += ((pecc >> 1) & 0x1) << 1;
40
  tx_data_1[4] += ((pecc >> 0) & 0x1) << 0;
41

42

43
  // Transmit and receive the data using DMA
44
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET);
45
  HAL_SPI_TransmitReceive_DMA(dev->spi, dev->tx_buff, dev->rx_buff, frame_length);
46

47
  // Wait for the DMA transfer to complete
48
  while(dev->spi->hdmatx->State != HAL_DMA_STATE_READY || dev->spi->hdmarx->State
49
      != HAL_DMA_STATE_READY);
50

51
  // Release the CS pin
52
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET);
53

54
  // Copy the received data to the output buffer
55
  memcpy(data, rx_data, length);
56

57
  // Compute RX PEC to compare it with the transmitted
58
  rx_pec_calc = swap_bytes(pec15(rx_data, length));
59
  if(*rx_pec != rx_pec_calc) rx_pec_error = 1;
60

61

62
  // Return error code if PEC error occurred, otherwise return success
63
  if(rx_pec_error)
64
    return -1;
65
  else
66
    return 0;
67
}
68

69
int8_t LTC2949_Write_Reg (LTC2949_t *dev, uint8_t *data, uint8_t address, uint8_t length)
70
{
71
  // Compute the frame length and PECC
72
  uint8_t frame_length = 5 + length + 2;
73
  uint8_t pecc = length - 1;
74

75
  // Set pointers to various parts of the buffers
76
  uint8_t *tx_data_1 = dev->tx_buff;
77
  uint8_t *tx_data_2 = dev->tx_buff + 5;
78
  uint8_t *rx_data = dev->rx_buff + 5;
79
  uint16_t *tx_pec_1 = (uint16_t*) (dev->tx_buff + 2);
80
  uint16_t *tx_pec_2 = (uint16_t*) (dev->tx_buff + 5 + length);
81
  uint16_t *rx_pec = (uint16_t*) (dev->rx_buff + 5 + length);
82

83
  // Variables for storing the received PEC and checking for errors
84
  uint16_t rx_pec_calc;
85
  uint8_t rx_pec_error = 0;
86

87
  // Configure the MOSI frame
88
  tx_data_1[0] = 0xFE; // Direct Read/Write Command
89
  tx_data_1[1] = address;
90
  *tx_pec_1 = swap_bytes(pec15(tx_data_1, 2));
91

92
  tx_data_1[4] = (0 << 7) + (1 << 6); // write command
93
  tx_data_1[4] += (((pecc >> 3) & 0x1) ^ ((pecc >> 2) & 0x1)) << 5;
94
  tx_data_1[4] += ((pecc >> 3) & 0x1) << 4;
95
  tx_data_1[4] += ((pecc >> 2) & 0x1) << 3;
96
  tx_data_1[4] += (((pecc >> 1) & 0x1) ^ ((pecc >> 0) & 0x1)) << 2;
97
  tx_data_1[4] += ((pecc >> 1) & 0x1) << 1;
98
  tx_data_1[4] += ((pecc >> 0) & 0x1) << 0;
99

100
  // Copy the data to the transmit buffer
101
  memcpy(tx_data_2, data, length);
102

103
  // Compute the PEC for the second part of the transmit buffer
104
  *tx_pec_2 = swap_bytes(pec15(tx_data_2, length));
105

106
  // Transmit and receive the data using DMA
107
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET);
108
  HAL_SPI_TransmitReceive_DMA(dev->spi, dev->tx_buff, dev->rx_buff, frame_length);
109

110
  // Wait for the DMA transfer to complete
111
  while(dev->spi->hdmatx->State != HAL_DMA_STATE_READY || dev->spi->hdmarx->State
112
      != HAL_DMA_STATE_READY);
113

114
  // Release the CS pin
115
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET);
116

117
  // Compute RX PEC to compare it with the transmitted
118
  rx_pec_calc = swap_bytes(pec15(rx_data, length));
119
  if(*rx_pec != rx_pec_calc) rx_pec_error = 1;
120

121

122
  // Return error code if PEC error occurred, otherwise return success
123
  if(rx_pec_error)
124
    return -1;
125
  else
126
    return 0;
127
}
128

129

130
int8_t LTC2949_Init (LTC2949_t *dev, SPI_HandleTypeDef *spi, GPIO_TypeDef *cs_port,
131
              uint16_t cs_pin)
132
{
133
  // Store parameters in device struct
134
  dev->spi = spi;
135
  dev->cs_port = cs_port;
136
  dev->cs_pin = cs_pin;
137
  dev->address = 0x0F; // Constant for every LTC2949
138

139
  // Initialize PEC15 table
140
  init_PEC15_Table();
141

142
  // Set CS pin high, low, high to wake up LTC249 core
143
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET);
144
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET);
145
  HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET);
146

147
  uint32_t start = HAL_GetTick();
148
  while(1)
149
  {
150
    // Check if initialization has taken longer than 120ms
151
    if(start + 120 <= HAL_GetTick()) return -1;
152

153
    uint8_t data = 0x00;
154

155
    // Wake up the LTC2949 twice to ensure it's responsive
156
    LTC2949_Wakeup_isoSpi(dev);
157
    LTC2949_Wakeup_isoSpi(dev);
158

159
    // Set page 0 and direct read mode in REGSCTRL register
160
    data = 0 + (1 << 7);
161
    LTC2949_Write_Reg(dev, &data, 0xFF, 1);
162

163
    // Read OPCTRL register to check if the LTC2949 core is in sleep mode
164
    LTC2949_Read_Reg(dev, &data, 0xF0, 1);
165

166
    // Continue looping if sleeping
167
    if((data & 0x01) != 0) continue;
168

169
    // Disable sleep mode
170
    data = 0x00;
171
    LTC2949_Write_Reg(dev, &data, 0x70, 1);
172
    break;
173
  }
174
  return 0;
175
}
OP (Firma: NautiTronix) #7363913
Lesenswert?

Ich habe hier auch schon Vieles gefunden, dann möchte ich auch etwas zurückgeben. Und ja, Google macht den Rest :)

Das Quarz schwingt nicht einmal beim Ansprechen, wohl erst beim Messen. Also erst bei dem Wechsel in den Status measure. Der Status standby ist etwas missverständlich. Er ist eher als "aktiv ohne zu Messen" zu interpretieren.

Das Messen ist der nächste Punkt auf dem Zettel.

#7363924
Lesenswert?

Hatte mich gefragt, wozu der Baustein dann überhaupt einen Quarz braucht. Habe mal ins Datenblatt geschaut.

An on-chip oscillator provides a 1% precise time base for calculating total charge, energy and time. If higher accuracy is required, a 4MHz crystal connected between pin CLKI and CLKO or an external clock can be used.

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