【问题标题】:Stm32f407IG SPI communicationstm32f407IG SPI通信
【发布时间】:2015-09-05 11:42:29
【问题描述】:
#include <stm32f4xx.h>
#include "stm32f4xx_spi.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "config.h"

void init_GPIO()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;  
GPIO_Init(GPIOI , &GPIO_InitStructure);
}


void SPI1_Configuration_master(void)
{
SPI_InitTypeDef SPI_InitStruct;  
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(Open_SPI1_SCK_GPIO_CLK | Open_SPI1_MISO_GPIO_CLK | Open_SPI1_MOSI_GPIO_CLK |Open_SPI1_NSS_GPIO_CLK ,ENABLE);
RCC_APB2PeriphClockCmd(Open_RCC_APB2Periph_SPI1,ENABLE);

GPIO_PinAFConfig(Open_SPI1_SCK_GPIO_PORT, Open_SPI1_SCK_SOURCE,  Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_MISO_GPIO_PORT, Open_SPI1_MISO_SOURCE, Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_MOSI_GPIO_PORT, Open_SPI1_MOSI_SOURCE, Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_NSS_GPIO_PORT, Open_SPI1_NSS_SOURCE, Open_SPI1_NSS_AF);

GPIO_InitStructure.GPIO_Pin = Open_SPI1_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;  
GPIO_Init(Open_SPI1_SCK_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI1_MISO_PIN;
GPIO_Init(Open_SPI1_MISO_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI1_MOSI_PIN;
GPIO_Init(Open_SPI1_MOSI_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI1_NSS_PIN;
GPIO_Init(Open_SPI1_NSS_GPIO_PORT, &GPIO_InitStructure);


SPI_I2S_DeInit(Open_SPI1);
SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; 
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(Open_SPI1, &SPI_InitStruct);

SPI_Cmd(Open_SPI1, ENABLE);

}
void SPI_Configuration2_slave(void)
{
SPI_InitTypeDef SPI_InitStruct;  
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(Open_SPI2_SCK_GPIO_CLK | Open_SPI2_MISO_GPIO_CLK | Open_SPI2_MOSI_GPIO_CLK| Open_SPI2_NSS_GPIO_CLK,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);

GPIO_PinAFConfig(Open_SPI2_SCK_GPIO_PORT, Open_SPI2_SCK_SOURCE,  Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MISO_GPIO_PORT, Open_SPI2_MISO_SOURCE, Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MOSI_GPIO_PORT, Open_SPI2_MOSI_SOURCE, Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MOSI_GPIO_PORT, Open_SPI2_NSS_SOURCE, Open_SPI2_MOSI_AF);

GPIO_InitStructure.GPIO_Pin = Open_SPI2_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;  
GPIO_Init(Open_SPI2_SCK_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI2_MISO_PIN;
GPIO_Init(Open_SPI2_MISO_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI2_MOSI_PIN;
GPIO_Init(Open_SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Open_SPI2_NSS_PIN;
GPIO_Init(Open_SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);

SPI_I2S_DeInit(Open_SPI2);
SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; 
SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ;
//SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(Open_SPI2, &SPI_InitStruct);

SPI_Cmd(Open_SPI2, ENABLE);

}

u16 SPI2_Send_byte(u16 data)
{
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI2,data);

while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI2);
}

u16 SPI2_Receive_byte(void)
{/*
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI2,0x00);
*/
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI2);
}

u16 SPI_Send_byte(u16 data)
{
GPIO_ResetBits(GPIOI,GPIO_Pin_10);
while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI1,data);

while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_RXNE)==RESET);
GPIO_SetBits(GPIOI,GPIO_Pin_10);
return SPI_I2S_ReceiveData(Open_SPI1);
}

u16 SPI_Receive_byte(u16 data)
{
/*while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI1,data);
*/
while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI1);
}

int main()
{
char a;
init_GPIO();
SPI_Configuration2_slave();
SPI1_Configuration_master();
GPIO_SetBits(GPIOI,GPIO_Pin_10);
while(1)
{
    a =SPI_Send_byte((u16)'a');
    a = SPI2_Receive_byte();
}
return 0;
}

我正在尝试在 STM32F407ig 上实现 Spi 我目前正在尝试在同一块板上实现两个 Spi1 和 SPI2 之间的通信。 我尝试了类似的代码来进行板之间的通信。 当我环回主控的 mosi 和 miso 时,我得到了传输的数据。 但从机没有收到任何东西或收到零。 建立的联系是正确的。 像Open_SPI1这样使用的宏也是对的。

我想知道我的SPI主从配置是否正确。

谁能详细说明 NSS 软件的具体工作原理。

【问题讨论】:

    标签: spi master-slave stm32f4discovery


    【解决方案1】:

    我在 STM32F2 系列上遇到了 SPI 问题。我不得不手动切换 NSS 线,之后一切正常。不确定 F4 是否有同样的问题(甚至可能是设计使然)。这是我的代码:

    /******************************************************************************/
    void SPI_GPIO_init( void )
    {
       GPIO_InitTypeDef GPIO_InitStructure;
    
       /* Configure SPI pins SCK and MOSI to be hardware controlled */
       GPIO_InitStructure.GPIO_Pin     = SPI_PIN_SCK | SPI_PIN_MOSI;
       GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF_PP;
       GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
    
       /* Configure SPI pin MISO to be an input pin since we are master */
       GPIO_InitStructure.GPIO_Pin     = SPI_PIN_MISO;
       GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN_FLOATING;
       GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
    
       /* Configure SPI pin NSS to be a regular GPIO output.  This is due to STM32
        * goofy handling of SPI: NSS stays low for the entire duration of SPI being
        * enabled instead of being released after outgoing data is completed.  This
        * is basically a HW bug but it definitely mentiones this in the Ref Manual.
        *
        * From the reference manual RM0090:
        * - NSS output enabled (SSM = 0, SSOE = 1)
        * This configuration is used only when the device operates in master mode.
        * The NSS signal is driven low when the master starts the communication and
        * is kept low until the SPI is disabled.
        *
        * Instead, we are going to drive this pin manually as CLRC663 chip expects
        * */
       GPIO_InitStructure.GPIO_Pin     = SPI_PIN_NSS;
       GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;
       GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
    
       SPI_NSS_high();
       DelayMS(1);
    
    }
    
    /******************************************************************************/
    void SPI_NSS_high( void )
    {
       GPIO_WriteBit( SPI_GPIO_PORT, SPI_PIN_NSS, Bit_SET);
    }
    
    /******************************************************************************/
    void SPI_NSS_low( void )
    {
       GPIO_WriteBit( SPI_GPIO_PORT, SPI_PIN_NSS, Bit_RESET);
    }
    
    /******************************************************************************/
    void SPI_init( void )
    {
       SPI_I2S_DeInit( SPI1 );
    
       SPI_NSS_high();
    
       SPI_InitTypeDef  SPI_InitStructure;
    
       /* SPI1 configuration */
       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_1Edge;
       SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;
       SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
       SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;
       SPI_InitStructure.SPI_CRCPolynomial     = 0;
       SPI_Init( SPI1, &SPI_InitStructure );
    
       SPI_Cmd( SPI1, ENABLE );
    
       /* Not using interrupts for SPI communication so don't enable the NVIC and
        * the ISR for it.*/
    }
    
    /******************************************************************************/
    Error SPI_send( uint8_t *snd_buf, uint8_t snd_buf_len )
    {
       uint8_t snd_indx        = 0;
       uint8_t spi_retry       = 0;
    
       SPI_NSS_low(); /* Assert the NSS pin low to become SPI bus master */
    
       for ( snd_indx = 0; snd_indx < snd_buf_len; snd_indx++ )
       {
          /* When SPI Tx buffer is empty, send data.  Make sure we don't get
           * stuck in an inf loop while waiting for HW */
          spi_retry = 0;
          while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) )
          {
             if ( 0xFF == spi_retry++ )
             {
                err_printf("Reached SPI hardware retries trying to send data over SPI bus\n");
                return ( ERR_HW_SPI_TIMEOUT );
             }
          }
          SPI_I2S_SendData( SPI1, snd_buf[ snd_indx ] );
          //        debug_printf("Sent %02x\n", snd_buf[ snd_indx ]);
    
          /* Get the dummy byte coming back when SPI Rx buffer is empty. Make sure
           * we don't get stuck in an inf loop while waiting for HW */
          spi_retry = 0;
          while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) )
          {
             if ( 0xFF == spi_retry++ )
             {
                err_printf("Reached SPI hardware retries trying to receive data over SPI bus\n");
                return ( ERR_HW_SPI_TIMEOUT );
             }
          }
          SPI_I2S_ReceiveData( SPI1 ); /* Dummy byte so no need to store it */
       }
    
       SPI_NSS_high(); /* Assert the NSS pin high to release SPI bus master */
    
       return ( ERR_NONE );
    }
    
    /******************************************************************************/
    Error SPI_transceive(
                            uint8_t *snd_buf,
                            uint8_t snd_buf_len,
                            uint8_t *rcv_buf,
                            uint8_t rcv_buf_len
                        )
    {
       uint8_t snd_indx        = 0;
       uint8_t rcv_indx        = 0;
       uint16_t spi_retry      = 0;
    
       SPI_NSS_low(); /* Assert the NSS pin low to become SPI bus master */
    
       if ( snd_buf_len != rcv_buf_len )
       {
          err_printf("SPI expects to receive same amount of data that it is sending\n");
          return ( ERR_HW_SPI_LENGTH_MISMATCH );
       }
    
       for ( snd_indx = 0; snd_indx < snd_buf_len; snd_indx++, rcv_indx++ )
       {
          /* When SPI Tx buffer is empty, send data.  Make sure we don't get
           * stuck in an inf loop while waiting for HW */
          spi_retry = 0;
          while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) )
          {
             if ( 0xFF == spi_retry++ )
             {
                err_printf("Reached SPI hardware retries trying to send data over SPI bus\n");
                return ( ERR_HW_SPI_TIMEOUT );
             }
          }
          SPI_I2S_SendData( SPI1, snd_buf[ snd_indx ] );
    
          /* Now receive the reply when the Rx buffer is empty. Make sure we don't
           * get stuck in an inf loop while waiting for HW */
          spi_retry = 0;
          while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) )
          {
             if ( 0xFF == spi_retry++ )
             {
                err_printf("Reached SPI hardware retries trying to receive data over SPI bus\n");
                return ( ERR_HW_SPI_TIMEOUT );
             }
          }
          uint8_t data = SPI_I2S_ReceiveData( SPI1 );
          rcv_buf[ rcv_indx ] = data;
          //        debug_printf("Got %02x\n", data );
       }
    
       SPI_NSS_high(); /* Assert the NSS pin high to release SPI bus master */
    
       return ( ERR_NONE );
    }
    

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 1970-01-01
      • 2021-08-27
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2013-09-14
      • 2021-11-22
      相关资源
      最近更新 更多