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!
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With