51单片机做电子相册-fat32文件系统

2020-01-23 14:24发布

51单片机做电子相册
文/张彬杰



(原文件名:实物图3.jpg)
本文介绍的电子相册如图,通过51单片机,自动播放SD/MMC卡存储设备的图像。电子相册具有传统相册无法比拟的优越性:图、文并茂的表现手法,随意修改编辑的功能,永不褪 {MOD}的恒久保存特性。而我们通过简单的电路,自己动手就可以实现了。


一、电路可实现功能

(原文件名:实物图4.jpg)  
如图所示,整个播放器的电路由彩 {MOD}液晶【左】、SD/MMC卡槽【中】和51单片机最小系统【右】3个部分组成。彩 {MOD}液晶用于图像的显示,SD/MMC卡槽用于插入存储设备,51单片机最小系统用于控制和播放图像。使用时,将SD/MMC卡格式化成fat32文件系统,然后把bmp格式图片复制到SD/MMC卡,即可自动播放。


二、所需元器件及材料
整个播放器几乎没使用什么分立元件。使用了一片LM1117-3.3及它的若干外围元件,进行电源电压转换,把电源电压稳定到3.3V。选用SST89E58RD单片机做为主控制芯片。它有1k的内部RAM ,有硬件SPI接口,最高可用40M晶振。单片机的外围元件组成了51最小系统。最后买了个SD/MMC卡槽,方便插入SD/MMC卡。彩 {MOD}液晶屏幕的分辨率是160x128,自带SPFD54124B控制器,这样只要通过发送命令就可以方便显示图像了。更具体的元器件,请看电路原理图,就不再一一介绍了。


三、电路原理

(原文件名:电子像册原理图.gif)  
电路原理如图。关键是如何和SD/MMC卡连接,以及如何和彩 {MOD}液晶连接。然而它们的连接方式都是直接连接的,直接和单片机的I/O口连接,很方便。在电源方面,用USB充电器的5v电源,经过LM1117-3.3稳压模块,转换成3.3v电压。当然了,如果有3.3v的电源,也可以直接使用。剩下的就是单片机最小系统了。 


四、SD卡的特点和通讯协议:
1、两个可选的通信协议:SD模式和SPI模式
2、可变时钟频率0-25MHz
3、工作电压范围:2.0-3.6V
4、卡片带电插拔保护
5、兼容MMC卡命令
SD卡有两个可选的通讯协议:SD模式和SPI模式。SD模式是SD卡标准的读写方式,但是在选用SD模式时,往往需要选择带有SD卡控制器接口的单片机,或者必须加入额外的SD卡控制单元以支持SD卡的读写。然而,一般单片机没有集成SD卡控制器接口,若选用SD模式通讯就无形中增加了产品的硬件成本。在SD卡数据读写时间要求不是很严格的情况下,选用SPI模式可以说是一种最佳的解决方案。因为在SPI模式下,通过四条线就可以完成所有的数据交换,并且目前市场上很多单片机都有现成的SPI接口电路,采用SPI模式对SD卡进行读写操作可大大简化硬件电路的设计,具体请看电路原理图了。
由于SD卡兼容MMC卡命令。所以,使用MMC卡的命令集。SD/MMC卡每次通信,传输48位,即6字节的数据。第1字节是命令,紧接着4字节是参数,一般用于指定SD/MMC卡的字节地址。 最后,一个字节是校验码。一般,命令也就用到0x40复位命令、 0x41初始化命令、 0x51读扇区命令、0x58 写扇区命令。硬件SPI接口电平上,设置单片机的时钟线,默认为1,设置数据在时钟的后沿移位。注意,在初始化阶段最好设置SPI频率为128分频,较低速度。等初始化完成再把分频系数改为4分频,较高速度,正常使用SD/MMC卡。


五、重点器件的选择理由及介绍
单片机的内存要大于512字节,因为SD/MMC卡的数据读写是512字节为单位的。并且要有SPI接口,因为程序使用SD卡的SPI通讯协议。所以,我选用SST89E58RD单片机作为主控制芯片。彩 {MOD}液晶要选自带控制器的,因为一般单片机不带液晶控制器。彩 {MOD}液晶的具体控制方式要看技术手册了,不同控制器,它的控制方法不一样。如果没有彩 {MOD}液晶,用熟悉的128X64的黑白液晶练习下也行。


六、制作过程介绍
我用了两片万用板,一片用来固定SD/MMC卡槽。另一片用来做单片机最小系统。在淘宝网上买了一片1.8英寸的彩 {MOD}液晶。使用了这3个部分组成一个整体,并用插针插座连接。电源用USB接口的5v电压,所以在万用板上焊接了miniUSB接口。当然,如果想要携带方便,也可以使用电池供电。


七、使用效果

(原文件名:实物图1.jpg)


(原文件名:实物图2.jpg)  
如图在彩 {MOD}液晶上显示图像。显示完一幅图像后,延迟2秒,继续显示下一幅。图像与图像之间从左往右,从上往下快速的切换。文件名以3位数字命名,存放在根目录下,从000开始,顺序读取。当读取不到下一个文件时,重新从000读取。Bmp文件是r-g-b 5-5-5存放的高彩 {MOD}图象,图像大小为:160x128。可用Photoshop,另存为产生。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
99条回答
zbjzxc
1楼-- · 2020-01-28 09:25
5、fat32.c 文件,它是简单的fat32文件系统,内容如下:

#ifndef fat32
#define fat32
#include"sd_mmc.c"


unsigned int  i=0,j,l=54;
unsigned long addr,x_addr,y_addr,root_s=0,base_s=0,cluster=0,first_c,root_c=0x2;
unsigned char s_p_c = 0;
unsigned char fat_area = 0;
unsigned int  fat_size = 0;
unsigned int  name=0;
unsigned char success=0,cluster_end=0;
int k,bmp_16;

//根目录扩展簇
extern_boot_cluster()
{
sd_read(fat_area+root_c/128);//“簇地址记录”所在扇区
i=root_c%128;                //每扇区128条“簇地址记录”,4字节簇地址
root_c =sd_512[i*4+3];
root_c =root_c<<8;
root_c+=sd_512[i*4+2];
root_c =root_c<<8;
root_c+=sd_512[i*4+1];
root_c =root_c<<8;
root_c+=sd_512[i*4];
if(root_c==0x0fffffff)cluster_end=1;//结束标志
}


//在根目录,读文件起始簇号,1扇区16条文件记录
file_first_cluster()
{

for(i=0;i<512;i+=32)
{

if(
sd_512   == (0x30+name%1000/100)&&
sd_512[i+1] == (0x30+name%100/10)&&
sd_512[i+2] == (0x30+name%10/1)&&
sd_512[i+8] == 'B'&&
sd_512[i+9] == 'M'&&
sd_512[i+10]== 'P')
{
first_c = sd_512[i+0x15];
first_c = first_c<<8;
first_c+= sd_512[i+0x14];
first_c = first_c<<8;
first_c+= sd_512[i+0x1b];
first_c = first_c<<8;
first_c+= sd_512[i+0x1a];
success=1;
break;}

if(
sd_512   == (0x30+name%1000/100)&&
sd_512[i+1] == (0x30+name%100/10)&&
sd_512[i+2] == (0x30+name%10/1)&&
sd_512[i+8] == 'B'&&
sd_512[i+9] == 'I'&&
sd_512[i+10]== 'N')
{
first_c = sd_512[i+0x15];
first_c = first_c<<8;
first_c+= sd_512[i+0x14];
first_c = first_c<<8;
first_c+= sd_512[i+0x1b];
first_c = first_c<<8;
first_c+= sd_512[i+0x1a];
success=2;
break;}


}

}


//读根目录扇区
read_root_sector()
{
while(cluster_end==0)
{
for(j=0;j<s_p_c;j++)      //1簇,j扇区,根目录文件读取
{
root_s=(root_c-2)*s_p_c+base_s+j;
sd_read(root_s);
file_first_cluster();     //寻找文件,定位首簇
if(success>0) break;
}
if(success>0) break;
extern_boot_cluster();    //读根目录下1簇
}
}

#endif
zbjzxc
2楼-- · 2020-01-28 15:06
5、show_bmp16.c 文件,它是简单的BMP文件处理函数,内容如下:

#ifndef show_bmp16
#define show_bmp16
#include "SD_MMC.c"
#include "lcd_160_128.c"
#include "fat32.c"

line1()
{
for(i=512-(320-l);i<512;i+=2)
{
send_byte( (sd_512[i+1]<<1)|(sd_512>>7) );
send_byte( (sd_512<<1)& 0xe0 | sd_512& 0x1f );
}
}


line2()
{
for(i=0;i<l;i+=2)
{
send_byte( (sd_512[i+1]<<1)|(sd_512>>7));
send_byte( (sd_512<<1)&0xe0 | sd_512&0x1f);
}
}


line3()
{
for(i=l;i<l+320;i+=2)
{
send_byte( (sd_512[i+1]<<1)|(sd_512>>7));  send_byte( (sd_512<<1)&0xe0 | sd_512&0x1f);
}
}


//显示1幅图像
show_frame_bmp16()
{
LCD_SetArea(0,0,159,128); send_command(0x2C);
for(bmp_16=79;bmp_16>=0;bmp_16--)
{

if(bmp_16>=s_p_c)
{
cluster = first_c;
for(k=bmp_16/s_p_c; k>0; k--)
{
sd_read(fat_area+cluster/128);i=cluster%128;//每扇区128条簇地址记录【fat】
cluster =sd_512[i*4+3];cluster=cluster<<8;
cluster+=sd_512[i*4+2];cluster=cluster<<8;
cluster+=sd_512[i*4+1];cluster=cluster<<8;
cluster+=sd_512[i*4];
}
x_addr=(cluster-2) * s_p_c + base_s + bmp_16%s_p_c;
}
else
x_addr=(first_c-2) * s_p_c + base_s + bmp_16%s_p_c;

sd_read(x_addr);
line1();

if( (bmp_16+1)>=s_p_c)
{
cluster = first_c;
for( k=(bmp_16+1)/s_p_c; k>0; k--)
{
sd_read(fat_area+cluster/128);i=cluster%128;//每扇区128条簇地址记录【fat】
cluster =sd_512[i*4+3];cluster=cluster<<8;//4字节簇地址
cluster+=sd_512[i*4+2];cluster=cluster<<8;
cluster+=sd_512[i*4+1];cluster=cluster<<8;
cluster+=sd_512[i*4];
}
y_addr=(cluster-2) * s_p_c + base_s + (bmp_16+1)%s_p_c;
}
else
y_addr=(first_c-2) * s_p_c + base_s + (bmp_16+1)%s_p_c;

sd_read(y_addr);
line2();

l=512-(320-l);
if(l>=320)
{
l-=320;
sd_read(x_addr);
line3();
}
}
_delay_ms(14000);//2秒等待
}


#endif
biansf2001
3楼-- · 2020-01-28 16:38
留名
zbjzxc
4楼-- · 2020-01-28 18:49
6、show_bin.c 文件,它是简单的BIN文件处理函数,内容如下:



#ifndef show_bin
#define show_bin
#include "SD_MMC.c"
#include "lcd_160_128.c"
#include "fat32.c"

show_frame_bin()
{
LCD_SetArea(0,0,159,128);send_command(0x2C);
cluster=first_c;
while(1)
{
        addr = ( (cluster-2) * s_p_c + base_s); //簇地址 转换 扇区地址
        for(i = 0;i<s_p_c;i++) sd_read_direct(addr+i); //每簇扇区数
        sd_read(fat_area+cluster/128);
        i=cluster%128;          //每扇区128条簇地址记录【fat】
        cluster = sd_512[i*4+3];
        cluster=cluster<<8;
        cluster+= sd_512[i*4+2];
        cluster=cluster<<8;
        cluster+= sd_512[i*4+1];
        cluster=cluster<<8;
        cluster+= sd_512[i*4];
        if(cluster==0x0fffffff) break;
        }
_delay_ms(14000);//2秒等待
}

#endif
zbjzxc
5楼-- · 2020-01-28 23:55
 精彩回答 2  元偷偷看……
fy024
6楼-- · 2020-01-29 03:03
支持楼主

一周热门 更多>