STM32 3-wire SPI MOSI high impedance

I have a sensor with a 3-wire SSC interface, which is SPI compatible, but only has one bidirectional data line. Now I try to read this sensor (https://www.infineon.com/dgdl/Infineon-Angle_Sensor_TLE5012B-UM-v01_02-en-UM-v01_02-EN.pdf?fileId=5546d46146d18cb40146ec2eeae4633b) out and it sends me data back, but since MISO and MOSI are shorted together (as recommended from the chip manufacturer), the data is blocked after the 470Ohm data line resistance, because MOSI needs to go high-impedance after the command was sent.

So, how can I achieve a high impedance MOSI pin on a STM32F410CBU6? I could define it as an input, but then I need to re-init the SPI interface. Is there a simpler solution with less overhead?

Edit: I tried now to configure the SPI in the half-duplex mode. Since I use CubeMX, the configuration for this was easy, but I have no success yet. When the SPI is in the half-duplex mode, the SCK seems to have some small offset (maybe about 0.4V) and the MOSI line has also a strange behaviour. When I switch to the full-duplex mode, this behaviour is gone. What could cause this? I'm reading the sensor our likes this:

HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS, LOW);
spi_pos->Instance->CR1 |= (1<<BIDIOE);
HAL_SPI_Transmit(spi_pos,&command,1,1);
spi_pos->Instance->CR1 &= ~(1<<BIDIOE);
asm("nop"); // Since sensor needs some ns to switch to sender mode
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS, HIGH);


The SPI is configured as follows:

  /* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 15;


MOSI Full Duplex:

SCK Full Duplex:

MOSI Half Duplex:

SCK Half Duplex:

Edit 2: Here are the settings in CubeMX:

• I believe that for the STM32's you should not be shorting MISO to MOSI but rather operating the STM32 SPI engine in a mode which uses one of the pins bi-directionally. Please see the programmer's manual applicable to your specific STM32. – Chris Stratton Oct 30 '18 at 15:56

The SPI peripheral of the STM32F4 is configureable for a single wire bidirectional half duplex transfer. In this mode the MOSI pin is used as a master or the MISO as a slave, no need to short the pins together on the STM32 side as only one is used.

For that you need to use the BIDIMODE (=1) bit in SPI_CR1. To set the data direction, you have to use the BIDIOE bit (1 = output, 0 = input) also in SPI_CR1.

So to send data you set BIDIOE to 1 and transfer all the data with writing to SPI_DR after that you reset BIDIOE to 0 and receive data with dummy writing something to SPI_DR (in order to generate the clock, which will tell the slave to send the data) and reading the received data from SPI_DR.

I haven't used this feature yet, and I do not use the peripheral libraries provided by ST, so I can't comment on their capability on using this feature.

• It does still not work in the half-duplex mode. I had a look at the transmit() and receive() function provided in the HAL libraries and they set the BIDIOE flag correctly when used. What could cause this half floating behaviour in the half-duplex mode? I tried already to define the MISO pin, which is shorted but not used for half duplex, as an input or let it in the default state. Both should be high-Z then and not influence the behaviour, right? – HansPeterLoft Oct 31 '18 at 7:39
• @HansPeterLoft well if a pin is switched to high-Z the line will float to some value which is determined by leakage currents, so I'm not surprised to see that behaviour. It seems like your sensor is not answering. Have you checked that you set the SPI in the correct mode (the data is sampled on the falling edge of the SCK by the sensor)? Can't make that out on the diagrams you provided. – Arsenal Oct 31 '18 at 7:58
• I have exactly the same settings as for the Full-Duplex mode with clock polarity low. Should I configure the unused MISO pin as a pull-down input, so the line is not floating anymore? The sensor does not answer, since at the startup the data line ist high. – HansPeterLoft Oct 31 '18 at 8:15
• What I also see is, that I can somehow not set the register with the command "spi_pos->Instance->CR1 |= (1<<SPI_CR1_BIDIOE);". The switching works only in the transmit() and receive() function from the HAL libraries. Otherwise I could let it as output and so this would Pull-Down the line. – HansPeterLoft Oct 31 '18 at 8:24
• @HansPeterLoft ah, yes if the sensor is expecting a low level to work correctly, using a pull down on the lines is probably a good idea. I have seen the pins floating in full duplex configuration as well, so I would not rely on setting the pin to output with the SPI peripheral. – Arsenal Oct 31 '18 at 12:01

You could try using a resistor between the MOSI and the MISO pins on the uC (microcontroller). Then, connecting the MISO pin on the uC to the bidirectional data pin on the sensor. If all the outputs are push-pull type, with no pull-up or pull-down resistors, it might work just fine with your working code.

A short analysis: if the sensor must read a command, the resistor allows the uC to send the command and read what was sent at the same time; if the sensor must send data, it will switch from input to output and drive the line. Even if the MOSI pin is also driving the line, either a HIGH or a LOW level, it will only result in a resistor load and won't change the level driven by the sensor.

The resistor value be must chosen so that the current it draws is bellow both the uC and sensor limits.

Please let me know if you tried this approach and it worked.