Hallo uC-Community, ich stehe vor einem Problem und sehe wahrscheinlich den Wald vor lauter Bäumen nicht. Ich versuche einen LTC6803-4 über (isolierten) SPI anzusprechen. Die Initialisierung vom SPI sollte passen denn auf dem Logic Analyser sehe ich SCLK, MOSI und CS sowohl vor als auch nach dem Optokoppler. Das Problem liegt in der Antwort vom LTC6803. Dieser sendet mir absolut keine Daten und macht auch sonst keinen Mucks. Meine Deklarationen:
1 | /** @defgroup STM32F4_HARDWARE_LTC6803
|
2 | * @{
|
3 | */
|
4 | uint8_t LTC6803_RX[LTC6803_NBR_BYTES] = {0}; |
5 | uint8_t LTC6803_PEC = 0x00; |
6 | static uint8_t CRC8_Table[256]; // 8-bit table for PEC calc |
7 | |
8 | #define LTC6803_NBR_BYTES 16
|
9 | |
10 | #define LTC6803n 4
|
11 | |
12 | /* PB12 - SPI2_NSS */
|
13 | #define LTC6803_CS_PIN GPIO_Pin_12
|
14 | #define LTC6803_CS_PIN_SOURCE GPIO_PinSource12
|
15 | #define LTC6803_CS_GPIO_PORT GPIOB
|
16 | #define LTC6803_CS_GPIO_CLK RCC_AHB1Periph_GPIOB
|
17 | |
18 | /* PB14 - SPI2_MISO */
|
19 | #define LTC6803_DOUT_PIN GPIO_Pin_14
|
20 | #define LTC6803_DOUT_PIN_SOURCE GPIO_PinSource14
|
21 | #define LTC6803_DOUT_GPIO_PORT GPIOB
|
22 | #define LTC6803_DOUT_GPIO_CLK RCC_AHB1Periph_GPIOB
|
23 | |
24 | /* PB15 - SPI2_MOSI */
|
25 | #define LTC6803_DIN_PIN GPIO_Pin_15
|
26 | #define LTC6803_DIN_PIN_SOURCE GPIO_PinSource15
|
27 | #define LTC6803_DIN_GPIO_PORT GPIOB
|
28 | #define LTC6803_DIN_GPIO_CLK RCC_AHB1Periph_GPIOB
|
29 | |
30 | /* PB13 - SPI2_SCK */
|
31 | #define LTC6803_SCLK_PIN GPIO_Pin_13
|
32 | #define LTC6803_SCLK_PIN_SOURCE GPIO_PinSource13
|
33 | #define LTC6803_SCLK_GPIO_PORT GPIOB
|
34 | #define LTC6803_SCLK_GPIO_CLK RCC_AHB1Periph_GPIOB
|
35 | |
36 | /* LTC6803 address A0 A1 A2 and A3 are connected to GND */
|
37 | #define LTC6803_ADDR 0x80
|
38 | /* Write Configuration Register Group */
|
39 | #define WRCFG 0x01
|
40 | #define WPEC 0xC7
|
41 | /* Read Configuration Register Group */
|
42 | #define RDCFG 0x02
|
43 | #define RCPEC 0xCE
|
44 | /* Poll Interrupt Status */
|
45 | #define PLINT 0x50
|
46 | #define PIPEC 0x77
|
47 | /* Start Diagnose and Poll Status */
|
48 | #define DAGN 0x52
|
49 | #define DAPEC 0x79
|
50 | /* Read Diagnostic Register */
|
51 | #define RDDGNR 0x54
|
52 | #define RDAPEC 0x6B
|
53 | |
54 | /* Read All Cell Voltage Group */
|
55 | #define RDCV 0x04
|
56 | #define RVPEC 0xDC
|
57 | /* Start Cell Voltage ADC Conversions and Poll Status */
|
58 | #define STCVAD 0x10
|
59 | #define SCVPEC 0xB0
|
60 | |
61 | #define CFG1R0 0x11
|
62 | #define CFG1R1 0x00
|
63 | #define CFG1R2 0x00
|
64 | #define CFG1R3 0x00
|
65 | #define CFG1R4 0x00
|
66 | #define CFG1R5 0x00
|
67 | #define CFGPEC 0x3B
|
68 | |
69 | /**
|
70 | * @}
|
71 | */
|
Meine Initialisierung des LTC6803 via SPI2 und die dazugehörigen Funktionen:
1 | /**
|
2 | * @brief Configures LTC6803 SPI
|
3 | * @param None
|
4 | * @retval None
|
5 | */
|
6 | void LTC6803_Init(void) |
7 | {
|
8 | GPIO_InitTypeDef GPIO_InitStructure; |
9 | SPI_InitTypeDef SPI_InitStructure; |
10 | |
11 | SPI_I2S_DeInit(SPI2); |
12 | |
13 | /* Enable the LTC6803_CS clock */
|
14 | RCC_AHB1PeriphClockCmd(LTC6803_CS_GPIO_CLK, ENABLE); |
15 | /* Configure the LTC6803_CS as output */
|
16 | GPIO_InitStructure.GPIO_Pin = LTC6803_CS_PIN; |
17 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; |
18 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
19 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
20 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; |
21 | GPIO_Init(LTC6803_CS_GPIO_PORT, &GPIO_InitStructure); |
22 | /* LTC6803_!CS as high (not active) */
|
23 | GPIO_WriteBit(LTC6803_CS_GPIO_PORT, LTC6803_CS_PIN, Bit_SET); |
24 | |
25 | /* Enable the LTC6803_SCLK clock */
|
26 | RCC_AHB1PeriphClockCmd(LTC6803_SCLK_GPIO_CLK, ENABLE); |
27 | /* Configure the LTC6801_NSOUT as input */
|
28 | GPIO_InitStructure.GPIO_Pin = LTC6803_SCLK_PIN; |
29 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; |
30 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
31 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; |
32 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
33 | GPIO_Init(LTC6803_SCLK_GPIO_PORT, &GPIO_InitStructure); |
34 | |
35 | /* Enable the LTC6803_DOUT (MISO) clock */
|
36 | RCC_AHB1PeriphClockCmd(LTC6803_DOUT_GPIO_CLK, ENABLE); |
37 | /* Configure the LTC6803_DOUT (MISO) as SPI2 DOUT */
|
38 | GPIO_InitStructure.GPIO_Pin = LTC6803_DOUT_PIN; |
39 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; |
40 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
41 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; |
42 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
43 | GPIO_Init(LTC6803_DOUT_GPIO_PORT, &GPIO_InitStructure); |
44 | |
45 | /* Enable the LTC6803_DIN (MOSI) clock */
|
46 | RCC_AHB1PeriphClockCmd(LTC6803_DIN_GPIO_CLK, ENABLE); |
47 | /* Configure the LTC6803_DIN (MOSI) as SPI2 DIN */
|
48 | GPIO_InitStructure.GPIO_Pin = LTC6803_DIN_PIN; |
49 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; |
50 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
51 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; |
52 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
53 | GPIO_Init(LTC6803_DIN_GPIO_PORT, &GPIO_InitStructure); |
54 | |
55 | /* Connect LTC6803 SPI pins to AF5 */
|
56 | GPIO_PinAFConfig(LTC6803_DIN_GPIO_PORT, LTC6803_DIN_PIN_SOURCE, GPIO_AF_SPI2); |
57 | GPIO_PinAFConfig(LTC6803_SCLK_GPIO_PORT, LTC6803_SCLK_PIN_SOURCE, GPIO_AF_SPI2); |
58 | GPIO_PinAFConfig(LTC6803_DOUT_GPIO_PORT, LTC6803_DOUT_PIN_SOURCE, GPIO_AF_SPI2); |
59 | |
60 | /* Enable the SPI2 clock */
|
61 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); |
62 | |
63 | /* Configure the SPI2 bus */
|
64 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
65 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; |
66 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; |
67 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; |
68 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; |
69 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; // 42MHz/128 = 328kHz |
70 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; |
71 | SPI_InitStructure.SPI_CRCPolynomial = 8; |
72 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; |
73 | |
74 | /* Initialize the SPI2 bus */
|
75 | SPI_Init(SPI2, &SPI_InitStructure); |
76 | SPI_Cmd(SPI2, ENABLE); |
77 | |
78 | /* Calculates the table for PEC data */
|
79 | CRC8_Init(); |
80 | }
|
81 | |
82 | /**
|
83 | * @brief Sends data through the SPI interface and return the data received
|
84 | * from the SPI bus.
|
85 | * @param data: data to send.
|
86 | * @retval The value of the received data.
|
87 | */
|
88 | uint8_t SPI2_SendReceive(uint8_t data) |
89 | {
|
90 | /*!< Loop while DR register in not empty */
|
91 | while ((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); |
92 | |
93 | /*!< Send data through the SPI2 peripheral */
|
94 | SPI2->DR = data; |
95 | |
96 | /*!< Wait to receive data */
|
97 | while ((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET); |
98 | |
99 | return SPI2->DR; |
100 | }
|
101 | |
102 | /**
|
103 | * @brief CRC8_Init calculates the CRC8 table for PEC calc
|
104 | * Cite: http://www.rajivchakravorty.com/source-code/uncertainty/multimedia-sim/html/crc8_8c.html
|
105 | * @param None
|
106 | * @retval None
|
107 | */
|
108 | static void CRC8_Init(void) |
109 | {
|
110 | uint16_t i, j; |
111 | uint8_t crc; |
112 | for (i = 0; i < 256; i++) |
113 | {
|
114 | crc = i; |
115 | for (j = 0; j < 8; j ++) |
116 | {
|
117 | crc = (crc << 1) ^ ((crc & 0x80) ? 0x07 : 0); |
118 | }
|
119 | CRC8_Table[i] = crc & 0xFF; |
120 | }
|
121 | }
|
122 | |
123 | /**
|
124 | * @brief CalcPEC_Byte calculates the PEC for the given byte
|
125 | * @param Data: byte for which the PEC should be calculated
|
126 | * @retval calculated PEC byte
|
127 | */
|
128 | uint8_t CalcPEC_Byte(uint8_t Data) |
129 | {
|
130 | /* Initialize PECbyte */
|
131 | uint8_t crc = 0x41; |
132 | return CRC8_Table[(crc) ^ Data]; |
133 | }
|
134 | |
135 | /**
|
136 | * @brief CalcPEC_Packet calculates the PEC for the data in LTC6803_RX
|
137 | * @param Len: number of bytes which are relevant in LTC6803_RX
|
138 | * @retval calculated PEC byte
|
139 | */
|
140 | uint8_t CalcPEC_Packet(uint8_t Len) |
141 | {
|
142 | uint16_t i; |
143 | /* Initialize PECbyte */
|
144 | uint8_t crc = 0x41; |
145 | for (i = 0; i < Len; i++) |
146 | {
|
147 | crc = CRC8_Table[(crc) ^ LTC6803_RX[i]]; |
148 | }
|
149 | return crc; |
150 | }
|
Meine main-Routine:
1 | /* Write Configuration Registers (Broadcast Write) */
|
2 | /* Set LTC6803_!CS to low (activate) */
|
3 | GPIO_WriteBit(LTC6803_CS_GPIO_PORT, LTC6803_CS_PIN, Bit_RESET); |
4 | |
5 | /* Send board address */
|
6 | SPI2_SendReceive(LTC6803_ADDR); |
7 | SPI2_SendReceive(CalcPEC_Byte(LTC6803_ADDR)); |
8 | |
9 | /* Fill buffer for PEC calculation */
|
10 | LTC6803_RX[0] = CFG1R0; |
11 | LTC6803_RX[1] = CFG1R1; |
12 | LTC6803_RX[2] = CFG1R2; |
13 | LTC6803_RX[3] = CFG1R3; |
14 | LTC6803_RX[4] = CFG1R4; |
15 | LTC6803_RX[5] = CFG1R5; |
16 | |
17 | /* Send WRCFG command and its PEC byte */
|
18 | SPI2_SendReceive(WRCFG); |
19 | SPI2_SendReceive(WPEC); |
20 | |
21 | /* Send CFGR0 byte, then CFGR1, …CFGR5, PEC byte */
|
22 | SPI2_SendReceive(CFG1R0); |
23 | SPI2_SendReceive(CFG1R1); |
24 | SPI2_SendReceive(CFG1R2); |
25 | SPI2_SendReceive(CFG1R3); |
26 | SPI2_SendReceive(CFG1R4); |
27 | SPI2_SendReceive(CFG1R5); |
28 | SPI2_SendReceive(CalcPEC_Packet(6)); |
29 | |
30 | /* Set LTC6803_!CS to high (deactivate) */
|
31 | GPIO_WriteBit(LTC6803_CS_GPIO_PORT, LTC6803_CS_PIN, Bit_SET); |
32 | |
33 | /* Insert 10us delay */
|
34 | Delay_1us(10); |
35 | |
36 | /* Read Configuration Registers (Broadcast Write) */
|
37 | /* Set LTC6803_!CS to low (activate) */
|
38 | GPIO_WriteBit(LTC6803_CS_GPIO_PORT, LTC6803_CS_PIN, Bit_RESET); |
39 | |
40 | SPI2_SendReceive(LTC6803_ADDR); // send board address |
41 | SPI2_SendReceive(CalcPEC_Byte(LTC6803_ADDR)); // send PECbyte of board address |
42 | |
43 | /* Send RDCFG command and its PEC byte */
|
44 | SPI2_SendReceive(RDCFG); |
45 | SPI2_SendReceive(RCPEC); |
46 | |
47 | /* Read CFGR0 byte, then CFGR1, ... CFGR5 and PEC byte */
|
48 | for (i = 0; i < 6; i++) |
49 | {
|
50 | LTC6803_RX[i] = SPI2_SendReceive(0x00); |
51 | }
|
52 | LTC6803_PEC = SPI2_SendReceive(0x00); |
53 | |
54 | /* Set LTC6803_!CS to high (deactivate) */
|
55 | GPIO_WriteBit(LTC6803_CS_GPIO_PORT, LTC6803_CS_PIN, Bit_SET); |
56 | |
57 | /* Insert 20us delay */
|
58 | Delay_1us(20); |
59 | |
60 | /* Print data when PEC is correct */
|
61 | if (LTC6803_PEC == CalcPEC_Packet(6)) |
62 | {
|
63 | printf("LTC6803 Address: %d\n", LTC6803_ADDR); |
64 | printf("Config[0...5]: %d %d %d %d %d %d\n", LTC6803_RX[0], LTC6803_RX[1], LTC6803_RX[2], LTC6803_RX[3], LTC6803_RX[4], LTC6803_RX[5]); |
65 | }
|
Ich sende zuerst die Addresse 0x80 (alle A0..3 liegen auf GND) und das entsprechende PEC byte, dann das Command zum schreiben der CFG und anschliessend will ich die CFG auslesen, genau hier passiert, wie im Analyser zu sehen, einfach gar nichts. Die Taktrate mit etwa 330kHz sollte der LTC locker mitmachen, laut Datenblatt ist bis 1Mhz alles möglich. Ich bin echt am verzweifeln, vielleicht sieht einer den Fehler auf die Schnelle, vielleicht kann ein anderer auch etwas mit den Codeschnipseln anfangen. Vielen Dank auf jeden Fall fürs lesen und die Mühen. Grüße #Max