I am attempting to interface with the TLE5012B (datasheet here) using SPI. The master in this case is a Nucleo F411RE, which uses an STM32F4 processor. The sensor communicates in 16-bit words, so I set the chip up in Cube as shown (some other peripherals which won't be used in this question's code are also activated):
All seemed to be going well, but a problem arose when I noticed that for some reason, an extra word was being clocked in by SCLK when there was nothing to be received from the data line, resulting in a rogue 0x0000
being stored in the buffer, which messes up future reads.
Here is my code:
#include "app_main.h"
#include "stm32f4xx_hal.h"
#include <stdint.h>
extern SPI_HandleTypeDef hspi2;
uint16_t command = 0x8088;
uint16_t safety = 0;
uint16_t data1[8];
int app_main()
{
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_SPI_Transmit(&hspi2, (uint8_t *)(&command), 1, 0xFF);
HAL_SPI_Receive(&hspi2, (uint8_t*)data1, 8, 0xFF);
HAL_SPI_Receive(&hspi2, (uint8_t *)(&safety), 1, 0xFF);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
HAL_Delay(1);
while (1) {
}
return 0;
}
And here is what happens in the SPI, read using a logic analyzer (Lines in descending order are CS, MOSI/DATA, SCLK, CS does drop low/set high outside the zoomed area):
As can be seen from the code, I should expect to send one word and receive 8 plus a safety word; however, 10 words are being clocked in, with the last being 0x0000
due to no data on the line, which then stays low for some time.
To get a better idea of what was going on, I altered my code slightly:
#include "app_main.h"
#include "stm32f4xx_hal.h"
#include <stdint.h>
extern SPI_HandleTypeDef hspi2;
uint16_t command = 0x8088;
uint16_t safety = 0;
uint16_t data1[8];
int app_main()
{
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
HAL_Delay(105);
HAL_SPI_Transmit(&hspi2, (uint8_t *)(&command), 1, 0xFF);
HAL_Delay(75);
for(int i = 0; i < 8; i++)
{
HAL_Delay(15);
HAL_SPI_Receive(&hspi2, (uint8_t*)&data1[i*2], 1, 0xFF);
}
HAL_Delay(50);
HAL_SPI_Receive(&hspi2, (uint8_t *)(&safety), 1, 0xFF);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
while (1) {
}
return 0;
}
This produced the following output:
From a distance, this seems correct; 8 words received back, plus the safety. On zooming in, however, the problem becomes visible; the command transmission is fine:
However, the first received word is not one word but two clocked in at once by SCLK:
While following words are fine:
What this double word appears to be doing is shoving the receive buffer ahead of what's actually being read in, meaning when the safety word is meant to be read, 0x0000
is added into the buffer, as the safety word has already been received and stored.
It could be worth noting that some of the delays are slightly smaller/larger than they're meant to be, but my question is, what could be causing this double-word to be read in? I tried changing the SPI peripheral to 8-bit mode instead of 16; this didn't fix the issue, it merely made the extra word 8 bits instead of 16. Running similar code on an F3 processor gave incorrect results as well. The TLE can't drive the SCLK line so it must be the micro that's doing something wrong, but I can't for the life of me figure out what.
EDIT: I did some fiddling with wires and set the STM into full-duplex with a resistor on the MOSI line. This fixed the problem, but doesn't tell me what caused it in the first place. Does half-duplex have some strange protocol I don't know about?