硬汉嵌入式论坛

 找回密码
 立即注册
查看: 7591|回复: 5
收起左侧

[有问必答] SPI  DMA模式

[复制链接]

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
发表于 2015-1-21 11:20:35 | 显示全部楼层 |阅读模式
想在MP3播放例程中将SPI改为用DMA来控制发送,但是DMA配置一直不成功,麻烦版主帮忙看下:
void bsp_CfgSPIForVS1053B(void)
{
    SPI_InitTypeDef  SPI_InitStructure;

    /* 打开SPI时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    
        /* 使能  DMA clock */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

    /* SPI1 配置 */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    /* 选择2线全双工模式 */
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        /* CPU的SPI作为主设备 */
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;    /* 8个数据 */
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;            /* CLK引脚空闲状态电平 = 0 */
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        /* 数据采样在第1个边沿(上升沿) */
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;              /* 软件控制片选 */

    /*
        由于SPI1的时钟源是84M, SPI3的时钟源是42M。为了获得更快的速度,软件上选择SPI1。
        pdf page=23 vs1053B SPI输入时钟 4个CLKI cycles; CLKI = 12.288M
        因此最大SPI时钟 = 12.288 / 4 = 3.072MHz
        需要 32分频
    */
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    /* 最高位先传输 */
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1,&SPI_InitStructure);

    SPI_Cmd(SPI1, DISABLE);            /* 先禁止SPI  */

    SPI_Cmd(SPI1, ENABLE);            /* 使能SPI  */
    
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
}

void SPI1_DMA_TxConfig(uint32_t *BufferDST, uint32_t BufferSize)
{
    DMA_InitTypeDef DMA_InitStructure;
    
    //DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF);
//    DMA_ClearFlag(SPI_SDIO_DMA_STREAM, SPI_SDIO_DMA_FLAG_FEIF | SPI_SDIO_DMA_FLAG_DMEIF
//                                     | SPI_SDIO_DMA_FLAG_TEIF | SPI_SDIO_DMA_FLAG_HTIF | SPI_SDIO_DMA_FLAG_TCIF);
    
    /* DMA2 Stream3  or Stream6 disable */
    DMA_Cmd(SPI_SDIO_DMA_STREAM, DISABLE);
    
    while (DMA_GetCmdStatus(SPI_SDIO_DMA_STREAM) != DISABLE)
    {
    }
    DMA_InitStructure.DMA_BufferSize = BufferSize;/* 配置DMA大小 */
     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;                  /* 在这个程序里面使能或者禁止都可以的 */
     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;          /* 设置阀值 */
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;           /* 设置内存为单字节突发模式 */
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        /* 设置内存数据的位宽是字节 */
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                /* 使能地址自增 */
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                          /* 设置DMA是正常模式 */
    DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI1->DR)) ; /* 设置外设地址 */
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    /* 设置外设为单字节突发模式 */
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;; /* 设置外设数据的位宽是字节 */
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/* 禁止外设地址自增 */
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;             /* 设置优先级 */
    
    /* 配置 TX DMA */
    DMA_InitStructure.DMA_Channel = SPI_SDIO_DMA_CHANNEL ;      /* 配置发送通道 */
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ;     /* 设置从内存到外设 */
    DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)BufferDST ; /* 设置内存地址 */
    DMA_Init(SPI_SDIO_DMA_STREAM,&DMA_InitStructure);
    
    DMA_FlowControllerConfig(SPI_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral);

    /* DMA2 Stream3 enable */
    DMA_Cmd(SPI_SDIO_DMA_STREAM, ENABLE);
    
    while (DMA_GetCmdStatus(SPI_SDIO_DMA_STREAM) != ENABLE);
}
操作控制部分:
static uint8_t Mp3Pro(void)
{
    uint32_t bw,i;
    char buf[32];

    /* 如果VS1003空闲,则写入新的数据 */
    if (vs1053_ReqNewData())
    {
        f_read(&g_Mp3File, &buf, 32, &bw);
        if (bw <= 0)
        {
            return 1;
        }

        /* 计算进度 */
        g_tMP3.uiProgress += bw;

        vs1053_PreWriteData();    /* 写数据准备,设置好片选 */
//        for (i = 0; i < bw; i++)
//        {
//            vs1053_WriteData(buf);
//        }

        SPI1_DMA_TxConfig((uint32_t *)buf, 32);
        GPIOA->BSRRH = GPIO_Pin_5;
        while (DMA_GetFlagStatus(SPI_SDIO_DMA_STREAM,SPI_SDIO_DMA_FLAG_TCIF)==RESET);

        /* 清除DMA传输完成标志 */
        DMA_ClearFlag(SPI_SDIO_DMA_STREAM,SPI_SDIO_DMA_FLAG_TCIF);
        GPIOA->BSRRL = GPIO_Pin_5;
    }
    return 0;
}
V5-121_VS1053B MP3硬件解码器例程(修改).zip (14.33 MB, 下载次数: 152) 上传附件,版主有空帮忙看下,非常感谢
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
 楼主| 发表于 2015-1-21 11:21:20 | 显示全部楼层
一直死在  while (DMA_GetCmdStatus(SPI_SDIO_DMA_STREAM) != ENABLE);中
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
 楼主| 发表于 2015-1-21 15:22:10 | 显示全部楼层
while (DMA_GetCmdStatus(SPI_SDIO_DMA_STREAM) != ENABLE);  这句话屏蔽掉后,示波器能测到SPI在发送数据,但是MP3模块没反应
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107137
QQ
发表于 2015-1-21 19:56:26 | 显示全部楼层
这个等我下次研究了,跟楼主一起探讨。
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
 楼主| 发表于 2015-1-22 08:17:24 | 显示全部楼层
想节约发送32字节的时间干其他事情,发现SPI有时候会工作,但是发的值不对,估计还是哪里细节问题,一直找不出来
回复

使用道具 举报

100

主题

275

回帖

575

积分

金牌会员

积分
575
发表于 2016-2-18 16:55:13 | 显示全部楼层
我的SPI DMA 只能进入一次中断,接下去就一直进不了了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-20 03:50 , Processed in 0.176114 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表