42. LED toggle using SPI

Back To All Submissions
Previous Submission
Next Submission

Solving Approach

How do you plan to solve it?

//init SPI(GPIO config, SPI handle config(sclk speed, duplex setting etc), enable spi peripheral

// in main, wait for button press, send a data, while(busy); disable spi.

// on slave side, toggle led in spi interrupt(RXNE Flag)

 

Code

/*Paste your code here*/
/* Master Side */
#include "../drivers/Inc/stm32f401xx.h"

void delay(void) {
    for (uint32_t i = 0; i < 500000 / 2; i++);
}

void GPIO_ButtonInit(void) {
    GPIO_Handle_t GPIOBtn;
    GPIOBtn.pGPIOx = GPIOC;
    GPIOBtn.GPIO_PinConfig.GPIO_PinNumber      = GPIO_PIN_NUM_13;
    GPIOBtn.GPIO_PinConfig.GPIO_PinMode        = GPIO_MODE_IN;
    GPIOBtn.GPIO_PinConfig.GPIO_PinSpeed       = GPIO_SPEED_HIGH;
    GPIOBtn.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
    GPIO_Init(&GPIOBtn);
}

void SPI2_GPIOInit(void) {
    GPIO_Handle_t SPI2Pins;
    SPI2Pins.pGPIOx = GPIOB;
    SPI2Pins.GPIO_PinConfig.GPIO_PinMode        = GPIO_MODE_ALTFN;
    SPI2Pins.GPIO_PinConfig.GPIO_PinAltFundMode = 5;
    SPI2Pins.GPIO_PinConfig.GPIO_PinOPType      = GPIO_OP_TYPE_PP;
    SPI2Pins.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
    SPI2Pins.GPIO_PinConfig.GPIO_PinSpeed       = GPIO_SPEED_HIGH;

    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_13; // SCLK
    GPIO_Init(&SPI2Pins);
    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_15; // MOSI
    GPIO_Init(&SPI2Pins);
    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_12; // NSS
    GPIO_Init(&SPI2Pins);
    // MISO omitted — master not receiving anything here
}

void SPI2_Init(void) {
    SPI_Handle_t SPI2handle;
    SPI2handle.pSPIx                     = SPI2;
    SPI2handle.SPIConfig.SPI_BusConfig   = SPI_BUS_CONFIG_FD;
    SPI2handle.SPIConfig.SPI_DeviceMode  = SPI_DEVICE_MODE_MASTER;
    SPI2handle.SPIConfig.SPI_SclkSpeed   = SPI_SCLK_SPEED_DIV8;
    SPI2handle.SPIConfig.SPI_DFF         = SPI_DFF_8BITS;
    SPI2handle.SPIConfig.SPI_CPOL        = SPI_CPOL_LOW;
    SPI2handle.SPIConfig.SPI_CPHA        = SPI_CPHA_LOW;
    SPI2handle.SPIConfig.SPI_SSM         = SPI_SSM_DI;
    SPI_Init(&SPI2handle);
}

int main(void) {
    uint8_t toggle_cmd = 0xAB;  // arbitrary command byte, slave just needs any byte

    GPIO_ButtonInit();
    SPI2_GPIOInit();
    SPI2_Init();
    SPI_SSOEConfig(SPI2, ENABLE);

    while (1) {
        while (GPIO_ReadFromInputPin(GPIOC, GPIO_PIN_NUM_13)); // wait for press
        delay(); // debounce

        SPI_PeripheralControl(SPI2, ENABLE);

        SPI_SendData(SPI2, &toggle_cmd, 1);
        while (SPI_GetFlagStatus(SPI2, SPI_BUSY_FLAG));

        SPI_PeripheralControl(SPI2, DISABLE);
    }

    return 0;
}


/* slave side *\
// LED on PA5 (onboard Nucleo LED)
void GPIO_LEDInit(void) {
    GPIO_Handle_t GPIOA_LED;
    GPIOA_LED.pGPIOx = GPIOA;
    GPIOA_LED.GPIO_PinConfig.GPIO_PinNumber      = GPIO_PIN_NUM_5;
    GPIOA_LED.GPIO_PinConfig.GPIO_PinMode        = GPIO_MODE_OUT;
    GPIOA_LED.GPIO_PinConfig.GPIO_PinSpeed       = GPIO_SPEED_HIGH;
    GPIOA_LED.GPIO_PinConfig.GPIO_PinOPType      = GPIO_OP_TYPE_PP;
    GPIOA_LED.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
    GPIO_Init(&GPIOA_LED);
}

void SPI2_GPIOInit(void) {
    GPIO_Handle_t SPI2Pins;
    SPI2Pins.pGPIOx = GPIOB;
    SPI2Pins.GPIO_PinConfig.GPIO_PinMode        = GPIO_MODE_ALTFN;
    SPI2Pins.GPIO_PinConfig.GPIO_PinAltFundMode = 5;
    SPI2Pins.GPIO_PinConfig.GPIO_PinOPType      = GPIO_OP_TYPE_PP;
    SPI2Pins.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
    SPI2Pins.GPIO_PinConfig.GPIO_PinSpeed       = GPIO_SPEED_HIGH;

    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_13; // SCLK
    GPIO_Init(&SPI2Pins);
    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_15; // MOSI
    GPIO_Init(&SPI2Pins);
    SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_12; // NSS
    GPIO_Init(&SPI2Pins);
    // MISO omitted — slave not sending anything back
}

void SPI2_Init(void) {
    SPI_Handle_t SPI2handle;
    SPI2handle.pSPIx                     = SPI2;
    SPI2handle.SPIConfig.SPI_BusConfig   = SPI_BUS_CONFIG_FD;
    SPI2handle.SPIConfig.SPI_DeviceMode  = SPI_DEVICE_MODE_SLAVE; // <-- slave
    SPI2handle.SPIConfig.SPI_DFF         = SPI_DFF_8BITS;
    SPI2handle.SPIConfig.SPI_CPOL        = SPI_CPOL_LOW;
    SPI2handle.SPIConfig.SPI_CPHA        = SPI_CPHA_LOW;
    SPI2handle.SPIConfig.SPI_SSM         = SPI_SSM_DI;
    // Note: no SclkSpeed for slave — slave doesn't generate the clock
    SPI_Init(&SPI2handle);
}


// SPI2 IRQ handler — fires when a byte is received (RXNE)
void SPI2_IRQHandler(void) {
    // Call your driver's IRQ handler if it exists, or handle inline:
    // SPI_IRQHandling(&SPI2handle);  // stub — depends on your driver

    // Toggle LED on every received byte
    GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NUM_5);
}

int main(void) {
    GPIO_LEDInit();
    SPI2_GPIOInit();
    SPI2_Init();

    // Enable RXNE interrupt on SPI2
    SPI_IRQInterruptConfig(IRQ_NO_SPI2, ENABLE);

    // Enable SPI peripheral — slave stays enabled, waiting
    SPI_PeripheralControl(SPI2, ENABLE);

    while (1) {
        // Nothing here — everything handled in IRQ
    }

    return 0;
}

 

Output

Video

Add a video of the output (know more)

 

 

 

 

 

Photo of Output

Add a photo of your hardware showing the output.

 


 

Was this helpful?
Upvote
Downvote