To make sure that Tx Buffer is empty, we use the SR, which flags if the Tx Buffer is empty, otherwise you will corrupt the data.
Note that the we don't have direct access to tx_buffer or rx_buffer. We can only access them via DR. So, as we write to the DR and before writing to this register, make sure that tx-buffer is empty. Likewise, before reading, we have to check the RX_ENE flag.
Let's test our SendData API now with a small Exercise. This is just to test, no slave thus no MISO or NSS.
To do so, we first check in the data-sheet which GPIO can i use to choose it as MISO, MOSI ,etc. Its hard to see but you can go to AF func mapping in Pinouts description. See if your uC exposes header for which SPIx.
Left-Shift or right shift :
All the APIs made are available on github.