0
0
Power-electronicsHow-ToBeginner · 3 min read

How to Configure SPI in Embedded C: Simple Guide

To configure SPI in Embedded C, you need to set up the SPI control registers to define clock polarity, phase, speed, and data order, then enable the SPI module. This involves initializing the SPI pins, configuring the SPI control registers like SPCR, and enabling SPI with SPE bit.
📐

Syntax

SPI configuration typically involves setting bits in control registers to define how SPI works:

  • SPCR: SPI Control Register to set clock polarity, phase, speed, and enable SPI.
  • SPSR: SPI Status Register for speed doubling and status flags.
  • SPDR: SPI Data Register for sending/receiving data.

Common bits in SPCR include:

  • SPR1, SPR0: Set SPI clock rate.
  • CPOL: Clock polarity (idle state).
  • CPHA: Clock phase (data sampling).
  • MSTR: Master/Slave select.
  • SPE: SPI enable.
c
SPCR = (1 << SPE) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0 << SPR1) | (1 << SPR0); // Enable SPI, Master mode, clock rate fosc/16
💻

Example

This example shows how to configure SPI as a master on an AVR microcontroller, send a byte, and wait for transmission to complete.

c
#include <avr/io.h>

void SPI_MasterInit(void) {
    // Set MOSI, SCK, and SS as output, others as input
    DDRB |= (1 << DDB3) | (1 << DDB5) | (1 << DDB2);
    DDRB &= ~(1 << DDB4); // MISO as input

    // Enable SPI, Master mode, set clock rate fosc/16
    SPCR = (1 << SPE) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0 << SPR1) | (1 << SPR0);
}

void SPI_MasterTransmit(char data) {
    SPDR = data; // Load data into SPI data register
    while (!(SPSR & (1 << SPIF))) ; // Wait until transmission complete
}

int main(void) {
    SPI_MasterInit();
    SPI_MasterTransmit(0x55); // Send 0x55
    while(1) {}
    return 0;
}
Output
No visible output; SPI sends byte 0x55 on MOSI line
⚠️

Common Pitfalls

  • Not setting the SPI pins direction correctly (MOSI, SCK, and SS as output for master).
  • Forgetting to enable SPI by setting the SPE bit.
  • Incorrect clock polarity (CPOL) and phase (CPHA) causing data mismatch.
  • Not waiting for the transmission complete flag (SPIF) before sending new data.
  • Confusing master and slave roles by wrong MSTR bit setting.
c
/* Wrong: Not enabling SPI */
SPCR = (1 << MSTR);

/* Right: Enable SPI and set master mode */
SPCR = (1 << SPE) | (1 << MSTR);
📊

Quick Reference

Register/BitPurposeTypical Setting for Master
SPCRSPI Control RegisterSet SPE=1, MSTR=1, SPR0=1 for clock fosc/16
SPSRSPI Status RegisterCheck SPIF bit for transfer complete
SPDRSPI Data RegisterWrite data to send, read received data
CPOLClock Polarity0 for idle low, 1 for idle high
CPHAClock Phase0 or 1 depending on slave device timing
MOSI PinMaster Out Slave InSet as output on master
MISO PinMaster In Slave OutSet as input on master
SCK PinSerial ClockSet as output on master
SS PinSlave SelectSet as output on master to avoid SPI reset

Key Takeaways

Always enable SPI by setting the SPE bit in the control register.
Configure SPI pins direction correctly: MOSI, SCK, and SS as output for master.
Set clock polarity and phase to match the slave device requirements.
Wait for the SPIF flag before sending new data to ensure transmission is complete.
Use the MSTR bit to select master or slave mode properly.