cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F401RET6 - Nucleo Board - SPI Problems

kyleprice
Associate II
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);

}

}

2 REPLIES 2
kyleprice
Associate II
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); // 

}

}

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