英文:
Can't solve this synchronization SPI problem
问题
So, I am integrating a MAX31865 temperature sensor in a NUCLEO-F103RB board using SPI communication. It doesn'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!
英文:
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!
答案1
得分: 2
这是一个已知问题(至少对我来说),STM32 SPI 外设在启动时可能会以错误的状态开始其时钟信号。解决方法是在总线上进行一个虚拟事务(不断言片选)。之后,时钟线将变得正确。因此,您可以在执行任何其他操作之前执行以下操作:
```c
SPI_Write1Byte(0x00);
我认为您有更多问题。您在发送每个字节时都在断言和取消断言片选。我相当确定这不是它的正确用法。根据 MAX31865 数据手册 第17页:
> 对于单字节传输,将读取或写入1字节,然后将 CS 引脚拉高(请参阅图6和图7)。对于多字节传输,在写入地址后可以读取或写入多个字节(请参阅图8)。只要 CS 保持低电平,地址就会持续递增。
因此,您可能应该从您的 SPI_Write1Byte()
函数中删除对片选的控制:
void SPI_Write1Byte(uint8_t data)
{
HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
}
然后,要写入配置寄存器(地址为 0x00),您可能需要如下操作:
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);
要写入寄存器地址为 0x05 和 0x06 的两个故障阈值寄存器,您可能需要:
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);
利用地址自然递增的事实。(即您不需要同时写入两个寄存器的地址,只需写入第一个寄存器的地址即可。)
您可以通过创建如下的函数来使所有这些操作更容易:
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);
}
英文:
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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论