AnsweredAssumed Answered

stm32f407 eval

Question asked by pietrobon.cristian on Oct 31, 2013
Hi to everyone, i'm new to this forum.
I started using the eval board with the mcu stm32f407vgt6.

I have some problem with the spi SLAVE mode.

Following the examples TwoBoards interrupts (STM32F4xx_DSP_StdPeriph_Lib_V1.1.0\Project\STM32F4xx_StdPeriph_Examples\SPI\SPI_TwoBoards\SPI_DataExchangeInterrupt)

i can get the master to work like a charm (tested on a scope, clock and dataout),
but the slave start sending the data after the first clock, so the data is 1 bit shifted and all i get is junk.

how can i figure out the problem?

spi is SPI1

images:
http://imageshack.us/g/707/0fs7.png/
first image is clock and dataout from master

second image is dataout from master(blu) and slave(yellow)

Posting the code:

main.c

/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/** @addtogroup STM32F4xx_StdPeriph_Examples
  * @{
  */
 
/** @addtogroup SPI_DataExchangeInterrupt
  * @{
  */
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
    uint8_t aTxBuffer[BUFFERSIZE] = "SPI Master/Slave : Communication between two SPI using Interrupts";
__IO uint8_t aRxBuffer [BUFFERSIZE];
__IO uint8_t ubRxIndex = 0;
__IO uint8_t ubTxIndex = 0;
__IO uint32_t TimeOut = 0;
 
SPI_InitTypeDef  SPI_InitStructure;
 
/* Private function prototypes -----------------------------------------------*/
static void SPI_Config(void);
static void SysTickConfig(void);
static TestStatus Buffercmp(uint8_t* pBuffer1, __IO uint8_t* pBuffer2, uint16_t BufferLength);
 
/* Private functions ---------------------------------------------------------*/
 
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       files (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
       application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f4xx.c file
     */
   
  /* SPI configuration */
  SPI_Config();
   
  /* SysTick configuration */
  SysTickConfig();
   
  /* LEDs configuration */
  STM_EVAL_LEDInit(LED4);
  STM_EVAL_LEDInit(LED5);
  STM_EVAL_LEDInit(LED6);
  STM_EVAL_LEDInit(LED3);
   
   
#define SPI_SLAVE_1
   
#ifdef SPI_MASTER_1
  /* Master board configuration */   
  /* Initializes the SPI communication */
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_Init(SPIx, &SPI_InitStructure);
   
  /* The Data transfer is performed in the SPI interrupt routine */
  /* Configure the Tamper Button */
  STM_EVAL_PBInit(BUTTON_USER,BUTTON_MODE_GPIO);
   
  /* Wait until Tamper Button is pressed */
  while (STM_EVAL_PBGetState(BUTTON_USER));
   
  /* Enable the SPI peripheral */
  SPI_Cmd(SPIx, ENABLE);
   
  /* Initialize Buffer counters */
  ubTxIndex = 0;
  ubRxIndex = 0;
   
  /* Enable the Rx buffer not empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, ENABLE);
   
  /* Enable the Tx buffer empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_TXE, ENABLE);
   
#endif /* SPI_MASTER */
   
#ifdef SPI_SLAVE_1
  /* Slave board configuration */
  /* Initializes the SPI communication */
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_Init(SPIx, &SPI_InitStructure);
   
  /* The Data transfer is performed in the SPI interrupt routine */
  /* Initialize Buffer counters */
  ubTxIndex = 0;
  ubRxIndex = 0;
   
  /* Enable the Rx buffer not empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, ENABLE);
   
  /* Enable the Tx empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_TXE, ENABLE);
   
  /* Enable the SPI peripheral */
  SPI_Cmd(SPIx, ENABLE);
   
#endif /* SPI_SLAVE */
   
  /* Waiting the end of Data transfer */
  while ((ubTxIndex < BUFFERSIZE) && (ubRxIndex < BUFFERSIZE))
  {
  }
   
  /* Disable the Rx buffer not empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, DISABLE);
   
  /* Disable the Tx empty interrupt */
  SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_TXE, DISABLE);
   
  /* Disable the SPI peripheral */
  SPI_Cmd(SPIx, DISABLE);
   
  if (Buffercmp(aTxBuffer, aRxBuffer, BUFFERSIZE) != FAILED)
  {
    /* Turn ON LED1 and LED3 */
    STM_EVAL_LEDOn(LED4);
    STM_EVAL_LEDOn(LED5);
    /* Turn OFF LED2 and LED4 */
    STM_EVAL_LEDOff(LED3);
    STM_EVAL_LEDOff(LED6);
  }
  else
  {
    /* Turn OFF LED1 and LED3 */
    STM_EVAL_LEDOff(LED4);
    STM_EVAL_LEDOff(LED5);
    /* Turn ON LED2 and LED4 */
    STM_EVAL_LEDOn(LED3);
    STM_EVAL_LEDOn(LED6);   
  }
   
  /* Infinite Loop */
  while (1)
  {
  
}
 
/**
  * @brief  Configures the SPI Peripheral.
  * @param  None
  * @retval None
  */
static void SPI_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
 
  /* Peripheral Clock Enable -------------------------------------------------*/
  /* Enable the SPI clock */
  SPIx_CLK_INIT(SPIx_CLK, ENABLE);
   
  /* Enable GPIO clocks */
  RCC_AHB1PeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK | SPIx_MOSI_GPIO_CLK, ENABLE);
 
  /* SPI GPIO Configuration --------------------------------------------------*/
  /* GPIO Deinitialisation */
  GPIO_DeInit(SPIx_SCK_GPIO_PORT);
  GPIO_DeInit(SPIx_MISO_GPIO_PORT);
  GPIO_DeInit(SPIx_MOSI_GPIO_PORT);
   
  /* Connect SPI pins to AF5 */ 
  GPIO_PinAFConfig(SPIx_SCK_GPIO_PORT, SPIx_SCK_SOURCE, SPIx_SCK_AF);
  GPIO_PinAFConfig(SPIx_MISO_GPIO_PORT, SPIx_MISO_SOURCE, SPIx_MISO_AF);   
  GPIO_PinAFConfig(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_SOURCE, SPIx_MOSI_AF);
 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
 
  /* SPI SCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;
  GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStructure);
   
  /* SPI  MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin =  SPIx_MISO_PIN;
  GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStructure); 
 
  /* SPI  MOSI pin configuration */
  GPIO_InitStructure.GPIO_Pin =  SPIx_MOSI_PIN;
  GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStructure);
  
  /* SPI configuration -------------------------------------------------------*/
  SPI_I2S_DeInit(SPIx);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  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_32;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
   
  /* Configure the Priority Group to 1 bit */               
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   
  /* Configure the SPI interrupt priority */
  NVIC_InitStructure.NVIC_IRQChannel = SPIx_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
 
/**
  * @brief  Configure a SysTick Base time to 10 ms.
  * @param  None
  * @retval None
  */
static void SysTickConfig(void)
{
  /* Setup SysTick Timer for 10ms interrupts  */
  if (SysTick_Config(SystemCoreClock / 100))
  {
    /* Capture error */
    while (1);
  }
 
  /* Configure the SysTick handler priority */
  NVIC_SetPriority(SysTick_IRQn, 0x0);
}
 
 
/**
  * @brief  Compares two buffers.
  * @param  pBuffer1, pBuffer2: buffers to be compared.
  * @param  BufferLength: buffer's length
  * @retval PASSED: pBuffer1 identical to pBuffer2
  *         FAILED: pBuffer1 differs from pBuffer2
  */
static TestStatus Buffercmp(uint8_t* pBuffer1, __IO uint8_t* pBuffer2, uint16_t BufferLength)
{
  while (BufferLength--)
  {
    if (*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }
    pBuffer1++;
    pBuffer2++;
  }
 
  return PASSED;
}

main.h
#include "stm32f4xx.h"
#include "stm32f4_discovery.h" 
 
#define SPIx                           SPI1
  #define SPIx_CLK                       RCC_APB2Periph_SPI1
  #define SPIx_CLK_INIT                  RCC_APB2PeriphClockCmd
  #define SPIx_IRQn                      SPI1_IRQn
  #define SPIx_IRQHANDLER                SPI1_IRQHandler
 
  #define SPIx_SCK_PIN                   GPIO_Pin_5
  #define SPIx_SCK_GPIO_PORT             GPIOA
  #define SPIx_SCK_GPIO_CLK              RCC_AHB1Periph_GPIOA
  #define SPIx_SCK_SOURCE                GPIO_PinSource5
  #define SPIx_SCK_AF                    GPIO_AF_SPI1
 
  #define SPIx_MISO_PIN                  GPIO_Pin_6
  #define SPIx_MISO_GPIO_PORT            GPIOA
  #define SPIx_MISO_GPIO_CLK             RCC_AHB1Periph_GPIOA
  #define SPIx_MISO_SOURCE               GPIO_PinSource6
  #define SPIx_MISO_AF                   GPIO_AF_SPI1
 
  #define SPIx_MOSI_PIN                  GPIO_Pin_7
  #define SPIx_MOSI_GPIO_PORT            GPIOA
  #define SPIx_MOSI_GPIO_CLK             RCC_AHB1Periph_GPIOA
  #define SPIx_MOSI_SOURCE               GPIO_PinSource7
  #define SPIx_MOSI_AF                   GPIO_AF_SPI1
 
 
#define BUFFERSIZE                       100

interrupts

void SPIx_IRQHANDLER(void)
{
  /* SPI in Receiver mode */
  if (SPI_I2S_GetITStatus(SPIx, SPI_I2S_IT_RXNE) == SET)
  {
    if (ubRxIndex < BUFFERSIZE)
    {
      /* Receive Transaction data */
      aRxBuffer[ubRxIndex++] = SPI_I2S_ReceiveData(SPIx);
    }
    else
    {
      /* Disable the Rx buffer not empty interrupt */
      SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, DISABLE);
    }
  }
  /* SPI in Tramitter mode */
  if (SPI_I2S_GetITStatus(SPIx, SPI_I2S_IT_TXE) == SET)
  {
    if (ubTxIndex < BUFFERSIZE)
    {
      /* Send Transaction data */
      SPI_I2S_SendData(SPIx, aTxBuffer[ubTxIndex++]);
    }
    else
    {
      /* Disable the Tx buffer empty interrupt */
      SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_TXE, DISABLE);
    }
  }
}
 
void SysTick_Handler(void)
{
  /* Decrement the timeout value */
  if (TimeOut != 0)
  {
    TimeOut--;
  }
     
  if (ubCounter < 10)
  {
    ubCounter++;
  }
  else
  {
    ubCounter = 0;
    STM_EVAL_LEDToggle(LED3);
  }
}

Outcomes