Skip to main content
Associate
Jul 17, 2025 2:22 PM UTC
Solved

SPI 8-Bit frame

Hi, 

I hope this is the right place to ask. I'm currently working on interfacing an SD Card with a nucleo f767. I used the DS-Bits in CR2 to set the data frame to 8 Bit (what also should be the reset value). Despite that, MOSI always sends the whole data register, which is 16 Bits. So if I use the function below to send 0xFF, the hardware will send 0x00FF. Does anybody know this issue? 

uint8_t spi_txrx(uint8_t b) {
  while (!(SPI3->SR & SPI_SR_TXE));
  SPI3->DR = b;
  while (!(SPI3->SR & SPI_SR_RXNE));
  return SPI3->DR;
}
This topic has been closed for replies.
TDK
TDKBest answer
Jul 17, 2025 3:32 PM UTC

Maybe this instead:

*((volatile uint8_t*)&(SPI3->DR)) = b;

stm32f7xx-hal-driver/Inc/stm32f7xx_ll_spi.h at 417ddbbea8a8e3f1d7cfe07aeefae9b409b8a30d · STMicroelectronics/stm32f7xx-hal-driver

 

"If you feel a post has answered your question, please click ""Accept as Solution""."

4 replies

TDK
Jul 17, 2025 2:46 PM UTC

Write 8 bits to the register instead of 16:

*(volatile uint8_t*)&SPI3->DR = b;

 

Look up data packing in the Reference Manual.

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
LuLeWiAuthor
Associate
Jul 17, 2025 2:59 PM UTC

Thank you for the quick response. I already tried this cast, but it leads into a system crash. With the following version, the cmd0 command works. Is it save to use?
void spi_send(uint8_t b) {
while (!(SPI3->SR & SPI_SR_TXE));
__asm__ volatile("strb %0, [%1]"
:
: "r"(b), "r"(&SPI3->DR)
: "memory");
while (!(SPI3->SR & SPI_SR_TXE));
}

TDK
TDKBest answer
Jul 17, 2025 3:32 PM UTC
"If you feel a post has answered your question, please click ""Accept as Solution""."
LuLeWiAuthor
Associate
Jul 18, 2025 6:33 AM UTC

This one is working. Thank you very much!