参考了原子哥哥的例程。其实SD卡的初始化以及FAT文件系统也移植到了我的板子上面。但是我要存一张BMP的照片,不知道为啥,每次存储150kb进入TF卡的时候,时间不确定。有时几百毫秒。有时要好几秒。导致我完全不能够实时保存一些图片。导致系统卡机。而且在FAT文件系统下,还不能够使用DMA释放CPU。
下面贴出 TF卡初始化例程,参考来自于正点原子源码:
u8 SD_Init(void)
{
u8 SD_Error;
//初始化时的时钟不能大于400KHZ
SDCARD_Handler.Instance=SDMMC1;
SDCARD_Handler.Init.ClockEdge=SDMMC_CLOCK_EDGE_RISING; //上升沿
SDCARD_Handler.Init.ClockBypass=SDMMC_CLOCK_BYPASS_DISABLE; //不使用bypass模式,直接用HCLK进行分频得到SDIO_CK
SDCARD_Handler.Init.ClockPowerSave=SDMMC_CLOCK_POWER_SAVE_DISABLE; //空闲时不关闭时钟电源
SDCARD_Handler.Init.BusWide=SDMMC_BUS_WIDE_1B; //1位数据线
SDCARD_Handler.Init.HardwareFlowControl=SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;//关闭硬件流控
SDCARD_Handler.Init.ClockDiv=SDMMC_TRANSFER_CLK_DIV; //SD传输时钟频率最大25MHZ
SD_Error=HAL_SD_Init(&SDCARD_Handler,&SDCardInfo);
if(SD_Error!=SD_OK) return 1;
SD_Error=HAL_SD_WideBusOperation_Config(&SDCARD_Handler,SDMMC_BUS_WIDE_4B);//使能宽总线模式
if(SD_Error!=SD_OK) return 2;
return 0;
}
//SDMMC底层驱动,时钟使能,引脚配置,DMA配置
//此函数会被HAL_SD_Init()调用
//hsd:SD卡句柄
void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_SDMMC1_CLK_ENABLE(); //使能SDMMC1时钟
__HAL_RCC_DMA2_CLK_ENABLE(); //使能DMA2时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟
//PC8,9,10,11,12
GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF12_SDIO; //复用为SDIO
HAL_GPIO_Init(GPIOC,&GPIO_Initure); //初始化
//PD2
GPIO_Initure.Pin=GPIO_PIN_2;
HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化
#if (SD_DMA_MODE==1) //使用DMA模式
HAL_NVIC_SetPriority(SDMMC1_IRQn,2,0); //配置SDMMC1中断,抢占优先级2,子优先级0
HAL_NVIC_EnableIRQ(SDMMC1_IRQn); //使能SDMMC1中断
//配置发送DMA
SDRxDMAHandler.Instance=DMA2_Stream3;
SDRxDMAHandler.Init.Channel=DMA_CHANNEL_4;
SDRxDMAHandler.Init.Direction=DMA_PERIPH_TO_MEMORY;
SDRxDMAHandler.Init.PeriphInc=DMA_PINC_DISABLE;
SDRxDMAHandler.Init.MemInc=DMA_MINC_ENABLE;
SDRxDMAHandler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;
SDRxDMAHandler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD;
SDRxDMAHandler.Init.Mode=DMA_PFCTRL;
SDRxDMAHandler.Init.Priority=DMA_PRIORITY_VERY_HIGH;
SDRxDMAHandler.Init.FIFOMode=DMA_FIFOMODE_ENABLE;
SDRxDMAHandler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
SDRxDMAHandler.Init.MemBurst=DMA_MBURST_INC4;
SDRxDMAHandler.Init.PeriphBurst=DMA_PBURST_INC4;
__HAL_LINKDMA(hsd, hdmarx, SDRxDMAHandler); //将接收DMA和SD卡的发送DMA连接起来
HAL_DMA_DeInit(&SDRxDMAHandler);
HAL_DMA_Init(&SDRxDMAHandler); //初始化接收DMA
//配置接收DMA
SDTxDMAHandler.Instance=DMA2_Stream6;
SDTxDMAHandler.Init.Channel=DMA_CHANNEL_4;
SDTxDMAHandler.Init.Direction=DMA_MEMORY_TO_PERIPH;
SDTxDMAHandler.Init.PeriphInc=DMA_PINC_DISABLE;
SDTxDMAHandler.Init.MemInc=DMA_MINC_ENABLE;
SDTxDMAHandler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;
SDTxDMAHandler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD;
SDTxDMAHandler.Init.Mode=DMA_PFCTRL;
SDTxDMAHandler.Init.Priority=DMA_PRIORITY_VERY_HIGH;
SDTxDMAHandler.Init.FIFOMode=DMA_FIFOMODE_ENABLE;
SDTxDMAHandler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
SDTxDMAHandler.Init.MemBurst=DMA_MBURST_INC4;
SDTxDMAHandler.Init.PeriphBurst=DMA_PBURST_INC4;
__HAL_LINKDMA(hsd, hdmatx, SDTxDMAHandler);//将发送DMA和SD卡的发送DMA连接起来
HAL_DMA_DeInit(&SDTxDMAHandler);
HAL_DMA_Init(&SDTxDMAHandler); //初始化发送DMA
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 3, 0); //接收DMA中断优先级
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 3, 0); //发送DMA中断优先级
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
#endif
}
接下来我继续更新。希望能够达到实时存储。
找到问题原因了,在FAT文件系统当中,如果不是一次性写完一个文件,而是分开来写一个文件,也就是连续调用f_write函数,后面这个函数的运行时间是不确定的。所以我把整个文件打包,直接一次写入,速度很快。、
但是又遇到了新的问题,每次创建一个新的文件,它需要的时间要好几百毫秒。这个太慢了,很大的影响我的操作。准备找到新的解决办法,并且如果要实时存视频的话,也需要新的办法。