STM32F051 SPI slave mode DMA接收

用STM32F051的SPI从模式接收主机发送的实时数据。

Eclips 环境,gcc编译器,相关源码如下:

#ifdef DEBUG_SPI_EN
#define DEBUG_SPI(...)      printf(__VA_ARGS__)
#else
#define DEBUG_SPI(...)
#endif

void SPI1_Config(void)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    SPI_InitTypeDef     SPI_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    // SPI1 port
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_5;
    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_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);

    // SPI1 config
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    SPI_I2S_DeInit(SPI1);
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;
    SPI_InitStructure.SPI_Mode      = SPI_Mode_Slave;  
    SPI_InitStructure.SPI_DataSize  = SPI_DataSize_8b; 
    SPI_InitStructure.SPI_CPOL      = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA      = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS       = SPI_NSS_Soft;    
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;  // SCLK = 12.0MHz
    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial     = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    SPI_Cmd(SPI1, DISABLE);
}

void SPI1_DMA_NVIC_Config(void)
{
    NVIC_InitTypeDef    NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel         = DMA1_Channel2_3_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2; 
    NVIC_InitStructure.NVIC_IRQChannelCmd      = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
}

void SPI1_DMA_Config(uint8_t *pbuff, uint16_t nbytes)
{
    DMA_InitTypeDef     DMA_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel2);
    DMA_StructInit(&DMA_InitStructure);
    DMA_Cmd(DMA1_Channel2, DISABLE);

    DMA_InitStructure.DMA_PeripheralBaseAddr= SPI1_BASE + 0x0C;
    DMA_InitStructure.DMA_MemoryBaseAddr    = (uint32_t)pbuff;
    DMA_InitStructure.DMA_BufferSize        = nbytes;
    DMA_InitStructure.DMA_DIR               = DMA_DIR_PeripheralSRC;        // from SPI
    DMA_InitStructure.DMA_PeripheralInc     = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc         = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize= DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize    = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode              = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority          = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M               = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);

    SPI1_DMA_NVIC_Config();
}

void SPI1_Read_Starting(uint8_t *pbuff, uint16_t nbytes)
{
    DMA_Cmd(DMA1_Channel2, DISABLE);
    DMA1_Channel2->CNDTR = nbytes;
    DMA1_Channel2->CPAR  = SPI1_BASE + 0x0C;
    DMA1_Channel2->CMAR  = (uint32_t)pbuff;
    DMA_Cmd(DMA1_Channel2, ENABLE);

    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
    SPI_Cmd(SPI1, ENABLE);
}

void SPI1_Read_Stop(void)
{
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, DISABLE);
    SPI_Cmd(SPI1, DISABLE);
}

/*
 *  SPI1_RX & SPI1_TX DMA Interrupt
 */
void DMA1_Channel2_3_IRQHandler(void)
{
    if(DMA_GetFlagStatus(DMA1_FLAG_TC2) != RESET)
    {
        DEBUG_SPI(">>");
        ; // 接收数据处理,略去...
        ;

        DMA_ClearITPendingBit(DMA1_FLAG_TC2);
    }
/*
    if(DMA_GetFlagStatus(DMA1_FLAG_TC3) != RESET)
    {
        DMA_ClearITPendingBit(DMA1_FLAG_TC3);
    }*/
}

/*
 *  片选中断设置
 */
void SPI1_NSS_Config(void)
{
    EXTI_InitTypeDef   EXTI_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource15);

    EXTI_InitStructure.EXTI_Line    = EXTI_Line15;
    EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  // _Rising  _Falling  _Rising_Falling
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel         = EXTI4_15_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0; // Low Medium Hight VeryHigh: 0 - 3
    NVIC_InitStructure.NVIC_IRQChannelCmd      = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    EXTI_ClearITPendingBit(EXTI_Line15);
}

void EXTI4_15_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line15) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line15);

        GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15);
        if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == RESET)
        {
            SPI1_Read_Starting(&dmaBuffPoll[0], FRAME_BYTES);   // startup SPI1 Data receive-only
        }
    }
}
 

起初,SPI设成“1-line bidirectional data mode selected”模式,接收到的数据全为“0”,找了很久的原因,无果;

改为“Receive-only mode”后,一切正常!


你可能感兴趣的:(STM32F051 SPI slave mode DMA接收)