OpenEdv-开源电子网

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

求一个STM32 带FATFS文件系统 SPI+DMA方式读取SD卡的 程序 感谢了

[复制链接]

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
发表于 2015-1-15 11:42:24 | 显示全部楼层 |阅读模式
5金钱
  求一个STM32 带FATFS文件系统 SPI+DMA方式读取SD卡的 程序  感谢了  已经实现STM32 SPI 方式读取带文件系统的SD卡 

83390052SD-card-STM32-FATFS.rar

452.5 KB, 下载次数: 2760

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

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-15 12:44:06 | 显示全部楼层
楼主实现SPI的DMA操作就可以实现了
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-15 15:51:27 | 显示全部楼层
回复【2楼】八度空间:
---------------------------------
  /* DMA configuration -------------------------------------------------------*/
  /* Deinitialize DMA Streams */
  DMA_InitTypeDef DMA_InitStructure;      
  DMA_DeInit(SPIx_TX_DMA_STREAM);
  DMA_DeInit(SPIx_RX_DMA_STREAM);
  
    /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(SPIx_DMA_CLK, ENABLE);
  
       /* Configure DMA Initialization Structure */
  DMA_InitStructure.DMA_BufferSize = BUFFERSIZE ;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
  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_Circular;
  DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI2->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;
  /* Configure TX DMA */
  DMA_InitStructure.DMA_Channel = SPIx_TX_DMA_CHANNEL ;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)StoreData ;
  DMA_Init(SPIx_TX_DMA_STREAM, &DMA_InitStructure);
    /* Configure RX DMA */
//  DMA_InitStructure.DMA_Channel = SPIx_RX_DMA_CHANNEL ;
//  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;
//  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)aRxBuffer ; 
//  DMA_Init(SPIx_RX_DMA_STREAM, &DMA_InitStructure);
  
    /* Enable DMA SPI TX Stream */
  DMA_Cmd(SPIx_TX_DMA_STREAM,ENABLE);

  /* Enable DMA SPI RX Stream */
  DMA_Cmd(SPIx_RX_DMA_STREAM,ENABLE);

  /* Enable SPI DMA TX Requsts */
  SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

  /* Enable SPI DMA RX Requsts */
  SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
  
    /* Waiting the end of Data transfer */
  //while (DMA_GetFlagStatus(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF)==RESET);
 // while (DMA_GetFlagStatus(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF)==RESET);
  
  /* Clear DMA Transfer Complete Flags */
  DMA_ClearFlag(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF);
  //DMA_ClearFlag(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF);  
 
  SPI_Cmd(SPI2, ENABLE);

  SPI2_ReadWriteByte(0xff);  
 

}  

请问老师 那实现SPI 的DMA  应该用DMA模式 用DMA_Mode_Circular 和DMA_Mode_NORMAL哪种 比较好呢
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-15 21:01:46 | 显示全部楼层
回复【2楼】八度空间:
---------------------------------
我就是这么想的  但是实现不了呢  求老师帮忙下
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-16 08:06:13 | 显示全部楼层
回复【3楼】panjiadi586:
---------------------------------
DMA_Mode_Circular 和DMA_Mode_NORMAL这两种模式,看你的数据需求了,推荐你使用DMA_Mode_NORMAL模式

你的是F4的片子啊???
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-16 10:38:22 | 显示全部楼层
回复【5楼】八度空间:
---------------------------------
嗯  是的  是F4的片子   NORMAL  还要每次重新开启DMA 关闭DMA 吧 

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

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
        
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //引脚初始化
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;   
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
        
         GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);  //打开引脚的复用功能
         GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
         GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);  
  //GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  

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_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure); 
        
  /* DMA configuration -------------------------------------------------------*/
  /* Deinitialize DMA Streams */
  DMA_InitTypeDef DMA_InitStructure;      
  DMA_DeInit(SPIx_TX_DMA_STREAM);
  DMA_DeInit(SPIx_RX_DMA_STREAM);
  
    /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(SPIx_DMA_CLK, ENABLE);
  
       /* Configure DMA Initialization Structure */
  DMA_InitStructure.DMA_BufferSize = BUFFERSIZE ;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
  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_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI2->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;
  /* Configure TX DMA */
  DMA_InitStructure.DMA_Channel = SPIx_TX_DMA_CHANNEL ;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_Buffer_Tx;
  DMA_Init(SPIx_TX_DMA_STREAM, &DMA_InitStructure);
    /* Configure RX DMA */
  DMA_InitStructure.DMA_Channel = SPIx_RX_DMA_CHANNEL ;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_Buffer_Rx; 
  DMA_Init(SPIx_RX_DMA_STREAM, &DMA_InitStructure);
  
//    /* Enable DMA SPI TX Stream */
//  DMA_Cmd(SPIx_TX_DMA_STREAM,ENABLE);
//
//  /* Enable DMA SPI RX Stream */
//  DMA_Cmd(SPIx_RX_DMA_STREAM,ENABLE);

  /* Enable SPI DMA TX Requsts */
  SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

  /* Enable SPI DMA RX Requsts */
 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
  
    /* Waiting the end of Data transfer */
  //while (DMA_GetFlagStatus(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF)==RESET);
 // while (DMA_GetFlagStatus(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF)==RESET);
  
  /* Clear DMA Transfer Complete Flags */
  //DMA_ClearFlag(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF);
  //DMA_ClearFlag(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF);  
 
  SPI_Cmd(SPI2, ENABLE);

  SPI2_ReadWriteByte(0xff);  
 

}   

  
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
   assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI2->CR1&=0XFFC7;
SPI2->CR1|=SPI_BaudRatePrescaler;
SPI_Cmd(SPI2,ENABLE); 



#define nodma
u8 SPI2_ReadWriteByte(u8 TxData)
{  u16 retry=0;
#if defined nodma
         
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) 
{
retry++;
if(retry>263)return 0;
}   
SPI_I2S_SendData(SPI2, TxData); 
             retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
retry++;
if(retry>263)return 0;
}        
return SPI_I2S_ReceiveData(SPI2);
#elif defined dma
       u16 i = 0;
     u8 temp=0,temp1=0;
 
           SPI_Buffer_Tx=TxData;
   
    /* Enable DMA SPI TX Stream */
  DMA_Cmd(SPIx_TX_DMA_STREAM,ENABLE);

  /* Enable DMA SPI RX Stream */
  DMA_Cmd(SPIx_RX_DMA_STREAM,ENABLE);
      
     while(1)
      {
        temp=DMA_GetFlagStatus(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF);
        temp1= DMA_GetFlagStatus(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF);
        if(temp==SET||temp1==SET)
          break;
        
      } 
   while (DMA_GetFlagStatus(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF)==RESET);
     
      return SPI_Buffer_Rx[0];
  DMA_ClearFlag(SPIx_TX_DMA_STREAM,SPIx_TX_DMA_FLAG_TCIF);
  DMA_ClearFlag(SPIx_RX_DMA_STREAM,SPIx_RX_DMA_FLAG_TCIF);   
#endif       
        

}
}

这个是我根据原子的列程改的 #define dma  是FATFS 显示 FR_NOT_READY     
                                        #define nodma  则可以使用文件系统  一切都正常   但是不满足 我想要的写入要求  想要提高速度   所以想到了用DMA  不知道还有什么方法可以提高写入SD卡的速度
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-16 11:17:20 | 显示全部楼层
回复【6楼】panjiadi586:
---------------------------------
SDIO驱动方式速度快点,可以试下

F4的DMA不能同时使用,否则死机,蛋疼的设计
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-16 11:24:47 | 显示全部楼层
回复【7楼】八度空间:
---------------------------------
DMA 不能同时使用 指的是啥是意思呢
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-16 13:00:00 | 显示全部楼层
回复【8楼】panjiadi586:
---------------------------------
开了DMA1再开DMA2就出问题,其他的没试过,呵呵
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

1

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2015-1-18
在线时间
6 小时
发表于 2015-1-23 22:23:22 | 显示全部楼层
回复【3楼】panjiadi586:
---------------------------------
楼主实现了吗?求代码
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-28 20:42:20 | 显示全部楼层
回复【9楼】八度空间:
---------------------------------
老师   为什么啥 我配的SDIO +FATFS比我 用SPI的速度还要慢很多  不知道是什么原因 ,您认为是哪边的问题呢  ?能给几个方向 参考下吗
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-29 07:33:21 | 显示全部楼层
回复【11楼】panjiadi586:
---------------------------------
代码优化一下,我目前的速度也不是很快,不过能满足目前的应用
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-29 11:43:49 | 显示全部楼层
回复【12楼】八度空间:
---------------------------------
我用示波器测试    在SPI+FATFS方式下  使用F_WRITE()函数一次写98Byte 是100多微秒         结果在SDIO+DMA+FATFS 下  使用F_WRITE()函数写入98Byte 却耗时3毫秒多  一算SDIO 比SPI 还慢了 30倍  不知道是怎么回事   太郁闷了
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
 楼主| 发表于 2015-1-29 11:45:22 | 显示全部楼层
回复【10楼】原来是你:
---------------------------------
没有呢  用SPI +DMA 没有弄起来  先测试下SDIO  结果比SPI 还慢  不知道是哪里的问题  好纠结啊
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-29 12:25:47 | 显示全部楼层
回复【13楼】panjiadi586:
---------------------------------
你的SDIO速度开多少
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

48

主题

180

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2016-3-18
在线时间
88 小时
发表于 2016-3-29 09:03:08 | 显示全部楼层
八度空间 发表于 2015-1-16 13:00
回复【8楼】panjiadi586:
---------------------------------
开了DMA1再开DMA2就出问题,其他的没试过,呵 ...

那你的意思就是F4的板不能开三路ADC然后使用DMA传送?还是可以DMA1传完关掉,然后DMA2再传
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-3-29 14:01:53 | 显示全部楼层
mengheli 发表于 2016-3-29 09:03
那你的意思就是F4的板不能开三路ADC然后使用DMA传送?还是可以DMA1传完关掉,然后DMA2再传

我试过只能开一路
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

0

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2013-5-5
在线时间
16 小时
发表于 2018-3-17 17:56:42 | 显示全部楼层
就是我想要的
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-20 17:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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