Skip to main content
i__it
Associate II
May 2, 2013
Question

STM32 SPI Setup

  • May 2, 2013
  • 13 replies
  • 3872 views
Posted on May 02, 2013 at 12:36

Hi all,

New to the stm32 range and so far all is well. I am having a couple of problems setting up SPI on my stm32vldiscovery board and was hoping to get some help. I'm sure I must be missing something very small but can't seem to find it. I have probed portB with a scope but havn't got any visible output.

I have a couple of theories on what may be the problem, perhaps you can help.

The lines:

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);

Will not compile, I get an error: GPIO_AF_SPI2 is undeclared. To compile I have been commenting these out.

I have not setup any clock preferences?

Thanks again, please see attached code below. (apologies for messy code, still just getting bits working!)

Ian

/**

******************************

******************************

******************

  * @file    main.c

  * @author  icooper

  * @version V1.0.0

  * @date    29/04//2013

  * @brief   Main program body.

******************************

******************************

******************

  * File Description:

  * Just messing around with some io

  */

/* Includes ------------------------------

------------------------------

------*/

&sharpinclude ''stm32f10x.h''

&sharpinclude ''stm32f10x_rcc.h''

&sharpinclude ''stm32f10x_gpio.h''

&sharpinclude ''stm32f10x_usart.h''

&sharpinclude ''stm32f10x_spi.h''

&sharpinclude ''stdint.h''

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

SPI_InitTypeDef SPI_InitStructure;

void Delay(uint32_t nTime);

int main(void)

{

    //Enable Peripheral Clocks, GPIOC, GPIOA, USART1, Alternative Function(AF), SPI2

    RCC_APB2PeriphClockCmd(RCC_

APB

2Periph_GPIOC |

                           RCC_APB2Periph_GPIOA |

                           RCC_APB2Periph_GPIOB |

                           //RCC_APB2Periph_USART1 |

                           RCC_APB2Periph_AFIO ,

                           ENABLE);

    RCC_APB1PeriphClockCmd(RCC_

APB

1Periph_SPI2 , ENABLE);

    //Configure Pins for CS for SPI

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //GPIO_Pin is a bit vector

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Output Push Pull

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Set Speed

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //confugre spi - CLK PA5, MOSI PA7

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Alternative function - push pull

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Set Speed

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);

    //Configure SysTickTimer

    if    (SysTick_Config(

SystemCoreClo

ck / 1000))

    while(1);

    SPI_Cmd(SPI2, DISABLE);

    //configure spi

    SPI_InitStructure.SPI_

Directio

n = SPI_Direction_2Lines_

FullDuple

x;

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

    SPI_InitStructure.SPI_

BaudRate

Prescaler = SPI_BaudRatePrescaler_16;

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

    SPI_InitStructure.SPI_

CRCPolyn

omial = 7;

    SPI_Init(SPI2, &SPI_InitStructure);

    SPI_Cmd(SPI2, ENABLE);

  while (1)

  {

      Delay(50); //wait 50ms

      sendbyte_spi_lcd('c');

      Delay(50); //wait 50ms

  }

}

void sendbyte_spi_lcd(unsigned char byte){

    GPIO_WriteBit(GPIOA, GPIO_Pin_4, 0);

    GPIO_WriteBit(GPIOC, GPIO_Pin_8, 1);

    SPI_I2S_SendData(SPI2, byte);

    //while(SPI_I2S_GetFlagStatus(

SPI2, SPI_I2S_FLAG_BSY) == SET);

}

//Delay loop

static __IO uint32_t TimingDelay;

void Delay(uint32_t nTime){

    TimingDelay = nTime;

    while(TimingDelay != 0);

}

void SysTick_Handler(void){

    if (TimingDelay != 0x00)

        TimingDelay--;

}

#stm32 #spi
This topic has been closed for replies.

13 replies

Tesla DeLorean
Guru
May 2, 2013
Posted on May 02, 2013 at 13:36

GPIO_PinAFConfig() is not for F1 parts, but rather newer chip designs.

Make sure you look at the F1 firmware examples.

For the VL Discovery, make sure the project is set up correctly to recognize that the F100 parts can only run up to 24 MHz, and uses the appropriate startup.s file, and has the right defines. Where you can use a project template for the VL board.

Make sure TXE is asserted before jamming data to the device.
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
i__it
i__itAuthor
Associate II
May 2, 2013
Posted on May 02, 2013 at 13:48

Hi Clive1,

Thanks for the fast and informative reply!

Yeh, after some digging I have found a lack of that function in the GPIO.c file for this library anyway (no wonder it doesn't compile).  I am managing to successfully program my board and have UART working successfully, so I assume all is setup ok?

As far as I am aware TXE is set when data is transferred? 

Thanks again

Ian

i__it
i__itAuthor
Associate II
May 2, 2013
Posted on May 02, 2013 at 15:55

After poking around the internet for a while I have found this example which works on my board:

http://www.stm32circle.com/forum/viewtopic.php?id=536

It would seem the only real difference was clock setup. I will investigate more. Does this sound correct?

Ian
Tesla DeLorean
Guru
May 2, 2013
Posted on May 02, 2013 at 17:33

As far as I am aware TXE is set when data is transferred?

It should be front tested so as not to trash the currently pending data register. It should assert at about the time the first bit starts transmitting, ie data register is moved to the output shift register for transmission. RXNE asserts as the last bit is shifted back in.
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
shankar
Visitor II
November 20, 2013
Posted on November 20, 2013 at 13:49

Hello Clive,

I am not able to get SPI1 signals on STM32F103ZG.

I referred many of the STM32 Forum discussions, but I am not able to get the Clock or Data signals on SPI1 pins of STM32F103ZG on PortA Pin 5, 6 ,& 7. Please help me in solving this problem.

I have attached the code in Main file for your reference

int main(void)

{

        static uint8_t i;

    

        SPI_Ini();

    

     /* Enable SPI_MASTER TXE interrupt */

      SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);//**********************************************

    

           /* Enable the SPI peripheral */

       SPI_Cmd(SPI1, ENABLE);

    

    while(1)

        {

        /* Send SPI_MASTER data */

       SPI_I2S_SendData(SPI1, SPI_MASTER_Buffer_Tx[0]);

       

       for(TimDelay=0; TimDelay < 100000; TimDelay++);

        }

                

}  // main end

void SPI_Ini(void)

{

    

    SPI_InitTypeDef              SPI_InitStructure;

        GPIO_InitTypeDef      GPIO_InitStructure;

    

    /* Enable GPIOB for SCK, MISO, MOSI GPIO clocks */

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    

    /* Enable the SPI1 periph */

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    

 

    /*----------------------Inicialization SPI master------------------------------------*/

    

    /* SPI1 SCK pin configuration: AF PP output 50MHz  */

        GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            // alternate mode

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    // 50MHz

        GPIO_Init(GPIOA, &GPIO_InitStructure);

    

        /* SPI1 configuration -------------------------------------------------------*/

        SPI_I2S_DeInit(SPI1);

        SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;

        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;

        SPI_InitStructure.SPI_CRCPolynomial = 7;

        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

        SPI_Init(SPI1, &SPI_InitStructure);

    

    /*----------------------Inicialization SPI slave------------------------------------*/

 

    /* SPI2 SCK pin configuration: input mode 50MHz */

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;             // input mode

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    // 50MHz

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Enable the Rx buffer not empty interrupt */

    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);

    

    /* Configure the SPI interrupt priority */

        NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure);

    

    /* Enable the SPI peripheral */

        SPI_Cmd(SPI1, ENABLE);

}

Tesla DeLorean
Guru
November 20, 2013
Posted on November 20, 2013 at 15:11

To remap pins the AFIO clock must be enabled.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
shankar
Visitor II
November 21, 2013
Posted on November 21, 2013 at 07:38

Hello Clive,

I have done

changes

, as per your inputs by calling two Functions as below, after SPI_Ini

(

) in main

(

)..

GPIO_PinRemapConfig

(

GPIO_Remap_SPI1, ENABLE);

RCC_APB2PeriphClockCmd

(

RCC_APB2Periph_SPI1, ENABLE);

There are no

signals

on PA 5, 6 & 7. I have not connected anything on these lines. They are open. 

I just want to know whether clock and data signals are coming on these respective pins. Everything else works on my board.

Shankar

shankar
Visitor II
November 21, 2013
Posted on November 21, 2013 at 12:40

Hello,

Do we have to connect the SPI CLK, MOSI, MISO to any Pull up or Pull Down Externally. Hope STM32F103ZG supports only GPIO_InitStructure

.

GPIO_Pin; GPIO_InitStructure

.

GPIO_Mode GPIO_InitStructure

.

GPIO_Speed

for

configuring GPIO Pins,.. Because I couldn't see any other elements than these above 3 to configure GPIO'sin this IC. I mean, I don'thave elements like

GPIO_InitStructure.GPIO_OType
GPIO_InitStructure.GPIO_PuPd .
Please let me know the solution..
Thanks Shankar

Tesla DeLorean
Guru
November 21, 2013
Posted on November 21, 2013 at 15:34

There seem to be several problems here, firstly the code is incomplete, an IRQ is initialized and no routine is presented. The IRQ is supposed to service TXE, but then you have another loop that pays no mind to TXE and sends data to the peripheral. There is a loop which might get optimized out.

The purpose of PA8 is not explained.

PA5/PA6/PA7 aren't remapped functions, so why are they being remapped?

SCK/MOSI should be AF_PP

MISO should be IN_FLOATING

See also F1 Examples

STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\SPI\FullDuplex_SoftNSS\main.c
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
shankar
Visitor II
November 22, 2013
Posted on November 22, 2013 at 10:35

Hello Clive, I changed the code as per your inputs and is as below. With this code I am just looking for sending Clock and Data out signals to a slave from SPI1 pins. Or you can say on PORTA_SPI1 pins. This is also not working.. Using the debugger, I can see that, the execution is getting stuck in Function/line ''while (SPI_I2S_GetFlagStatus

(

SPI1, SPI_I2S_FLAG_TXE) == RESET);''

I have added this function definition below this code.

int

main

(

void)

{

  /*!< At this stage the

microcontroller

clock setting is already configured, 

       

this

is done through SystemInit

(

) function which is called from startup

       

file

(startup_stm32f10x_xx

.

s) before to branch to application main.

       To reconfigure the default setting of SystemInit

(

) function, refer to

       system_stm32f10x

.

c file

     */     

       

  /* System clocks configuration ---------------------------------------------*/

  SPI_RCC_Configuration

(

);

  /* 1st phase: SPIy Master and SPIz Slave */

  /* GPIO configuration ------------------------------------------------------*/

  SPI_GPIO_Configuration

(

SPI_Mode_Master, SPI_Mode_Slave);

  

  /*

SPIy

Config -------------------------------------------------------------*/

  SPI_InitStructure

.

SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure

.

SPI_Mode = SPI_Mode_Master;

  SPI_InitStructure

.

SPI_DataSize = SPI_DataSize_8b;

  SPI_InitStructure

.

SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure

.

SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure

.

SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure

.

SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

  SPI_InitStructure

.

SPI_FirstBit = SPI_FirstBit_LSB;

  SPI_InitStructure

.

SPI_CRCPolynomial = 7;

  SPI_Init

(

SPI1, &SPI_InitStructure);

  /* Enable

SPIy

*/

  SPI_Cmd

(

SPI1, ENABLE);

SPI_I2S_SendData

(

SPI1, SPIy_Buffer_Tx

[

TxIdx++]);

while

(TxIdx <

BufferSize

)

{

Millisecond_delay

(

10);

/* Wait for SPIy

Tx

buffer empty */

while

(SPI_I2S_GetFlagStatus

(

SPI1, SPI_I2S_FLAG_TXE) == RESET);

/* Send SPIy data */

SPI_I2S_SendData

(

SPI1, SPIy_Buffer_Tx

[

TxIdx++]);

/* Wait for SPIy data reception */

      

Millisecond_delay

(

10);

Millisecond_delay

(

10);

Millisecond_delay

(

10);

}

}  //

main

end

/**

  * @brief  Configures the different system clocks.

  * @param  None

  * @retval None

  */

void

SPI_RCC_Configuration

(

void)

{

  /* PCLK2 = HCLK/2 */

  RCC_PCLK2Config

(

RCC_HCLK_Div2); 

/* Enable peripheral clocks --------------------------------------------------*/

  /* Enable GPIO clock for SPIy */

  RCC_APB2PeriphClockCmd

(

RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);

  /* Enable

SPIy

Periph clock */

  RCC_APB1PeriphClockCmd

(

RCC_APB2Periph_SPI1, ENABLE);

}

/**

  * @brief  Configures the different SPIy and

SPIz

GPIO ports.

  * @param  SPIy_Mode: Specifies the SPIy operating mode. 

  *            This parameter can be:

  *              -  SPIy_Mode_Master

  *              -  SPIy_Mode_Slave                 

  * @param  SPIz_Mode: Specifies the SPIz operating mode. 

  *            This parameter can be:

  *              -  SPIz_Mode_Master

  *              -  SPIz_Mode_Slave 

  * @retval None

  */

void

SPI_GPIO_Configuration

(

uint16_t SPIy_Mode, uint16_t SPIz_Mode)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure

SPIy

pins: SCK, MISO and MOSI ---------------------------------*/

  GPIO_InitStructure

.

GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;

  GPIO_InitStructure

.

GPIO_Speed = GPIO_Speed_50MHz;

 

if

(

SPIy_Mode == SPI_Mode_Master)

  {

    /* Configure SCK and MOSI pins as Alternate Function Push Pull */

    GPIO_InitStructure

.

GPIO_Mode = GPIO_Mode_AF_PP;

  }

 

else

  {

/* Configure SCK and MOSI pins as Input Floating */

GPIO_InitStructure

.

GPIO_Mode = GPIO_Mode_IN_FLOATING;

  }

  GPIO_Init

(

GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure

.

GPIO_Pin = GPIO_Pin_6;

 

if

(

SPIy_Mode == SPI_Mode_Master)

  {

    /* Configure MISO pin as Input Floating  */

    GPIO_InitStructure

.

GPIO_Mode = GPIO_Mode_IN_FLOATING;

  }

 

else

  {

    /* Configure MISO pin as Alternate Function Push Pull */

    GPIO_InitStructure

.

GPIO_Mode = GPIO_Mode_AF_PP;

  }

  GPIO_Init

(

GPIOA, &GPIO_InitStructure);

}

In this below function, the ''

bitstatus

'' is becoming

TRUE

which is returned. But when I added the address SPI1 in Watch window, the

vaue

at ''SPIx->SR'' = 0. If this is the condition then ''

bitstatus

'' must be FALSE after the end of

Function

, which is not happening. Do

u

have any explanation. This is very strange for me..

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)

{

 

FlagStatus

bitstatus

= RESET;

  /* Check the parameters */

  assert_param

(

IS_SPI_ALL_PERIPH

(

SPIx));

  assert_param

(

IS_SPI_I2S_GET_FLAG

(

SPI_I2S_FLAG));

  /* Check the status of the specified SPI/I2S flag */

 

if

((SPIx->SR & SPI_I2S_FLAG) != (uint16_t

)

RESET)

  {

    /* SPI_I2S_FLAG is set */

   

bitstatus

= SET;

  }

 

else

  {

    /* SPI_I2S_FLAG is reset */

   

bitstatus

= RESET;

  }

  /* Return the SPI_I2S_FLAG status */

 

return

 

bitstatus

;

}

Hope you understood, what I am saying..

Thanks 

Shankar