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条回答
seawind319
1楼-- · 2020-01-27 08:55
 精彩回答 2  元偷偷看……
mysky
2楼-- · 2020-01-27 14:38
楼主创意不错,记录一个!
收藏创意。
zbjzxc
3楼-- · 2020-01-27 19:01
由于不能上传文件。
就直接黏贴程序了。
1、main.c文件,它是主程序,内容如下:

#include "SD_MMC.c"
#include "LCD_160_128.c"
#include "SST89x5x4.H"
#include "fat32.c"
#include "show_bmp16.c"
#include "show_bin.c"
//程序入口
main()
{
lcd_init();
SPCR=0X5F;                          //128分频【最低速度】,高电平,后沿移位
while(sd_init()==0);
SPCR=0X5C;                          //4分频【最高速度】,高电平,后沿移位
sd_read(0);
s_p_c     = sd_512[0xd];
fat_area  = sd_512[0xf];
fat_area  = fat_area<<8; fat_area += sd_512[0xe];
fat_size  = sd_512[0x25];
fat_size  = fat_size<<8; fat_size += sd_512[0x24];
base_s=fat_size*2+fat_area;//根目录扇区,2簇,开始簇。
while(1)
{
read_root_sector();
name++;
if(success==0) name=0;
if(success==1) show_frame_bmp16();
if(success==2) show_frame_bin();
root_c=0x2;
success=0;
cluster_end=0;
}
}
zbjzxc
4楼-- · 2020-01-27 22:50
2、LCD_160_128.c文件,它是液晶驱动,内容如下:
#ifndef LCD_160_128
#define LCD_160_128


_delay_ms(int t)
{
        int i,j;
        for (i=0;i<t;i++) for(j=0;j<120;j++);
}

        sbit CS=0xb2;
        sbit RS=0xb3;
        sbit RW=0xb4;
        sbit Rd=0xb5;
        sbit PWM=0xb6;
        sbit RST=0xb7;

        sfr num_out = 0xa0;

//命令1字节
void send_command(unsigned int Cmd)
{
        CS=0;
        RS=0;
        num_out=Cmd;
        RW=0;RW=1;
        CS=1;
}

//数据1字节
void send_byte(unsigned char Data)
{
        CS=0;
        RS=1;
        num_out=Data;
        RW=0;RW=1;CS=1;
}


//1字节命令,1字节数据
void write_com(unsigned int Cmd,unsigned int num)
{
        CS=0;
        RS=0;num_out=Cmd;RW=0;RW=1;
        RS=1;num_out=num;RW=0;RW=1;
        CS=1;
}

//初始化
void lcd_init(void)
{
        CS=1;        RW=1;         Rd=1;        RS=1;
        RST=0;        
        _delay_ms(1);RST=1;
        send_command(0x11);_delay_ms( 1 );// sleep out/power on(SLPOUT)
        send_command(0x20);                  // display inversion off
        send_command(0x38);                  // ID mode off (IDMOFF)
        send_command(0x13);                  // Normal display mode on (Partial mode off)
                                          // color mode Interface pixel format  (COLMOD)
        write_com(0x3A,0x05);                  // 16-bit/pixel , 1-times data transfer
        write_com(0xC0,0x00);                  // power control 1      (PWCTR1) , GVDD voltage set 4.65
        write_com(0xC1,0x05);_delay_ms( 1 );
                                          // VCOMH voltage set 4.10V
        write_com(0xC5,0xc7);                  //;c0h   VCOMH voltage set 4.175V
        write_com(0xC6,0x07);_delay_ms( 1 );
        send_command(0xE0);
        send_byte(0x21);
        send_byte(0x11);
        send_byte(0x21);
        send_byte(0x22);
        send_byte(0x22);
        send_byte(0x33);
        send_byte(0x03);
        write_com(0x36,0xA0);                  // MY=1; MX=0; MV=0; ML=0; RGB=0
        send_command(0x37);
        send_byte(0x00);
        send_byte(0x00);                  // display on
        send_command(0x29);
}


//液晶定位
void LCD_SetArea( unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1 )
{
        send_command(0x2A);
        send_byte(0x00);
        send_byte(x0);
        send_byte(0x00);
        send_byte(x1);

        send_command(0x2B);
        send_byte(0x00);
        send_byte(y0);
        send_byte(0x00);
        send_byte(y1);
}

#endif
zbjzxc
5楼-- · 2020-01-28 04:43
3、SD_MMC.c文件,它是SD、MMC卡驱动,内容如下:

#ifndef SD_MMC
#define SD_MMC
#include "SD_MMC_DATA.c"
#include "SST89x5x4.H"

void send_byte(unsigned char);

sbit sd_mosi = P1^5;
sbit sd_miso = P1^6;
sbit sd_clk  = P1^7;
sbit sd_cs   = P1^4;



//读写sd卡时序,高位先发。
unsigned char sd_rw(unsigned char a)
{

        SPDR=a;         //spi输出
        while((SPSR&0x80)==0);
        SPSR=0;
        return SPDR;
}

//6字节命令
unsigned char sd_cmd(unsigned char *p)
{
        unsigned char i,a=0;

        sd_cs=1;
        sd_rw(0xff);
        sd_cs=0;
        for(i=0;i<6;i++) sd_rw(*p++);
        sd_rw(0xff);
        a=sd_rw(0xff);

        return a;
}

//mmc/sd 卡初始化
unsigned char sd_init(void)
{
        unsigned char cmd[]={0x40,0x00,0x00,0x00,0x00,0x95};
        unsigned char i=0;
        for(i=0;i<10;i++) sd_rw(0xff);
        i=0;
        if(sd_cmd(cmd)!=0x01)    return 0;
        cmd[0]=0x41;cmd[5]=0xff;
        while(sd_cmd(cmd)!=0X00) if( (++i)>200 ) return 0;
        return 1;
}




//读指定扇区512字节,跳转sd_512data_r()函数处理。
unsigned char sd_read(unsigned long address)
{
        unsigned char cmd[]={0x51,0x00,0x00,0x00,0x00,0xff};

        address=address<<9;
        cmd[1]=(address>>24);
        cmd[2]=(address>>16);
        cmd[3]=(address>>8);
        cmd[4]=(address>>0);
        if(sd_cmd(cmd)!=0x00) return 0;
        while(sd_rw(0xff)!=0xfe);
        sd_512data_r();
        sd_rw(0xff);sd_rw(0xff);
        return 1;
}


//读指定扇区512字节,跳转sd_512data_r_direct()函数处理。
unsigned char sd_read_direct(unsigned long address)
{
        unsigned char cmd[]={0x51,0x00,0x00,0x00,0x00,0xff};

        address=address<<9;
        cmd[1]=(address>>24);
        cmd[2]=(address>>16);
        cmd[3]=(address>>8);
        cmd[4]=(address>>0);
        if(sd_cmd(cmd)!=0x00) return 0;
        while(sd_rw(0xff)!=0xfe);
        sd_512data_r_direct();
        sd_rw(0xff);sd_rw(0xff);
        return 1;
}

#endif
zbjzxc
6楼-- · 2020-01-28 09:04
 精彩回答 2  元偷偷看……

一周热门 更多>