单SPI轮询读取W25Qxx可以使用,但SPI+DMA中断读取不知道为什么不行,麻烦帮忙看下

如题,一开始一直进不去中断,考虑可能是配置问题,但是反复对照过类似代码,应该没有缺什么了。

刚刚把DMA_ClearFlag清除标志位的2句注释了,还进了中断,不过只有上电首次            ->中断配置应该是通的。

但整个代码呈现的效果就感觉DMA没有运行,不产生中断。麻烦帮忙看下是为什么

芯片是:CH32V208RBT6

image.png

关键代码如下:

#define DataBuf_Len 128

uint8_t RxData1[DataBuf_Len],RxData2[DataBuf_Len];


//SPI2初始化

void SPI_2_DMA_Initial(void)

{

    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);


    GPIO_InitStructure.GPIO_Pin = SPI2_CSN;        //此处引脚、端口都是正确的,因为轮询读取都是可以的

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SPI2_SS_PORT, &GPIO_InitStructure);

    GPIO_SetBits(SPI2_SS_PORT, SPI2_CSN);


    GPIO_InitStructure.GPIO_Pin = SPI2_SCK;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SPI2_DT_PORT, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = SPI2_MISO;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(SPI2_DT_PORT, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = SPI2_MOSI;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SPI2_DT_PORT, &GPIO_InitStructure);

    //------------------------------------------------------

    DMA_InitTypeDef DMA_InitStructure = {0};

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel4);

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DATAR));

    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxData1;

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

    DMA_InitStructure.DMA_BufferSize = 1;        //后续使用时,会在函数内更改,此处就随便写了个

    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_VeryHigh;

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel4, &DMA_InitStructure);

    DMA_Cmd(DMA1_Channel4, DISABLE);

    DMA_ClearFlag(DMA1_FLAG_GL4|DMA1_FLAG_TC4|DMA1_FLAG_HT4|DMA1_FLAG_TE4);

    DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);


    //------------------------------------------------------

    SPI_InitTypeDef  SPI_InitStructure = {0};

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);

    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_4;

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

    SPI_InitStructure.SPI_CRCPolynomial = 0;        //??

    SPI_Init(SPI2, &SPI_InitStructure);


    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);

    SPI_Cmd(SPI2, ENABLE);

    //------------------------------------------------------

//    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    //在其它地方有了,就注释了

    NVIC_InitTypeDef NVIC_InitStructure = {0};

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    NVIC_EnableIRQ(DMA1_Channel4_IRQn);

    DMA_Cmd(DMA1_Channel4, DISABLE);

}


//收发单字节数据

uint8_t SPI_ReadWrite_1_Byte(uint8_t byte)

{

    u8 i = 0;

     SPI_I2S_SendData(SPI2, byte);

     i = 0;

     while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)

     {

         i++;

         if(i > 200)

             return 0;

     }

     return SPI_I2S_ReceiveData(SPI2);

}


//用于读取W25Q64中地址为ReadAddr的bufsize长度数据,存储在temp_buf中

void SPI_FLASH_Get256(uint32_t ReadAddr, uint8_t *temp_buf, uint16_t bufsize)

{

    SPI_CS_SET_LOW();// 选择 FLASH: CS 低电平


    SPI_ReadWrite_1_Byte(CMD_READ_BUFF);


    SPI_ReadWrite_1_Byte((ReadAddr >> 16) &0xFF);

    SPI_ReadWrite_1_Byte((ReadAddr >> 8) &0xFF);

    SPI_ReadWrite_1_Byte(ReadAddr&0xFF);


    SPI_I2S_ReceiveData(SPI2);

    DMA_Cmd(DMA1_Channel4,DISABLE);

    DMA_ClearFlag(DMA1_FLAG_GL3|DMA1_FLAG_TC3|DMA1_FLAG_HT3|DMA1_FLAG_TE2);


    DMA1_Channel4->CNTR = bufsize;

    DMA1_Channel4->PADDR = (uint32_t)(&(SPI2->DATAR));

    DMA1_Channel4->MADDR = (uint32_t)temp_buf;

    DMA_Cmd(DMA1_Channel4,ENABLE);

}


void DMA1_Channel4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

void DMA1_Channel4_IRQHandler(void)

{

    if(DMA_GetITStatus(DMA1_IT_TC4) !=RESET)

    {

        SPI_DMA_Read_Flag = 0x00;

        DMA_Cmd(DMA1_Channel4,DISABLE);

        SPI_CS_SET_HIGH();

        DMA_ClearITPendingBit(DMA1_IT_GL4|DMA1_IT_TC4|DMA1_IT_HT4|DMA1_IT_TE4);

    }

}


补充:主频使用120MHz,也考虑过可能是SPI的速率过快,SPI_BaudRatePrescaler_4 将它分频更多8、32、64、125、256也都试过了


您好,中断中关闭DMA之后还有调用么,若方便,可将代码发过来(lzs@wch.cn)具体看一下,后续若有问题,也可以通过邮箱沟通


有的,每次使用SPI_FLASH_Get256 这个函数的时候都会进行一次调用。代码,我稍后整理一下,发你邮箱。


只有登录才能回复,可以选择微信账号登录