AnsweredAssumed Answered

SPI communication between two STM32F407 for transfer of 10bytes buffer data from Master to Slave

Question asked by beginner.st on Sep 21, 2015
Latest reply on Oct 5, 2015 by beginner.st
Good Afternoon,

I am trying to build an SPI communication between 2 STM32F407. I am trying to send 10 bytes of data from Master to Slave through SPI ISR. When I try sending one byte , I am able to successfully receive it at the slave. Checked through scope as well . However sending 10 bytes of data continuously appears confusing to me. I think , I am unable to receive the 10bytes. The receive buffer appears to be empty . I do not know if I unable to handle the scope or debug or write the correct ISR. I have written the following the code for Master:                                              
#include "stm32f4xx.h"
#include "stm32f4xx_spi.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"

__IO uint8_t aRxBuffer [128];
__IO uint8_t ubRxIndex = 0;
__IO uint8_t ubTxIndex = 0;

#define UTD_SPI_LEN 128

uint8_t utd_readbuf [UTD_SPI_LEN];
uint8_t utd_writebuf[UTD_SPI_LEN];

int master_rev_buff[10];

RCC_ClocksTypeDef RCC_Clocks;
uint8_t sysclk_src;
void mySPI_Init(void);
uint8_t mySPI_SendData(uint8_t);

int main(void)
{
    RCC_HSEConfig(RCC_HSE_ON);
    while(!RCC_WaitForHSEStartUp())
    {}

    RCC_GetClocksFreq(&RCC_Clocks);
    sysclk_src=RCC_GetSYSCLKSource();
    RCC->AHB1ENR |= 0x00000001; // Enable clock for GPIOA for reading the User switch
    GPIOA->MODER |= 0x00000000; // Input pin for reading User Button PA0

    // Debug starts : Color Green indicates Master
    printf("Master! \n\r");
    RCC->AHB1ENR = 0x0000008; // Enable Clock for PortD
    GPIOD->MODER |= (1<<24);  // Enable PortD Pin 12 as a digital output
    GPIOD->ODR |= (1<<12);    // Turn GPIO Pin 12 ON or Assert High
    // Debug ends

    mySPI_Init();

    while(1){}
}

void mySPI_Init(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    SPI_InitTypeDef SPI_InitTypeDefStruct;

    SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
    SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft; // Chip Select Software
    SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High; // Clock Pol
    SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_1Edge;

    SPI_Init(SPI1, &SPI_InitTypeDefStruct);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE , ENABLE);

    GPIO_InitTypeDef GPIO_InitTypeDefStruct;
    /* configure pins used by SPI1
        * PA5 = SCK
        * PA6 = MISO
        * PA7 = MOSI
        */
    GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
    GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitTypeDefStruct.GPIO_PuPd =  GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);

    GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_Init(GPIOE, &GPIO_InitTypeDefStruct);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

    GPIO_SetBits(GPIOE, GPIO_Pin_3);

    while(!(GPIOA->IDR & 0x01));  //wait when PA0=0

    NVIC_EnableIRQ (SPI1_IRQn);                               // enable interrupt on SPI1

    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);

    SPI_Cmd(SPI1, ENABLE);

}
void SPI1_IRQHandler(void)
{
    static unsigned short int count = 0, i = 0 ;
    GPIO_ResetBits(GPIOE, GPIO_Pin_3);
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) == SET)
    {
        if(ubTxIndex < 10)
        {
                SPI1->DR  = ubTxIndex;
                ubTxIndex++;
        }
        else
        {
                SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
        }
    }
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
    {
        if(ubRxIndex < 10)
           {
                aRxBuffer[ubRxIndex++] = SPI1->DR ;
                //master_rev_buff[i] = SPI1->DR ;
                //i++ ;
           }
        else
           {
                SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
           }
    }
    GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
The following is the code for Slave :                                                                                      
#include "stm32f4xx.h"
#include "stm32f4xx_spi.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"

__IO uint8_t aRxBuffer[128];
__IO uint8_t ubRxIndex=0;
__IO uint8_t ubTxIndex=0;

int Slave_rev_buff[10];

RCC_ClocksTypeDef RCC_Clocks;
uint8_t sysclk_src;

void mySPI_Init(void);
uint8_t mySPI_SendData(uint8_t data);

int main(void)
{
    RCC_HSEConfig(RCC_HSE_ON);
    while(!RCC_WaitForHSEStartUp())
    {}

    RCC_GetClocksFreq(&RCC_Clocks);
    sysclk_src=RCC_GetSYSCLKSource();

    mySPI_Init();

    printf("Slave! \n\r");

    while(1){}
}
uint8_t mySPI_SendData(uint8_t data){
    uint8_t dt;
    GPIO_ResetBits(GPIOE, GPIO_Pin_3);

    while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));  // transmit buffer empty?
    //while(SPI1->SR & SPI_I2S_FLAG_BSY);                   // wait until SPI is not busy anymore

    SPI1->DR = data;
    while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));

    GPIO_SetBits(GPIOE, GPIO_Pin_3);                        // Transmit enable flag setzen
    return dt;
}

void mySPI_Init(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    SPI_InitTypeDef SPI_InitTypeDefStruct;

    SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Slave;
    SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft;
    SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
    SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_1Edge;

    SPI_Init(SPI1, &SPI_InitTypeDefStruct);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE , ENABLE);

    GPIO_InitTypeDef GPIO_InitTypeDefStruct;
    /* configure pins used by SPI1
        * PA5 = SCK
        * PA6 = MISO
        * PA7 = MOSI
        * Also you have to configure GPIO. SCK and MOSI should be AF/PP outputs
        * on master and AF inputs on slave; MISO should be AF input on master and
        * AF/PP output on slave; NSS should be AF input on slave.
        */
    GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
    GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);

    /* Configure the chip select pin in this case we will use PE7 */
    GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitTypeDefStruct.GPIO_Mode =  GPIO_Mode_IN;
    GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_Init(GPIOE, &GPIO_InitTypeDefStruct);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

    GPIO_SetBits(GPIOE, GPIO_Pin_3);

    NVIC_EnableIRQ (SPI1_IRQn);                                // enable interrupt on SPI1
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
    SPI_Cmd(SPI1, ENABLE);
}
void SPI1_IRQHandler(void)
{
    static unsigned short int count = 0, i = 0 ;
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) == SET)
    {
        if(ubTxIndex < 10)
        {
            SPI1->DR  = ubTxIndex;
            ubTxIndex++ ;
        }
        else
        {
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
        }
    }
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
    {
        if(ubRxIndex<10)
        {
            aRxBuffer[ubRxIndex++] = SPI1->DR ;
            //Slave_rev_buff[i] = SPI1->DR ;
            //i++ ;
            printf("Data received : %d\n",aRxBuffer[ubRxIndex]);
        }
        else
        {
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
        }
    }
}
 It would be kind of you if you could throw some light on issues which could clear my confusion. Thank you so much.

Outcomes