Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't solve this synchronization SPI problem

So, I am integrating a MAX31865 temperature sensor in a NUCLEO-F103RB board using SPI communication. It doens't seem to be working well, since I just can't send a single Write Transmission: enter image description here

I am just using this function:

void INIT_SPI_MAX(void)
{

    uint8_t spi_reg =0b11000000;  //V_BIAS ON, Auto off, 4-wire, returns all fault status bits in register, 50Hz
    uint16_t low_fault = (100) & 0x7FFF;;
    uint8_t threshold[2] = {0x85, 0x86};  //RTD resistance data address registers

    SPI_Write1Byte(0x80);
    SPI_Write1Byte(spi_reg);
    SPI_Write1Byte(threshold[0]);
    SPI_Write1Byte((uint8_t)((low_fault & 0xFF00) >> 8));
    SPI_Write1Byte(threshold[1]);
    SPI_Write1Byte((uint8_t)((low_fault & 0x00FF) << 1));

}

and also this one

void SPI_Write1Byte(uint8_t data)
{

    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
    HAL_Delay(1);
    HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
    HAL_Delay(1);


} 

I just did this in a PIC microcontroller in MPLAB and it worked perfectly. I am using SPI mode 3 and my STM32 Cube IDE settings are "CPOL: HIGH" and "CPHA: 2 Edge", and I also am sure that GPIOs are configurated correctly (CS included, using it as a GPIO_OUTPUT).

I don't seem to find the error in this, can it be system configuration? Or maybe SPI Clock parameters (which are 32 prescaler (2MBits/s, since sensor can handle 5M)? Hope someone can help me, thank you guys!

like image 831
Manuel Orsini Avatar asked Sep 07 '25 08:09

Manuel Orsini


1 Answers

It's a known issue (at least to me) that the STM32 SPI peripheral starts out with its clock signal possibly in the wrong state. The solution is to do a dummy transaction on the bus (without asserting chip-select). After that, the clock line will be correct. So you could just do this (before doing anything else):

    SPI_Write1Byte(0x00);

I think you have more problems. You're asserting and de-asserting chip-select around every byte that you send. I'm pretty sure that's not how it is meant to be used. From the MAX31865 datasheet on page 17:

For a single-byte transfer, 1 byte is read or written and then CS is driven high (see Figure 6 and Figure 7). For a multiple-byte transfer, multiple bytes can be read or written after the address has been written (see Figure 8). The address continues to increment through all memory locations as long as CS remains low.

Figure 7

So you should probably remove the control of chip-select from your SPI_Write1Byte() function:

void SPI_Write1Byte(uint8_t data)
{
    HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
}

Then, to write the Configuration Register (address 0x00) you'd want something like:

    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
    SPI_Write1Byte(0x80);
    SPI_Write1Byte(spi_reg);
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

To write the two Fault Threshold registers at register 0x05 and 0x06 you'd probably need:

    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
    SPI_Write1Byte(threshold[0]);
    SPI_Write1Byte((uint8_t)((low_fault & 0xFF00) >> 8));
    SPI_Write1Byte((uint8_t)((low_fault & 0x00FF) << 1));
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

taking advantage of the fact that the address naturally increments. (i.e. you don't need to write the address of both registers, just the first one.)

You could make all this easier by making a function like so:

void write_consecutive_registers(uint8_t start_reg, uint8_t num_reg, uint8_t *buff)
{
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
    SPI_Write1Byte(start_reg);

    for (uint8_t i = 0u; i < num_reg; ++i)
    {
        SPI_Write1Byte(buff[i]);
    }

    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
}
like image 110
pmacfarlane Avatar answered Sep 11 '25 01:09

pmacfarlane