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.
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.
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.
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).
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.
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:
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
.SPI_NSS_Soft
: it'll be automatically selected (if you won't set SPI_NSSInternalSoft_Set
).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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With