I am using F411RE Nucleo board to communicate with some other devices through SPI.
My code is based on SPI LL example SPI_TwoBoards_FullDuplex_DMA in package STM32Cube_FW_F4_V1.26.0.
The original code works well. However, my app needs more than one SPI; so I tried to change SPI1 to SPI4.
The DMA and SPI configurations are showed in below:
/** * @brief This function configures the DMA Channels for SPI1 * @note This function is used to : * -1- Enable DMA2 clock * -2- Configure NVIC for DMA2 transfer complete/error interrupts * -3- Configure the DMA2_Stream2 functional parameters * -4- Configure the DMA2_Stream3 functional parameters * -5- Enable DMA2 interrupts complete/error * @param None * @retval None */ void Configure_DMA(void) { /* DMA2 used for SPI1 Transmission * DMA2 used for SPI1 Reception */ /* (1) Enable the clock of DMA2 and DMA2 */ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2); /* (2) Configure NVIC for DMA transfer complete/error interrupts */ #ifdef USE_SPI1 NVIC_SetPriority(DMA2_Stream2_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream2_IRQn); NVIC_SetPriority(DMA2_Stream3_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream3_IRQn); #endif #ifdef USE_SPI4 NVIC_SetPriority(DMA2_Stream0_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream0_IRQn); NVIC_SetPriority(DMA2_Stream1_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream1_IRQn); #endif /* (3) Configure the DMA2_Stream2 functional parameters */ LL_DMA_ConfigTransfer(DMA2, SPI_RX_STREAM, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); LL_DMA_ConfigAddresses(DMA2, SPI_RX_STREAM, LL_SPI_DMA_GetRegAddr(SPI), (uint32_t)aRxBuffer, LL_DMA_GetDataTransferDirection(DMA2, SPI_RX_STREAM)); LL_DMA_SetDataLength(DMA2, SPI_RX_STREAM, ubNbDataToReceive); LL_DMA_SetChannelSelection(DMA2, SPI_RX_STREAM, SPI_RX_CHANNEL); /* (4) Configure the DMA2_Stream3 functional parameters */ LL_DMA_ConfigTransfer(DMA2, SPI_TX_STREAM, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); LL_DMA_ConfigAddresses(DMA2, SPI_TX_STREAM, (uint32_t)aTxBuffer, LL_SPI_DMA_GetRegAddr(SPI), LL_DMA_GetDataTransferDirection(DMA2, SPI_TX_STREAM)); LL_DMA_SetDataLength(DMA2, SPI_TX_STREAM, ubNbDataToTransmit); LL_DMA_SetChannelSelection(DMA2, SPI_TX_STREAM, SPI_TX_CHANNEL); /* (5) Enable DMA interrupts complete/error */ LL_DMA_EnableIT_TC(DMA2, SPI_RX_STREAM); LL_DMA_EnableIT_TE(DMA2, SPI_RX_STREAM); LL_DMA_EnableIT_TC(DMA2, SPI_TX_STREAM); LL_DMA_EnableIT_TE(DMA2, SPI_TX_STREAM); } /** * @brief This function configures SPI1. * @note This function is used to : * -1- Enables GPIO clock and configures the SPI1 pins. * -2- Configure SPI1 functional parameters. * @note Peripheral configuration is minimal configuration from reset values. * Thus, some useless LL unitary functions calls below are provided as * commented examples - setting is default configuration from reset. * @param None * @retval None */ void Configure_SPI(void) { /* (1) Enables GPIO clock and configures the SPI1 pins ********************/ /* Enable the peripheral clock of GPIOB */ if(! LL_AHB1_GRP1_IsEnabledClock(LL_AHB1_GRP1_PERIPH_GPIOB)) { LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB); } if(! LL_AHB1_GRP1_IsEnabledClock(LL_AHB1_GRP1_PERIPH_GPIOA)) { LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); } #ifdef USE_SPI1 /* Configure SCK Pin connected to pin 31 of CN10 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_CLK_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_CLK_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_CLK_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_CLK_PIN, LL_GPIO_PULL_DOWN); /* Configure MISO Pin connected to pin 27 of CN10 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_MISO_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_MISO_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_MISO_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_MISO_PIN, LL_GPIO_PULL_DOWN); /* Configure MOSI Pin connected to pin 29 of CN7 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_MOSI_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_MOSI_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_MOSI_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_MOSI_PIN, LL_GPIO_PULL_DOWN); /* (2) Configure SPI1 functional parameters ********************************/ /* Enable the peripheral clock of GPIOB */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); #endif #ifdef USE_SPI4 /* Configure SCK Pin PB13 */ LL_GPIO_SetPinMode(GPIOB, SPI_CLK_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(GPIOB, SPI_CLK_PIN, LL_GPIO_AF_6); LL_GPIO_SetPinSpeed(GPIOB, SPI_CLK_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_CLK_PIN, LL_GPIO_PULL_DOWN); /* Configure MISO Pin PA11 */ LL_GPIO_SetPinMode(GPIOA, SPI_MISO_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(GPIOA, SPI_MISO_PIN, LL_GPIO_AF_6); LL_GPIO_SetPinSpeed(GPIOA, SPI_MISO_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOA, SPI_MISO_PIN, LL_GPIO_PULL_DOWN); /* Configure MOSI Pin PA1 */ LL_GPIO_SetPinMode(GPIOA, SPI_MOSI_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOA, SPI_MOSI_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOA, SPI_MOSI_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOA, SPI_MOSI_PIN, LL_GPIO_PULL_DOWN); /* (2) Configure SPI4 functional parameters ********************************/ /* Enable the peripheral clock of GPIOB */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI4); #endif /* Configure SPI1 communication */ LL_SPI_SetBaudRatePrescaler(SPI, LL_SPI_BAUDRATEPRESCALER_DIV8); LL_SPI_SetTransferDirection(SPI, LL_SPI_FULL_DUPLEX); LL_SPI_SetClockPhase(SPI, LL_SPI_PHASE_1EDGE); LL_SPI_SetClockPolarity(SPI, LL_SPI_POLARITY_LOW); /* Reset value is LL_SPI_MSB_FIRST */ LL_SPI_SetTransferBitOrder(SPI, LL_SPI_MSB_FIRST); LL_SPI_SetDataWidth(SPI, LL_SPI_DATAWIDTH_8BIT); LL_SPI_SetNSSMode(SPI, LL_SPI_NSS_SOFT); #ifdef MASTER_BOARD LL_SPI_SetMode(SPI, LL_SPI_MODE_MASTER); #else /* Reset value is LL_SPI_MODE_SLAVE */ //LL_SPI_SetMode(SPI, LL_SPI_MODE_SLAVE); #endif /* MASTER_BOARD */ /* Configure SPI1 DMA transfer interrupts */ /* Enable DMA RX Interrupt */ LL_SPI_EnableDMAReq_RX(SPI); /* Enable DMA TX Interrupt */ LL_SPI_EnableDMAReq_TX(SPI); }
Some of the macro definitions are showed here:
//#define USE_SPI1 #define USE_SPI4 #ifdef USE_SPI1 #define SPI SPI1 #define SPI_RX_STREAM LL_DMA_STREAM_2 #define SPI_RX_CHANNEL LL_DMA_CHANNEL_3 #define SPI_TX_STREAM LL_DMA_STREAM_3 #define SPI_TX_CHANNEL LL_DMA_CHANNEL_3 #define SPI_CLK_PIN LL_GPIO_PIN_3 #define SPI_MOSI_PIN LL_GPIO_PIN_5 #define SPI_MISO_PIN LL_GPIO_PIN_4 #endif #ifdef USE_SPI4 #define SPI SPI4 #define SPI_RX_STREAM LL_DMA_STREAM_0 #define SPI_RX_CHANNEL LL_DMA_CHANNEL_4 #define SPI_TX_STREAM LL_DMA_STREAM_1 #define SPI_TX_CHANNEL LL_DMA_CHANNEL_4 #define SPI_CLK_PIN LL_GPIO_PIN_13 #define SPI_MOSI_PIN LL_GPIO_PIN_1 #define SPI_MISO_PIN LL_GPIO_PIN_11 #endif
The whole project works well when I enable SPI1, but does not work when SPI4 is enabled (SPI1 disabled). The problem is that I cannot see any signal on CLK, MISO, and MOSI pins.
Like I2C, SPI is a common communication protocol in embedded devices. It often supports higher data rates than I2C, but it requires more pins to use. In this tutorial, I’ll show you how to set up SPI using STM32CubeIDE and communicate with an external EEPROM chip.
Toys R Us Credit Card Login
Thx. Where is the tutorial?