Our board has an STM32L031 as a SPI master with two AD5271 Digital Pots (R24 and R25) as SPI slaves. After power-on both digital pots can be read (return default of 511). The first digital pot accessed can be given a new value and that new value read back. The other pot now reads all zeros. A different value can be written to the first digital pot and read back (so the SPI bus didn't get 'stuck' after the write routine finished). Once the second digital pot is given a new value, neither digital pot can be read back (returns all zeros). It doesn't matter if R24 is accessed first or if R25 is accessed first; the first pot accessed can be read-modified-written. A UART port provides debug output:
Accessing R24 first:
--------------------
Configuring digital pots...
R24 config is set to 511
R25 config is set to 511
R24 config is set to 156
R25 config is set to 0
R24 config is set to 188
dpotSetRDAC(R25) failed, tried to set to 68, is set to 0
R25 config is set to 0
R24 config is set to 0
Changed the code to access R25 first:
--------------------
Configuring digital pots...
R25 config is set to 511
R24 config is set to 511
R25 config is set to 272
R24 config is set to 0
R25 config is set to 304
dpotSetRDAC(R24) failed, tried to set to 39, is set to 0
R24 config is set to 0
R25 config is set to 0
The nCS pins to the DigiPots are just general purpose GPIO's with the SPI port NSS in software controlled mode. SCK is 500 kHz (verified on 'scope).
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
/**SPI1 GPIO Configuration
PB0 ------> SPI1_MISO
PB1 ------> SPI1_MOSI
PB3 ------> SPI1_SCK
*/
GPIO_InitStruct.Pin = SPI1_MISO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // AD5271 SDO pin is open drain
GPIO_InitStruct.Pull = GPIO_PULLUP; // AD5271 SDO pin is open drain
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_SPI1;
HAL_GPIO_Init(SPI1_MISO_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI1_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_SPI1;
HAL_GPIO_Init(SPI1_MOSI_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI1_SCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
Another data point is the code only works from power-on. If the STLINK debugger (or a ground probe on nRESET) resets the code, nothing works:
Re-running after hitting nRESET pin with probe to ground:
-----------------------------------------------------------------------------
Configuring digital pots...
R24 config is set to 0
R25 config is set to 0
dpotSetRDAC(R24) failed, tried to set to 39, is set to 0
R24 config is set to 0
R25 config is set to 0
dpotSetRDAC(R24) failed, tried to set to 47, is set to 0
R24 config is set to 0
dpotSetRDAC(R25) failed, tried to set to 68, is set to 0
R25 config is set to 0
R24 config is set to 0
If the board is powered off and then back on, the first accessed DigiPot works:
After power cycle:
-------------------------
Configuring digital pots...
R24 config is set to 511
R25 config is set to 511
R24 config is set to 156
R25 config is set to 0
R24 config is set to 188
dpotSetRDAC(R25) failed, tried to set to 68, is set to 0
R25 config is set to 0
R24 config is set to 0
Notes:
- No interrupts are being used in the application, everything is just busy-waiting using the HAL_SPI_Transmit() and HAL_SPI_TransmitReceive() library functions.
- There is only one SPI port in use with all MISO lines tied together, all MOSI lines tied together, all SCK lines tied together, and the two DigiPots nCS lines tied to individual GPIO output pins.
- The SPI controller doesn't 'know' to what device it is communicating since the nCS lines are handled by HAL_GPIO_WritePin() function calls.
- The GPIOB and SPI1 registers are the same (as inspected with STLINK and STM32CubeIDE) when the code works as when the code fails.
Questions:
Q1) Why does a dpotSetRDAC(R24) call make subsequent dpotSetRDAC(R25) calls fail?
Q2) Why does the code only work out of power-on and not from STLINK debugger reset or nRESET hardware reset?
Q3) Are Q1 and Q2 somehow related?