整理stm32Fatfs读写SD卡.docx
《整理stm32Fatfs读写SD卡.docx》由会员分享,可在线阅读,更多相关《整理stm32Fatfs读写SD卡.docx(33页珍藏版)》请在冰豆网上搜索。
![整理stm32Fatfs读写SD卡.docx](https://file1.bdocx.com/fileroot1/2023-2/22/c4068d20-0c72-40d3-9d72-462e4542fad1/c4068d20-0c72-40d3-9d72-462e4542fad11.gif)
整理stm32Fatfs读写SD卡
stm32Fatfs读写SD卡
读写SD是嵌入式系统中一个比较基础的功能,在很多应用中都可以用得上SD卡。
折腾了几天,总算移植成功了最新版Fatfs(FatfsR0.09),成功读写SD卡下文件。
FatFs(http:
//elm-chan.org/fsw/ff/00index_e.html)是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。
FatFs的编写遵循ANSIC,因此不依赖于硬件平台。
它可以嵌入到便宜的微控制器中,如8051,PIC,AVR,SH,Z80,H8,ARM等等,不需要做任何修改。
1.SD卡/TF卡硬件接口
SD卡有两种操作接口,SDIO和SPI。
使用SDIO口的速度比较快,SPI的速度比较慢。
SD卡引脚描述如下:
SD卡SPI接法如下:
我使用的是正点原子的开发板,所以采用的是SPI接口的模式。
TF卡SDIO模式和SPI模式引脚定义:
可以发现MicroSD卡只有8个引脚是因为比SD卡少了一个Vss。
使用TF转SD的卡套套在MicroSD卡上,这样一来大小就和SD卡一样大,这时候卡套上的9个引脚就和SD卡一样了,你可以完全当做SD卡来操作。
2.SD卡底层驱动
SD卡的操作比较复杂,需要多看看一些文档。
这里附上SD底层驱动代码,代码说明详见注释
Sd卡SPi操作底层代码:
sdcard.c sdcard.h
3.Fatfs移植
FatFs软件包中相关文件:
ffconf.h FatFs模块配置文件
ff.h FatFs和应用模块公用的包含文件
ff.c FatFs模块
diskio.h FatFsanddiskI/O模块公用的包含文件
integer.h 数据类型定义
option 可选的外部功能
diskio.c FatFs与diskI/O模块接口层文件(不属于FatFs需要由用户提供)
FatFs配置,文件系统的配置项都在ffconf.h文件之中:
(1)_FS_TINY:
这个选项在R0.07版本之中开始出现,在之前的版本都是以独立的文件出现,现在通过一个宏来修改使用起来更方便;
(2)_FS_MINIMIZE、_FS_READONLY、_USE_STRFUNC、_USE_MKFS、_USE_FORWARD这些宏是用来对文件系统进行裁剪
(3)_CODE_PAGE:
本选项用于设置语言码的类型
(4)_USE_LFN:
取值为0~3,主要用于长文件名的支持及缓冲区的动态分配:
0:
不支持长文件名;
1:
支持长文件名存储的静态分配,一般是存储在BSS段;
2:
支持长文件名存储的动态分配,存储在栈上;
3:
支持长文件名存储的动态分配,存储在堆上。
(5)_MAX_LFN:
可存储长文件的最大长度,其值一般为(12~255),但是缓冲区一般占(_MAX_LFN+1)*2bytes;
(6)_LFN_UNICODE:
为1时才支持unicode码;
(7)_FS_RPATH:
R0.08a版本改动配置项,取值范围0~2:
0:
去除相对路径支持和函数;
1:
开启相对路径并且开启f_chdrive()和f_chdir()两个函数;
2:
在1的基础上添加f_getcwd()函数。
(8)_VOLUMES:
支持的逻辑设备数目;
(9)_MAX_SS:
扇区缓冲的最大值,其值一般为512;
(10)_MULTI_PARTITION:
定义为1时,支持磁盘多个分区;
(11)_USE_ERASE:
R0.08a新加入的配置项,设置为1时,支持扇区擦除;
(12)_WORD_ACCESS:
如果定义为1,则可以使用word访问;
(13)_FS_REENTRANT:
定义为1时,文件系统支持重入,但是需要加上跟操作系统信号量相关的几个函数,函数在syscall.c文件中;
(14)_FS_SHARE:
文件支持的共享数目。
Fatfs开源文件系统从R0.07e之后版本开始就不再提供底层接口文件diskio.c模板,这里附上根据
以上SD卡底层驱动对应的diskio.c源码:
001
#include"common.h"
002
/*-----------------------------------------------------------------------*/
003
/*InidializeaDrive */
004
005
DSTATUSdisk_initialize(
006
BYTE drv /*Physicaldrivenmuber(0..)*/
007
)
008
{
009
u8state;
010
011
if(drv)
012
{
013
return STA_NOINIT; //仅支持磁盘0的操作
014
}
015
016
state=SD_Init();
017
if(state==STA_NODISK)
018
{
019
return STA_NODISK;
020
}
021
else if(state!
=0)
022
{
023
return STA_NOINIT; //其他错误:
初始化失败
024
}
025
else
026
{
027
return 0; //初始化成功
028
}
029
}
030
031
032
033
/*-----------------------------------------------------------------------*/
034
/*ReturnDiskStatus */
035
036
DSTATUSdisk_status(
037
BYTE drv /*Physicaldrivenmuber(0..)*/
038
)
039
{
040
if(drv)
041
{
042
return STA_NOINIT; //仅支持磁盘0操作
043
}
044
045
//检查SD卡是否插入
046
if(!
SD_DET())
047
{
048
return STA_NODISK;
049
}
050
return 0;
051
}
052
053
054
055
/*-----------------------------------------------------------------------*/
056
/*ReadSector(s) */
057
058
DRESULTdisk_read(
059
BYTE drv, /*Physicaldrivenmuber(0..)*/
060
BYTE *buff, /*Databuffertostorereaddata*/
061
DWORD sector, /*Sectoraddress(LBA)*/
062
BYTE count /*Numberofsectorstoread(1..255)*/
063
)
064
{
065
u8res=0;
066
if (drv||!
count)
067
{
068
return RES_PARERR; //仅支持单磁盘操作,count不能等于0,否则返回参数错误
(五)规划环境影响评价的跟踪评价069
}
(1)生产力变动法070
if(!
SD_DET())
3.政府部门规章
071
{
072
return RES_NOTRDY; //没有检测到SD卡,报NOTREADY错误
073
疾病成本法和人力资本法将环境污染引起人体健康的经济损失分为直接经济损失和间接经济损失两部分。
直接经济损失有:
预防和医疗费用、死亡丧葬费;间接经济损失有:
影响劳动工时造成的损失(包括病人和非医务人员护理、陪住费)。
这种方法一般通常用在对环境有明显毒害作用的特大型项目。
}
『正确答案』B074
C.可能造成较大环境影响的建设项目,应当编制环境影响报告书075
3.评估环境影响的价值(最重要的一步):
采用环境经济学的环境经济损益分析方法,对量化后的环境功能损害后果进行货币化估价,即对建设项目的环境费用或环境效益进行估价。
1.准备阶段076
同建设项目安全评价相关但又有不同的还有:
《地质灾害防治管理办法》规定的地质灾害危险性评估,《地震安全性评价管理条例》中规定的地震安全性评价,《中华人民共和国职业病防治法》中规定的职业病危害预评价等。
077
if(count==1) //1个sector的读操作
078
(3)是否符合区域、流域规划和城市总体规划。
{
079
res=SD_ReadSingleBlock(sector,buff);
080
}
081
else //多个sector的读操作
082
{
083
res=SD_ReadMultiBlock(sector,buff,count);
084
}
085
/*
086
do
087
{
088
if(SD_ReadSingleBlock(sector,buff)!
=0)
089
{
090
res=1;
091
break;
092
}
093
buff+=512;
094
}while(--count);
095
*/
096
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
097
if(res==0x00)
098
{
099
return RES_OK;
100
}
101
else
102
{
103
return RES_ERROR;
104
}
105
}
106
107
108
109
/*-----------------------------------------------------------------------*/
110
/*WriteSector(s) */
111
112
#if_READONLY==0
113
DRESULTdisk_write(
114
BYTE drv, /*Physicaldrivenmuber(0..)*/
115
const BYTE *buff, /*Datatobewritten*/
116
DWORD sector, /*Sectoraddress(LBA)*/
117
BYTE count /*Numberofsectorstowrite(1..255)*/
118
)
119
{
120
u8res;
121
122
if (drv||!
count)
123
{
124
return RES_PARERR; //仅支持单磁盘操作,count不能等于0,否则返回参数错误
125
}
126
if(!
SD_DET())
127
{
128
return RES_NOTRDY; //没有检测到SD卡,报NOTREADY错误
129
}
130
131
//读写操作
132
if(count==1)
133
{
134
res=SD_WriteSingleBlock(sector,buff);
135
}
136
else
137
{
138
res=SD_WriteMultiBlock(sector,buff,count);
139
}
140
//返回值转换
141
if(res==0)
142
{
143
return RES_OK;
144
}
145
else
146
{
147
return RES_ERROR;
148
}
149
}
150
#endif/*_READONLY*/
151
152
153
154
/*-----------------------------------------------------------------------*/
155
/*MiscellaneousFunctions */
156
157
DRESULTdisk_ioctl(
158
BYTE drv, /*Physicaldrivenmuber(0..)*/
159
BYTE ctrl, /*Controlcode*/
160
void *buff /*Buffertosend/receivecontroldata*/
161
)
162
{
163
DRESULTres;
164
165
166
if (drv)
167
{
168
return RES_PARERR; //仅支持单磁盘操作,否则返回参数错误
169
}
170
171
//FATFS目前版本仅需处理CTRL_SYNC,GET_SECTOR_COUNT,GET_BLOCK_SIZ三个命令
172
switch(ctrl)
173
{
174
case CTRL_SYNC:
175
SD_CS_ENABLE();
176
if(SD_WaitReady()==0)
177
{
178
res=RES_OK;
179
}
180
else
181
{
182
res=RES_ERROR;
183
}
184
SD_CS_DISABLE();
185
break;
186
187
case GET_BLOCK_SIZE:
188
*(WORD*)buff=512;
189
res=RES_OK;
190
break;
191
192
case GET_SECTOR_COUNT:
193
*(DWORD*)buff=SD_GetCapacity();
194
res=RES_OK;
195
break;
196
default:
197
res=RES_PARERR;
198
break;
199
}
200
201
return res;
202
}
203
204
/*-----------------------------------------------------------------------*/
205
/*Userdefinedfunctiontogiveacurrenttimetofatfsmodule */
206
/*31-25:
Year(0-127org.1980),24-21:
Month(1-12),20-16:
Day(1-31)*/
207
/*15-11:
Hour(0-23),10-5:
Minute(0-59),4-0:
Second(0-29*2)*/