cancel
Showing results for 
Search instead for 
Did you mean: 

L9945 SPI register read problem

BBame
Associate II

Hi All,

We have problem reading register values from L9945. We use STM32G474RE to communicate with it and the project was made using current STM32CubeMX and its FreeRTOS.

Here are the SPI parameters in main.c:

  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

Here is the code using a HAL call to send and receive the register values, including temporary logging to produce raw sent/received output:

std::optional<uint32_t> nowtech::L9945::read(uint32_t const aCommand) noexcept {
    std::optional<uint32_t> result;
    prepareDataToSend(cFixedPatternValues[aCommand] | cMaskRead);
    mPinChipSelect.write(Gpio::State::cOn);
auto log = Log::i(nowtech::LogTopics::system); log << " read out: "; for (int i = 0; i < cSizeofRegister * 2u; ++i) log << LC::cX2 << mDataOut[i] << ' '; log << Log::end;
    if(aCommand < cRegisterCount && HAL_SPI_TransmitReceive(mSpiHandle, mDataOut, mDataIn, cSizeofRegister * 2u, mSpiTimeout) == HAL_OK) {
auto log = Log::i(nowtech::LogTopics::system); log << " read  in: "; for (int i = 0; i < cSizeofRegister * 2u; ++i) log << LC::cX2 << mDataIn[i] << ' '; log << Log::end;
      uint32_t value = (static_cast<uint32_t>(mDataIn[4]) << 24u) | 
                       (static_cast<uint32_t>(mDataIn[5]) << 16u) | 
                       (static_cast<uint32_t>(mDataIn[6]) <<  8u) | 
                                              mDataIn[7];
      if(value == cInvalidResponse || calculateParity(value) == cInvalidParity) {
        mReadCache[aCommand] = cInvalidResponse;
      }
      else {
        mReadCache[aCommand] = value;
        result = value;
      }
    }
    else { // perhaps store HAL error, but not now
    }
    mPinChipSelect.write(Gpio::State::cOff);
    return result;
  }

Now we first set SPI input select on channel 1 to true (write to reg 0). Then read the battery voltage (read from reg 13) and then SPI input select (read from reg 0).

defaultTask 0000025 SYSTEM       write out: 00 02 00 01 f0 00 00 01 
defaultTask 0000025 SYSTEM       write  in: f3 40 7c bf 00 02 00 01 
defaultTask 0000025 SYSTEM        read out: da aa aa ab f0 00 00 01 
defaultTask 0000025 SYSTEM        read  in: f3 40 7c bf da aa aa ab 
defaultTask 0000026 SYSTEM        read out: 08 00 00 01 f0 00 00 01 
defaultTask 0000026 SYSTEM        read  in: f3 40 7c bf 08 00 00 01 

Although the write seems to function, the read merely echoes back the command used to initiate the read process. The voltage and temperature values are independent of the actual situation. Actually no matter what are the bits 1-26 in a read command, their values will be returned as long as the parity is correctly set.

For all operations, the last command is intentionally corrupt (invalid reg and parity bit).

Here is a logic analyzer screenshot for the voltage read process:

0690X00000BwLF2QAN.png

...and from the SPI select bit read process:

0690X00000BwLG0QAN.png

What can be the problem?

Thank you in advance.

Best regards: Balázs Bámer

1 ACCEPTED SOLUTION

Accepted Solutions
BBame
Associate II

I reply to myself. A collegue has pointed out that perhaps the L9945 wants to forward the command to its siblings via daisy chain. And yes, this was the case. Turning off CS between two words yields correct SPI communication.

View solution in original post

1 REPLY 1
BBame
Associate II

I reply to myself. A collegue has pointed out that perhaps the L9945 wants to forward the command to its siblings via daisy chain. And yes, this was the case. Turning off CS between two words yields correct SPI communication.