Things to mention in this post:
* SPI Communication protocol
In this post we are going to do SPI communication protocol via GPIO pins.
About SPI Communication Protocol
As all you know, Spi is a hardware(peripheral) based communication protocol. SPI is a common communication protocol used by many different devices. For example, SD card reader modules, RFID card reader modules, and 2.4 GHz wireless transmitter/receivers all use SPI to communicate with microcontrollers. At the end of the day we could be run out of SPI peripheral. Thus, if we need to use Spi, we should do BitBang Spi.
Let’s BANG BANG! :
Spi have 4 wired connection and if we want to simulate it over GPIO pins we need to simulate every wire’s protocol over GPIO pins seperately.
So we need just 4 GPIO pins for that and they will simulate Sck, Mosi, Miso, Ss connections .
- SCK : For SCK connection protocol , GPIO pin which is simulate SCK will always toggle.
- SS : For SS , related GPIO pin have to action before transmitting data.
- MOSI : Master Out Slave In pin simulates the data as Low and High.
- MISO : Master In Slave Out pin simulates the data as Low and High.

Let’s Code :
HEADER FILE
In the header file we need to configure our spi pins and port as we want.
/* DEFINES */
/*
*Spi general ports
*/
#define SPI_PORT GPIOE
/*
*Spi general pins
*/
#define SPI_CLK GPIO_PIN_15
#define SPI_MOSI GPIO_PIN_7
#define SPI_MISO GPIO_PIN_12
#define SPI_CS GPIO_PIN_10
And useful macros here ;
Help us to configure GPIO states fastly.
#define GPIO_OUTPUT_HIGH(port,pin) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET);
#define GPIO_OUTPUT_LOW(port,pin) HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET);
#define GPIO_INPUT_READ(port,pin) HAL_GPIO_ReadPin (port, pin);
Microsecond Delay here;
#define DELAYUS(x) {\
uint32_t m = (x * 30);\
while(m > 0 ){ m--;} \
}
C FILE
First of all, we need an Init function that will help us simulating Polarization of the CLK. Here, CPOL is predefined in header file.
/**
* @brief Inits SPI. This function inits chip select and clk pins
*/
void BitBangSpi_Init(void){
GPIO_OUTPUT_HIGH(SPI_PORT,SPI_CS);
if(CPOL)
GPIO_OUTPUT_HIGH(SPI_PORT,SPI_CLK);
}
There we read bits :
/**
* @brief Reads the 1 bit data from GPIO
* @retval Related GPIO output
*/
uint8_t BitBangSpi_bitRead(){
return GPIO_INPUT_READ(SPI_PORT, SPI_MISO);
}
When we need to write bit :
/**
* @brief Writes an 1 bit data.
* @param bit: variable that configures pin output
*/
uint8_t BitBangSpi_bitWrite(uint8_t bit){
uint8_t result = 0;
if (bit)
{
// Write '1' bit
GPIO_OUTPUT_HIGH(SPI_PORT, SPI_MOSI);
}
else
{
// Write '0' bit
GPIO_OUTPUT_LOW(SPI_PORT, SPI_MOSI);
}
return result;
}
Then, we can write bytes using write bit function which is above :
/**
* @brief Writes an 1 byte data.
* @retval Received 1 byte value from GPIO
*/
uint8_t BitBangSpi_byteWrite(uint8_t data){
uint8_t result = 0;
// Loop to write each bit in the byte, LS-bit first
for (uint8_t loop = 0; loop < 8; loop++)
{
if(CPOL){
GPIO_OUTPUT_LOW(SPI_PORT, SPI_CLK);}
else
GPIO_OUTPUT_HIGH(SPI_PORT, SPI_CLK);
BitBangSpi_bitWrite(data & 0x80);
// shift the data byte for the next bit
result |= (BitBangSpi_bitRead() << loop);
if(CPOL){
GPIO_OUTPUT_HIGH(SPI_PORT, SPI_CLK);}
else
GPIO_OUTPUT_LOW(SPI_PORT, SPI_CLK);
data = data << 1;
}
return result;
}
So, the final step to send data which is wanted to transmit over SPI. In this function we are using :
/**
* @brief Sends the 1 byte data via GPIO
* @param Tx_data: Variable to the transmits data address
* @retval Related GPIO output
*/
uint8_t BitBangSpi_sendByte(uint8_t Tx_data){
// Incoming data buffer
uint8_t Rx_data = 0;
// To Start the Communication make sure that Chip Select is low.
GPIO_OUTPUT_LOW(SPI_PORT,SPI_CS);
// Writing data through to the IO pins
Rx_data = BitBangSpi_byteWrite(Tx_data);
// To Finish the Communication make sure that Chip Select is low.
GPIO_OUTPUT_HIGH(SPI_PORT,SPI_CS);
return Rx_data;
}
Overall, we achieved the SPI without SPI peripheral. You can use these functions to transmit data and observe the flow using logic analyzer over the related GPIO pins.
You can check the GitHub Link,
