/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
/ AVR32 0 *1 RL78 0 *2 R32C 0 *2
/ PIC18 0/1 SH-2 0 *1 M16C 0/1
/ PIC24 0 *2 H8S 0 *1 MSP430 0 *2
/ PIC32 0 *1 H8/300H 0 *1 8051 0/1
/
/
* 1:高位优先。/
* 2:不支持不连续的内存访问。/
* 3:一些编译器生成LDM(逻辑磁盘管理器 ) / STM mem_cpy(内存拷贝)函数。
*/
(3)实现动态内存分配函数与时间函数
ff.h文件有动态内存的释放,动态内存申请,时间获取函数接口。
在diskio.c文件实现函数功能:
代码实现如下:
//动态内存分配
void* ff_memalloc (UINT msize) /* 分配内存块 */
{
return (void*)malloc(msize); //分配空间
}
//动态内存释放
void ff_memfree (void* mblock) /* 空闲内存块 */
{
free(mblock); //释放空间
}
//返回FATFS时间
//获得时间
DWORD get_fattime (void)
{
//Get_RTC_Timer(); //获取一次RTC时间
return (RTC_Timer.year-1980)<<25| //年
RTC_Timer.month<<21| //月
RTC_Timer.day<<16| //日
RTC_Timer.hour<<11| //时
RTC_Timer.minute<<5| //分
RTC_Timer.sec; //秒
}
/*
Return Value
Currnet local time is returned with packed into a DWORD value. The bit field is as follows:
bit31:25
Year origin from the 1980 (0..127)
bit24:21
Month (1..12)
bit20:16
Day of the month(1..31)
bit15:11
Hour (0..23)
bit10:5
Minute (0..59)
bit4:0
Second / 2 (0..29)
*/
(4)修改堆栈空间
完成了上述的修改,还需要修改堆栈空间,因为长文件支持需要占用堆空间。
修改STM32启动文件如下:
(5)编译工程测试
修改完毕之后,给开发板插上SD卡,调用API函数在SD卡创建一个文件,并写入数据,测试是否成功:
#include 'ff.h'
FATFS fs; // 用户定义的文件系统结构体
FIL file; // 用户定义的文件系统结构体
u8 buff[]='123 知识!!';
int main(void)
{
u32 data; //检测SD卡容量
u8 i,res;
LED_Init(); //LED灯初始化
Delay_Init();
KEY_Init();
USART1_Init(72,115200);
USART2_Init(36,115200);
FLASH_Init();
Set_Font_addr(); //字库地址初始化
FSMC_SRAM_Init();
LCD_Init();
RTC_Init(); //RTC时钟初始化
while(SD_Init()) //检测不到SD卡,SD相关硬件初始化
{
i=!i;
LCD_ShowString(60,150,200,16,16,'SD Card Error! Please Check SD Card!!',0xf800);
Delay_ms(500);
LED1(i)//DS0闪烁
}
f_mount(&fs,'0',1); // 注册工作区,驱动器号 0,初始化后其他函数可使用里面的参数
printf('注册工作区!n');
if(f_mkfs('0',0,4096)) //格式化SD卡
{
printf('格式化失败!!n');
}
else
{
printf('格式化成功!!n');
}
res = f_open(&file, '/file.c', FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
if(res==0)
{
printf('文件创建成功!!n');
}
else
{
printf('文件创建失败!!n');
}
res =f_write(&file,buff,strlen((const char*)buff),&data);
if(res==0)
{
printf('数据写入成功!!n');
}
else
{
printf('数据写入失败!!n');
}
printf('成功写入%d字节数据n',data);
f_close(&file); //关闭文件
//_FS_RPATH
while(1)
{
Delay_ms(1000);
LED1(1);
Delay_ms(500);
LED1(0);
}
}
五、案例使用
5.1 读取GBK字库文件(LCD汉字显示)
产品开发中,如果设备带有LCD显示屏,一般会显示各种文字提示,或者机器操作说明,显示中文需要字库,为了方便字模的提取,可以将字库文件制作好之后放到SD NAND上,通过文件系统打开字库文件,读取字模进行显示。
下面贴出文件系统读取字模的核心代码:
/*
函数功能: 显示GBK字库数据
u32 x 范围0~319
u32 y 范围0~479
u32 size 数据的宽度(必须是8的倍数) 是正方形
u8 *p 中文
说明: 取模横向坐标必须保证是8的倍数
*/
void ILI9341_DisplayGBKData(u32 x,u32 y,u32 size,u8 *p)
{
FIL fp;
UINT br;
u8 L,H;
u32 Addr;
u16 font_size=size/8*size; //字体占用的点阵码字节大小
u8 *buff=NULL;
H=*p;
L=*(p+1);
if(L<0x7f)L=L-0x40;
else L=L-0x41;
H=H-0x81;
Addr=(190*H+L)*font_size; //中文在字库里的偏移量
buff=malloc(font_size); //使用的堆空间
if(buff==NULL)return;
switch(size)
{
case 16:
if(f_open(&fp,'0:/font/gbk16.DZK',FA_READ)!=FR_OK)
{
printf('f_open error.rn');
}
f_lseek(&fp,Addr);
f_read(&fp,buff,font_size,&br);
f_close(&fp);
break;
case 24:
f_open(&fp,'0:/font/gbk24.DZK',FA_READ);
f_lseek(&fp,Addr);
f_read(&fp,buff,font_size,&br);
f_close(&fp);
break;
case 32:
break;
}
//显示中文
ILI9341_DisplayData(x,y,size,size,buff);
//释放空间
free(buff);
}
这是读取字模,显示的效果:
5.2 读取MP3文件播放(开机音乐)
这个例子是演示文件系统的目录扫描函数使用方式,读取指定目录下的MP3文件进行播放。
u8 PlayerMP3(const char *path);
FATFS FatFs;
int main()
{
LED_Init();
BEEP_Init();
KeyInit();
USARTx_Init(USART1,72,115200);
SDCardDeviceInit(); //初始化SD卡
// res=f_mkfs('0:',FM_ANY,0,work,sizeof work);
// if(res)printf('格式化失败!n');
// else printf('格式化成功!n');
f_mount(&FatFs, '0:', 0); //注册工作区
PlayerMP3('0:/MP3');
while(1)
{
DelayMs(100);
LED0=!LED0;
}
}
/*
函数功能: 扫描目录mp3播放
0表示成功 1表示失败
*/
u8 PlayerMP3(const char *path)
{
DIR dir;
FRESULT res;
FILINFO fno; //存放读取的文件信息
char *abs_path=NULL;
/*1. 打开目录*/
res=f_opendir(&dir,path);
if(res!=FR_OK)return res;
/*2. 循环读取目录*/
while(1)
{
res=f_readdir(&dir,&fno);
if(fno.fname[0] == 0 || res!=0)break;
printf('文件名称: %s,文件大小: %ld 字节rn',fno.fname,fno.fsize);
/*过滤目录*/
if(strstr(fno.fname,'.mp3'))
{
//申请存放文件名称的长度
abs_path=malloc(strlen(path)+strlen(fno.fname)+1);
if(abs_path==NULL)break;
strcpy(abs_path,path);
strcat(abs_path,'/');
strcat(abs_path,fno.fname);
printf('abs_path=%sn',abs_path);
VS1053_MP3(0,0,abs_path);
free(abs_path);
}
}
/*3. 关闭目录*/
f_closedir(&dir);
return 0;
}
上一篇:stm32单片机pwm设置与实际输出频率不一致
下一篇:STM32入门学习笔记之MPU6050传感器解析实验4
推荐阅读最新更新时间:2024-11-05 19:08
设计资源 培训 开发板 精华推荐
- 适用于 RGB、YPbPr 等的完整宽带 UTP 驱动器和接收器解决方案
- 使用 Analog Devices 的 LTC1174CN8-3.3 的参考设计
- 具有浪涌电流控制、过流保护、输入电压浪涌保护和反向输入保护的 LTC3897EUHF 非同步 107V/1.5A 2 相升压转换器的典型应用电路
- LTC3458 的典型应用 - 具有输出断开连接的 1.4A、1.5MHz 同步升压型 DC/DC 转换器
- 适用于 60 个白光 LED 的 LT3598 90% 效率 LED 驱动器的典型应用
- LT3091MPFE 低压差工作在非常低的输出电压下的典型应用
- LT1933HDCB 3.3V 降压转换器的典型应用电路
- LT1086CT-5 低压差负电源的典型应用
- STM32F411最小系统
- [712T]STM32G031G8U6开发板