Skip to main content
kyleprice
Associate II
October 13, 2015
Question

STM32F401RET6 - Nucleo Board - SPI Problems

  • October 13, 2015
  • 2 replies
  • 813 views
Posted on October 14, 2015 at 00:53

I have been working on setting up and trying to test the SPI output from the Nucleo-F401RE. I am currently using a logic analyzer to view the data and clock lines, though I have not yet been able to see any change on either line...

Here is what I have so far (I am very new to STM and the HAL libraries...):


#include ''stm32f4xx.h''

#include ''NONPRECISIONDELAY.h''


int main(void)

{

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;

RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;


// HAL GPIO - Onboard LED init

GPIO_InitTypeDef ledInit;

ledInit.Pin = GPIO_PIN_5;

ledInit.Mode = GPIO_MODE_OUTPUT_PP;

ledInit.Pull = GPIO_NOPULL;

ledInit.Speed = GPIO_SPEED_HIGH;

HAL_GPIO_Init(GPIOA, &ledInit);

/* END GPIO INIT */


// CS

GPIO_InitTypeDef spiOneGpioInit_t;

spiOneGpioInit_t.Pin = GPIO_PIN_12;

spiOneGpioInit_t.Mode = GPIO_MODE_AF_PP;

spiOneGpioInit_t.Pull = GPIO_PULLUP;

spiOneGpioInit_t.Speed = GPIO_SPEED_LOW;

spiOneGpioInit_t.Alternate = GPIO_AF5_SPI2;

HAL_GPIO_Init(GPIOB, &spiOneGpioInit_t);


// SPI 2

spiOneGpioInit_t.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13;

spiOneGpioInit_t.Mode = GPIO_MODE_AF_PP;

spiOneGpioInit_t.Pull = GPIO_PULLDOWN;

spiOneGpioInit_t.Speed = GPIO_SPEED_LOW;

spiOneGpioInit_t.Alternate = GPIO_AF5_SPI2;

HAL_GPIO_Init(GPIOB, &spiOneGpioInit_t);


// SPI Handler

SPI_HandleTypeDef hspi;

hspi.Instance = SPI2;

hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;

hspi.Init.Direction = SPI_DIRECTION_2LINES;

hspi.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi.Init.DataSize = SPI_DATASIZE_8BIT;

hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi.Init.TIMode = SPI_TIMODE_DISABLED;

hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

hspi.Init.NSS = SPI_NSS_HARD_OUTPUT;



if (HAL_SPI_Init(&hspi) != HAL_OK)

{

HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // On board LED for indication 

return 1;

}


uint8_t data[] = {0xff};


while(1)

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // On board LED for indication 

delayMs(500);

HAL_SPI_Transmit(&hspi, data, 1, 10);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // On board LED for indication 

delayMs(500);

}

}

    This topic has been closed for replies.

    2 replies

    kyleprice
    kylepriceAuthor
    Associate II
    October 14, 2015
    Posted on October 14, 2015 at 20:52

    So I ended up doing away with the HAL libraries, as they were just further confusing things... The SPI2 port works perfectly using the following test:

    (Which just counts through 0 - 255 sending each after a period of delay, to see on a logic analyzer)

    
    #include ''stm32f4xx.h''
    
    #include ''NONPRECISIONDELAY.h''
    
    
    #define GPIO_AFRH_AF5_15 ((uint32_t)0x50000000)
    
    #define GPIO_AFRH_AF5_14 ((uint32_t)0x05000000)
    
    #define GPIO_AFRH_AF5_13 ((uint32_t)0x00500000)
    
    #define GPIO_AFRH_AF5_12 ((uint32_t)0x00050000)
    
    
    int main(void)
    
    {
    
    // Turn on GPIOB and SPI2 Clocks
    
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
    
    RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
    
    
    // MOSI - PB15
    
    GPIOB->MODER |= GPIO_MODER_MODER15_1;
    
    GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_15);
    
    GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15;
    
    GPIOB->PUPDR |= GPIO_PUPDR_PUPDR15_1;
    
    GPIOB->AFR[1] |= GPIO_AFRH_AF5_15;
    
    
    // MISO - PB14
    
    GPIOB->MODER |= GPIO_MODER_MODER14_1;
    
    GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_14);
    
    GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR14;
    
    GPIOB->PUPDR |= GPIO_PUPDR_PUPDR14_1;
    
    GPIOB->AFR[1] |= GPIO_AFRH_AF5_14;
    
    
    // SCLK - PB13
    
    GPIOB->MODER |= GPIO_MODER_MODER13_1;
    
    GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_13);
    
    GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13;
    
    GPIOB->PUPDR |= GPIO_PUPDR_PUPDR13_1;
    
    GPIOB->AFR[1] |= GPIO_AFRH_AF5_13;
    
    
    // CS - PB12
    
    GPIOB->MODER |= GPIO_MODER_MODER12_0;
    
    GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_12);
    
    GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12;
    
    GPIOB->PUPDR |= GPIO_PUPDR_PUPDR14_0;
    
    
    GPIOB->ODR |= GPIO_ODR_ODR_12;
    
    
    SPI2->CR1 |= SPI_CR1_BR_0 | SPI_CR1_BR_1;
    
    SPI2->CR2 |= SPI_CR2_SSOE;
    
    SPI2->CR1 |= SPI_CR1_MSTR;
    
    SPI2->CR1 |= SPI_CR1_SPE;
    
    
    volatile uint8_t data = 0x01;
    
    uint8_t input;
    
    
    while(1)
    
    {
    
    if (SPI2->SR & SPI_SR_TXE)
    
    {
    
    GPIOB->ODR &= ~(GPIO_ODR_ODR_12); // CS goes LOW
    
    SPI2->DR = data++; // Send byte and increment
    
    while ((SPI2->SR & SPI_SR_RXNE) == 0); // Wait for frame end RXNE = 1
    
    input = SPI2->DR; // Read to clear RXNE for next time through
    
    GPIOB->ODR |= GPIO_ODR_ODR_12; // CS goes HIGH - could swap with read
    
    }
    
    delayMs(500); // 
    
    }
    
    }

    waclawek.jan
    Super User
    October 14, 2015
    Posted on October 14, 2015 at 21:23

    > GPIOB->ODR &= ~(GPIO_ODR_ODR_12)

    I recommend using the GPIOx_BSRR register instead of performing RMW operations on the GPIOx_ODR register. Check in stm32f4xx.h to for the GPIOx_BSRR register's name(s) there. JW