Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SPI Slave setup on STM32F4 board

I am trying to communicate between two STM32F4 discovery boards via SPI in Master & Slave configuration. I already have the code for the master but I am a bit confused on the changes I need to make on the SPI initialisation for the slave.

I would also like to implement an interrupt whenever the master is sending data, rather than having the slave poll the RXNE register all the time. However, I am unsure of the exact configurations for the NVIC for the SPI.

Below is the master's configuration code

void init_SPI1(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    SPI_InitTypeDef SPI_InitStruct;

    // enable clock for used IO pins
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    /* configure pins used by SPI1
     * PA5 = SCK
     * PA6 = MISO
     * PA7 = MOSI
     */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // connect SPI1 pins to SPI alternate function
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

    // enable clock for used IO pins
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

    /* Configure the chip select pin
       in this case we will use PE7 */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high

    // enable peripheral clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    /* configure SPI1 in Mode 0 
     * CPOL = 0 --> clock is low when idle
     * CPHA = 0 --> data is sampled at the first edge
     */
    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
    SPI_Init(SPI1, &SPI_InitStruct); 

    SPI_Cmd(SPI1, ENABLE); // enable SPI1
}

The reference manual states that I need the CPOL and CPHA bits to be configured the same as the master, this is also true for MSB/LSB first frame format. Apart from this I am unsure on how to configure the rest.

like image 492
user2253922 Avatar asked Dec 02 '13 02:12

user2253922


People also ask

How does SPI work in STM32?

SPI is a bus, which means you can use multiple peripheral devices for one controller. All of the lines are shared except for the CS line. You will need to dedicate one pin on your controller as a separate CS line for each peripheral you wish to communicate with.

What is slave mode in SPI?

In slave mode, the SPI can operate at clock rates up to the bus frequency, or 8 MHz in most 68HC08 MCUs. The SPI is configurable for both polarity and phase enabling the SPI to communicate with most serial peripherals.

Is multiple slaves possible in SPI protocol?

No, it's not possible. Since SPI is 4- wire interface. The SS line is used for slave selection. One SPI master can have multiple slaves but it cannot select all the slaves at once since it is either using some bit or SS signal to select the slave(and cannot select multiple slave at a single time).

What is SPI with DMA?

QSPI is used to conduct SPI Master Slave communication using the DMA module. This example implements an SPI full duplex communication. QSPI2 is configured as an SPI master and QSPI3 is configured as an SPI. slave. Both master and slave exchange eight bytes of data.


1 Answers

You should change mode to SPI_Mode_Slave (by the way, SPI_Mode_Master implies SPI_NSSInternalSoft_Set), set SPI_NSS based on slave select method you are going to use:

  • If you use SPI_NSS_Hard, configure appropriate pin as AF/OD with pull-up (if you haven't external pull-up resistor) and connect it to AF using GPIO_PinAFConfig.
  • If you have only one slave, use SPI_NSS_Soft: it'll be automatically selected (if you won't set SPI_NSSInternalSoft_Set).
  • If you use non-standard pin for slave select, configure EXTI to recieve interrupt on slave selection and reset internal NSS with SPI_NSSInternalSoft_Reset by software.

The last one is unrecommended, it's kind of kludge.

So, to get simple configuration use NSS_Soft (permanently selected). If you have more than 1 slave, use NSS_Hard.

Also you have to configure GPIO. SCK and MOSI should be AF/PP outputs on master and AF inputs on slave; MISO should be AF input on master and AF/PP output on slave; NSS should be AF input on slave.

like image 160
Konstantin Gribov Avatar answered Oct 15 '22 11:10

Konstantin Gribov