OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4079|回复: 4

急急急,使用mini开发板做SPI+DMA读写SD卡却一直卡死,实在不知道问题出在哪里,现把读写扇区程序附上,麻烦各位大牛们不吝赐...

[复制链接]

3

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2014-7-27
在线时间
31 小时
发表于 2016-3-29 20:33:57 | 显示全部楼层 |阅读模式
void DMA1_Init(void)    //DMA初始化程序
{
        DMA_InitTypeDef DMA_InitStructure;   
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);        //使能DMA传输
       
        DMA_DeInit(DMA1_Channel2);   //将DMA的通道2寄存器重设为缺省值
        DMA_DeInit(DMA1_Channel3);   //将DMA的通道3寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&SPI1->DR;//DMA外设基地址
        //DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)pbuf;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//数据传输方向,从内存读取发送到外设
        DMA_InitStructure.DMA_BufferSize=512;
        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_Channel3, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道SPI1_Tx_DMA_Channel所标识的寄存器
       
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;  //DMA外设基地址
//        DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存
        DMA_InitStructure.DMA_BufferSize = 512;  //DMA通道的DMA缓存的大小,一个SD卡扇区大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常模式下
        DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //DMA通道x拥有较高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA1_Channel2, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道SPI1_Rx_DMA_Channel所标识的寄存器
       
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE); //使能SPI1接收的DMA传输
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE); //使能SPI1发送的DMA传输
}

//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;       
u8 SD_RecvData(u8*buf,u16 len)
{                                    
        u8 dummyclock=0xff;               //用于SPI接收的时钟
        if(SD_GetResponse(0xFE))return 1; //等待SD卡发回数据起始令牌0xFE
        DMA1_Channel2->CNDTR=512;         //接收的数据个数
        DMA1_Channel2->CMAR=(uint32_t)buf;//接收数据缓冲区地址       
        DMA1_Channel3->CNDTR=512;         //发送的数据个数
        DMA1_Channel3->CMAR=(uint32_t)&dummyclock;//此处的目的是给SPI的DMA接收添加时钟
        DMA1_Channel3->CCR&=~DMA_MemoryInc_Enable;//发送内存区地址不增加,一直发送0xff接收时钟用
       
        DMA_Cmd(DMA1_Channel2,ENABLE);    //使能DMA1通道2指令
        DMA_Cmd(DMA1_Channel3,ENABLE);    //使能DMA1通道3指令
        while(!DMA_GetFlagStatus(DMA1_FLAG_TC2));//等待DMA传输完成                   ???  读扇区一直卡死在这
        DMA_ClearFlag(DMA1_FLAG_TC2);     //清除通道2传输完成标志位
        DMA_ClearFlag(DMA1_FLAG_TC3);     //清除通道3传输完成标志位
        DMA_Cmd(DMA1_Channel2,DISABLE);   //关闭DMA1通道2指令
        DMA_Cmd(DMA1_Channel3,DISABLE);   //关闭DMA1通道3指令
       
        DMA1_Channel3->CCR|=DMA_MemoryInc_Enable;//恢复发送内存区地址增加
//        while(len--)//开始接收数据
//    {
//        *buf=SPI1_ReadWriteByte(0xFF);
//        buf++;
//    }
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);                                                                                                                      
    return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;       
u8 SD_SendBlock(u8*buf,u8 cmd)
{       
        u16 t;                            
        if(SD_WaitReady())return 1;//等待准备失效
        SD_SPI_ReadWriteByte(cmd);
        if(cmd!=0XFD)//不是结束指令
        {
                //此处采用DMA方式传输
                DMA1_Channel3->CNDTR=512;//在DMA传输计数器中写入要传输的数据个数
                DMA1_Channel3->CMAR=(u32)buf;              //发送数据缓冲区地址
                DMA_Cmd(DMA1_Channel3,ENABLE); //使能DMA1通道3指令
                while(!DMA_GetFlagStatus(DMA1_FLAG_TC3));//等待DMA传输完成                     ???  写扇区一直卡死在这
                DMA_ClearFlag(DMA1_FLAG_TC3);  //清除传输完成标志位
                DMA_Cmd(DMA1_Channel3,DISABLE);//关闭DMA1通道3指令
//                for(t=0;t<512;t++)SPI1_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
               SD_SPI_ReadWriteByte(0xFF);//忽略crc
               SD_SPI_ReadWriteByte(0xFF);
                t=SD_SPI_ReadWriteByte(0xFF);//接收响应
                if((t&0x1F)!=0x05)return 2;//响应错误                                                                                                                      
        }                                                                                                                                                                       
    return 0;//写入成功
}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2014-7-27
在线时间
31 小时
 楼主| 发表于 2016-3-30 15:36:10 | 显示全部楼层
本实验是使用STM32 MINI开发板,用以上SPI的DMA语句读写W25Q64是完全没问题的,可用到SD卡上就一直卡在在等待DMA发送完成那个语句那里,读DMA传输计数器的值一直是512,说明DMA根本没有启动,实在找不出原因出在哪里,求助一下各位了,好心帮帮忙
回复 支持 反对

使用道具 举报

3

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2014-7-27
在线时间
31 小时
 楼主| 发表于 2016-4-3 18:15:22 | 显示全部楼层
附上我的测试程序,麻烦各位大哥帮忙看看,弄了好多天都没找到原因,头都大了,用在flash上没有问题,用在SD卡上就一直卡死,DMA都启动不了
回复 支持 反对

使用道具 举报

3

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2014-7-27
在线时间
31 小时
 楼主| 发表于 2016-4-3 18:22:17 | 显示全部楼层
求助,请大家帮忙看看

ALIENTEK MINISTM32 SD卡SPI DMA实验.zip

3.15 MB, 下载次数: 155

测试程序

回复 支持 反对

使用道具 举报

5

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2015-9-11
在线时间
46 小时
发表于 2016-4-9 10:10:59 | 显示全部楼层
正好要试试。
迫于生计
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 02:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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