一、思路
这里保存的是BMP图像,需要先连接bmp图像的数据格式。在STM32上采集的数据格式是RGB565方便在LCD上显示。如果直接发送还需要处理RGB565到RGB555的格式转换,以及bmp的数据头信息。
将bmp保存在sd卡上,这里移植FATFS文件系统。
图片保存的步骤:
配置bmp的图片头信息,
设置数据格式掩码,
写入图像数据。
二、移植文件系统
我们使用FATFS文件系统来管理SD卡,
FATFS文件系统
FATFS文件系统也就是一个软件,直接去官网下载最新版本即可。官网也有基本的介绍。下图是文件系统的结构:

在这里插入图片描述
应用层:
FATFS提供文件操作的API给应用层使用,完成自己的应用开发,不再需要考虑底层硬件的操作。这也是FATFS移植性好的原因。
中间层:
就是FATFS文件系统连接底层和应用层的桥梁,调用底层驱动封装成文件操作的API给应用层使用。这部分不需要修改,只需要简单的修改配置文件即可。
修改共10处,修改如下(正点原子):具体看注释
ffconf.h
//line13
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
//line20
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
//line36
#define _USE_STRFUNC 1 /* 0:Disable or 1-2:Enable */
//line40
#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
//line44
#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */
//line48
#define _USE_LABEL 1 /* 0:Disable or 1:Enable */
//line60
#define _CODE_PAGE 936 //采用中文GBK编码
//line92
#define _USE_LFN 3 /* 0 to 3 设置为1,支持长文件名,并采用动态内存*/
//line135
#define _VOLUMES 2
//line155
#define _MAX_SS 512
底层:
底层是移植文件系统时需要我们自己根据自己的硬件平台进行编写diskio.c。我直接使用正点原子提供的代码,但是自己不写也要读懂理解啊。
这里有6个函数:
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
//还有一个 get_fattime 函数,只读配置可以不用写
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2013 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control module to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include 'diskio.h' /* FatFs lower layer API */
#include 'mmc_sd.h'
#include 'flash.h'
#include 'malloc.h'
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//FATFS disio.c 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2014/3/14
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//
#define SD_CARD 0 //SD卡,卷标为0
#define EX_FLASH 1 //外部flash,卷标为1
#define FLASH_SECTOR_SIZE 512
//对于W25Q64
//前4.8M字节给fatfs用,4.8M字节后~4.8M+100K给用户用,4.9M以后,用于存放字库,字库占用3.09M.
u16 FLASH_SECTOR_COUNT= 9832; //4.8M字节,默认为W25Q64
#define FLASH_BLOCK_SIZE 8 //每个BLOCK有8个扇区
//初始化磁盘
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
u8 res=0;
switch(pdrv)
{
case SD_CARD://SD卡
res = SD_Initialize();//SD_Initialize()
if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
{
SD_SPI_SpeedLow();
SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
SD_SPI_SpeedHigh();
}
break;
case EX_FLASH://外部flash
SPI_Flash_Init();
if(SPI_FLASH_TYPE==W25Q64)FLASH_SECTOR_COUNT=9832; //W25Q64
else FLASH_SECTOR_COUNT=0; //其他
break;
default:
res=1;
}
if(res)return STA_NOINIT;
else return 0; //初始化成功
}
//获得磁盘状态
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
return 0;
}
//读扇区
//drv:磁盘编号0~9
//*buff:数据接收缓冲首地址
//sector:扇区地址
//count:需要读取的扇区数
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..128) */
)
{
u8 res=0;
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD://SD卡
res=SD_ReadDisk(buff,sector,count);
if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
{
SD_SPI_SpeedLow();
SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
SD_SPI_SpeedHigh();
}
break;
case EX_FLASH://外部flash
for(;count>0;count--)
{
SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
res=0;
break;
default:
res=1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
if(res==0x00)return RES_OK;
else return RES_ERROR;
}
//写扇区
//drv:磁盘编号0~9
//*buff:发送数据首地址
//sector:扇区地址
//count:需要写入的扇区数
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
)
{
u8 res=0;
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD://SD卡
res=SD_WriteDisk((u8*)buff,sector,count);
break;
case EX_FLASH://外部flash
for(;count>0;count--)
{
SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
res=0;
break;
default:
res=1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
if(res == 0x00)return RES_OK;
else return RES_ERROR;
}
#endif
//其他表参数的获得
//drv:磁盘编号0~9
//ctrl:控制代码
//*buff:发送/接收缓冲区指针
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
if(pdrv==SD_CARD)//SD卡
{
switch(cmd)
{
case CTRL_SYNC:
SD_CS=0;
if(SD_WaitReady()==0)res = RES_OK;
else res = RES_ERROR;
SD_CS=1;
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = 512;
res = RES_OK;
上一篇:【STM32调试(一)】串口发送像素,上位机解析显示
下一篇:Archlinux下 stm32 烧写工具配置
推荐阅读最新更新时间:2026-03-25 11:24
- 用于 7VIN 至 16VIN、1.5V 和 1.2V 输出的 LTM4628EV DC/DC 模块稳压器的典型应用电路
- 使用 Analog Devices 的 LTC3728LIGN 的参考设计
- DER-406 - 适用于 A19 灯的 5.76 W 高 PF 非隔离降压-升压型 TRIAC 调光 LED 驱动器
- ADR5045B 5V 输出精密微功率并联模式电压基准的典型应用
- LT3970EDDB-3.42 2.5V 降压转换器的典型应用
- MC78M08BDTG 8V 电流调节器的典型应用
- LT1021DCN8-5 精密电压基准的典型应用
- DER-282 - 100W, 扁平(11 mm), LLC DC-DC转换器
- REF193 低压差开尔文连接电压基准的典型应用电路
- LT3088EM 线性稳压器用于添加软启动的典型应用



【Follow me第三季第1期】- 代码合辑
嵌入式实时操作系统UCOS-III应用开发 基于STM32微控制器
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号