STM32F429 HAL库 DMA方式实现用SD卡存储.csv文件

HAL库 DMA方式实现用SD卡存储.csv文件

前言:SD卡作为一个大容量的存储介质,用来做一些本地数据存储还是不错的,最近一个项目采用SD来存储设备的一些实时运行信息,最终敲定用.csv文件格式来做存储,方便管理和后续的数据分析处理~~主要是一个.csv文件可以装贼多条数据^ _ ^!

话不多说,接下来进入正题~~

1. SDIO底层驱动部分

这里我们用STM32CubeMx生成底层驱动,一些STM32的一些基础的时钟、GPIO等配置我就不赘述咯,直接上一些图吧

  • 时钟配置
    时钟配置
  • SDIO参数配置
    SDIO参数配置
    SDIO中断配置
    DMA配置
    这里的SDIO我们用DMA方式来进行数据收发,反正有DMA通道,不用闲着也是闲着~~

2.FATFS驱动部分

FATFS配置

3.MDK下驱动文件结构

生成的驱动文件结构如下如图所示:
驱动文件结构
下面对生成的文件进行一个说明:

文件名 文件内容
diskio.c FATFS 和 disk I/O 模块接口层文件
ff.c FATFS 模块
ff_gen_drv.c FatFs通用底层驱动
syscall.c 这里是对使用操作系统时的同步、内存管理操作的一些示例
bsp_driver_sd.c SD卡的底层驱动,BSP_SD_ReadBlocks_DMA、BSP_SD_WriteBlocks_DMA等API的实现
sd_diskio.c SD Disk I/O驱动,含SD_initialize、SD_read、SD_write、SD_ioctl等
sdio.c 包含SDIO驱动的配置,SDIO的时钟、引脚、速率、DMA通道等配置
fatfs_platform.c 这个文件里面是SD卡插入状态检测的代码

4.SD卡文件读写流程

下面用代码来阐述一下SD卡文件读写的一个流程

4.1读写文件前先做一些检查和文件系统的准备工作

uint8_t BSP_SdCheck(void)
{
    SD_DiskStuTypeDef cardStu;
        
	if(BSP_SD_IsDetected() == SD_PRESENT)
	{         
        //连接底层驱动
        FATFS_LinkDriver(&SD_Driver,SDPath );
        if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) == FR_OK){/* 注册文件系统对象,立即注册 */
            cardStu = SD_STU_OK;
        }else{ 
            cardStu = SD_STU_INVAL;   				     
        }
        g_SdDetectedFlag = DEF_SET;  
            
	}else{
  
		if(g_SdDetectedFlag == DEF_SET ){
			f_mount(NULL, (TCHAR const*)SDPath, 0);/* 注销文件系统对象 */
			FATFS_UnLinkDriver(SDPath); /* 解除底层连接,否则不能实现热插拔 */ 
			g_SdDetectedFlag = DEF_CLR;  
		}
	}
    
    return cardStu;
}
  1. 先检测SD卡是否插入
  2. 将SD卡底层驱动和磁盘链接起来,这里我们用的是"0:"盘符
  3. 挂载文件系统,如果上面步骤都成功我们就可以开始SD卡文件读写了
    tips:我这里是直接将文件保存到根目录下,如果需要对文件按目录区分可以在后续文件读写时增加一手创建/打开目录的操作。

4.2 .csv文件读写

.csv文件其实就是数据之间加逗号分隔符就可以将各个数据分开了,一般先写好标题,后面换行一直填充数据就行了~~

void RunInfoRecord(void)
{
    FIL fileobj;            /* File objects */
    FRESULT fr;             /* FatFs function common result code */
    UINT br;                /* File read/write count */
    CPU_SR_ALLOC();
    
    uint32_t size=0;        /* File size */    
    uint8_t buf[512];	    /* File read/write data buffer */   
    uint8_t p[25];          /* File path */    
    
    if(SD_STU_OK == BSP_SdCheck())		
    {   
        sprintf((char *)buf,"FC%02d%02d%02d.csv",(RTC_GetTimeYear()%100),RTC_GetTimeMonth(),RTC_GetTimeDate());//按日期进行数据存储
        sprintf((char *)p,"0:/%s",buf); //0:为SD卡盘符
        fr = f_open (&fileobj,(const char *)buf, FA_OPEN_ALWAYS | FA_WRITE);
        if(fr == FR_OK)
        {
            size = f_size(&fileobj);            
            if(size == 0) //第一次创建文件,添加标题栏
            {
                memset(buf,0,sizeof(buf));
                sprintf((char *)buf,"%s,%s,%s\r\n","Time","SysStep","ErrCode");
                fr= f_write(&fileobj, buf, sizeof(buf),(void *)&br);
                if(fr != FR_OK){
                    printf("Title write process error code is %d...\r\n",fr);  
                }   
            }else{    
                OS_CRITICAL_ENTER();              //防止写数据过程被打断
                fr= f_lseek(&fileobj,size);       //指针移至文件尾部,追加数据,如果用追加方式打开文件则不需要
                
                /* 分组追加运行数据 */
                for(int i=0;i<FUN_LIST_SIZE;i++){
                    
                    memset(buf,0,sizeof(buf));
                    sprintf((char *)buf,"%d:%d:%d,%d,%d,", 
                             RTC_GetTimeHours(),
                             RTC_GetTimeMinutes(),
                             RTC_GetTimeSeconds(),
                             sys_step,
                             sys_errCode);
                    fr = f_write(&fileobj, buf, sizeof(buf),(void *)&br);
                    if(fr != FR_OK){
                        printf("Data write process error code is %d...\r\n",fr);  
                    }
                }
            }            
        }else{
            printf("File Open failed,error code is %d...\r\n",fr);  
        }
        fr = f_close(&fileobj);
        if(fr != FR_OK){
            printf("f_close error code is %d...\r\n",fr);  
        }        
        OS_CRITICAL_EXIT();    
    }else{
        printf("SD Card check err...\r\n");  
    }
    SetSD_CardStau(SD_STU_IDLE);
}

当然啦,上面只是个范例,实际项目中我可不止这么点数据,上面简单写了个实现的方法,数据只要往buff里面加就好了~~不过需要注意的是我这里一次写的数据没有超过512byte,超过512byte可就需要再做做处理了。

结语

########## 完结撒花 ##########
注意一点:SDIO的速率不要太快了,否则会容易出现 FR_DISK_ERR

发布了13 篇原创文章 · 获赞 16 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_32969455/article/details/102765716