fyx2009 发表于 2010-8-14 18:43:11

制作电子相册(sd卡读取bmp图片显示在tft彩屏上)读取fat32的步骤非常简单的方法(简单意

看着高手们写的SD卡读fat32或fat的程序。动辄数百行,模块强大,功能丰富。近似完美,通用性强,但看着也眼花缭乱的,让新手无从下手。
玩tft彩屏和sd卡的目的之一就是把sd卡中的图片显示到彩屏上。
这有个简单的办法找到fat32文件系统中的图片依次显示在彩屏上。
sd卡驱动和彩屏驱动这里不涉及。就拿240*320的tft彩屏和1G的sd卡为例。
fat32文件系统和bmp格式的资料网上屎一样多。对照文件的hex值很容易研究明白
读fat32的简单规律就是先从根目录出发。找到bmp和相关字眼,记下第一簇位置。然后读fat表。找到第一簇,和下一簇簇号。把当前簇的几个扇区的内容写在屏幕上。然后循环几次找到其余簇就把全部图片显示出来。至于循环次数可以图片的用字节大小计算。
我这里SD卡中第一fat表是第36扇区,根目录是第3904扇区,每簇8扇区。可以从分区头文件中读出来。为了方便我就在下面直接写数值了。


/////////////////////////////下面的函数是显示图片第一簇的,因为bmp文件第一簇第一扇区有一些文件信息。要跳过,不予显示。当然你也可以写函数读出来。
writefirst(unsigned int kk)//显示第一簇,kk为扇区号,去掉头信息
{
        unsigned int m,j;
        unsigned char tp1,tp2,tp3,k;
        SD_Read_Sector(kk,buf);
        for(j=27;j<=255;j++)//第一扇区中的第一像素从第54字节开始,前面的是文件信息。因此此扇区单独处理
        {
                tp2=buf;//读第2*j像素高字节
                tp1=buf;//读第2*j像素低字节       
                m=(tp2<<8)|tp1;
                  tp3=m&0b11111;
                m=((m&0b1111111111100000)<<1)|(tp3);//把555格式转换成565格式,m为565格式的一个像素值。
                writedata(m);//这是往tft写像素点的函数,在别处定义。

        }
        for(k=1;k<8;k++)//其余7个扇区全部写入。
        {
                SD_Read_Sector(kk+k,buf);
                for(j=0;j<=255;j++)
                {
                        tp2=buf;//同上
                        tp1=buf;//                       
                        m=(tp2<<8)|tp1;
                        tp3=m&0b11111;
                        m=((m&0b1111111111100000)<<1)|(tp3);//同上
                        writedata(m);
                }
        }
}


//////////////////////////////////下面的函数是写正常簇的(除了第一簇)。一个簇8个扇区全写入,原理同上
writecu(unsigned int kk)//显示一簇,kk为扇区号
{
        unsigned int m,j;
        unsigned char tp1,tp2,tp3,k;
        for(k=0;k<8;k++)
        {
                SD_Read_Sector(kk+k,buf);
                for(j=0;j<=255;j++)
                {
                        tp2=buf;
                        tp1=buf;
                        m=(tp2<<8)|tp1;
                        tp3=m&0b11111;
                        m=((m&0b1111111111100000)<<1)|(tp3);
                        writedata(m);
                }
        }
}

/////////////////////////主要部分//////////////////tp1到tp6为uchar,其余为uint。buf为512字节的缓冲区(全局变量)。
////////////////////void SD_Read_Sector(扇区数,缓冲数组)为sd卡读扇区的函数。应位于sd读写模块中。
fatcunum=0;//一个全局变量,表示当前是fat表中第几簇。
for(n1=0;n1<8;n1++)//依次读根目录中的8个扇区,虽然fat32不限制文件数量,这里不考虑(偷懒,但不是直接读第九个扇区)。
{
        SD_Read_Sector(3904+n1,buf);//读根目录的第n1扇区,从第3904扇区开始
        for(n2=0;n2<16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)
        {
                tp1=buf;
                tp2=buf;
                tp3=buf;//文件名首字节
                tp4=buf;
                tp5=buf;
                if((tp1==0x42)&&(tp2==0x4d)&&(tp3!=0xe5)&&(tp4==0x58)&&(tp5==0x02))
///////////////////////查找root中的bmp字样和文件大小字样,我这里查找"B","M","0xe5",“0x58”,“0x02”这几个字样,
//////////////////////符合要求的图片大小一定是0x25836字节或者0x25838字节。文件名首字节如果是0xE5表示已删除,如果全部满足条件,开始读取文件。
                {       
                        addset(0,0,239,319);//这是在定义tft中的显示区域,应在显示模块中定义。
                        cu=(buf<<8)|buf;//记下文件第一簇簇号,一共有4个字节,在此只读取后两字节。(偷懒呗,一般用不到那么多)
                        fatcunum=cu/0x80;//每扇区有0x80个簇号,fatcunum表示下一个簇号位于fat表的第几簇,全局变量
                        SD_Read_Sector(36+fatcunum,buf);//读下一簇号指向的的fat表的簇
                        writefirst((cu-3)*8+3912);//写第一簇的数据(赋值为扇区号),这是刚才上面定义的函数。文件的第一簇簇号为3,所以需要减去。8表示每簇8扇区。3912为数据区的第一扇区。
                        for(tp6=0;tp6<37;tp6++)//为什么循环37次后面解释。
                        {
                                SD_Read_Sector(36+fatcunum,buf);//一定再次读fat表(刚才的操作把buf中的数改了)               
                                nextcu=(buf[(cu-(fatcunum*0x80))*4+1]<<8)|buf[(cu-(fatcunum*0x80))*4];//下一簇簇号
                                fatcunum=nextcu/0x80;//算出下一簇号位于fat表的第几簇
                                writecu((nextcu-3)*8+3912);//写其余扇区的数据,刚才上面定义的。
                                cu=nextcu;
                                SD_Read_Sector(36+fatcunum,buf);//一定再读fat表
                        }
                }                       
        SD_Read_Sector(3904+n1,buf);//一定再读根目录。刚才的操作可能改buf中的数据。
        }
}
为什么循环37次,因为一个符合要求的16位的240×320的bmp图片大小一定是0x25836字节或者0x25838字节。以0x25836为例。
转成十进制就是153654字节,以本程序为例,每簇8扇区。153654÷512÷8=37.51,就是说占了37个半簇,第一簇特殊处理。还剩下36.5簇。因此这里循环37次,当然最后的一个簇的不完整会导致显示有问题,通过观察只是屏幕最左侧或者最右侧有一两条线异常。无伤大雅。如果你不嫌麻烦就写个处理结尾簇的函数。


这就完事了。通过观察,8M晶振,显示完整每幅图片需要1.5秒,是连续显示。如果你需要按键操作的话自己加个标志位。

这个方法仅针对显示240×320的16位bmp图片,不能直接移植到其它用途。因为写的太简单了,漏洞百出。高手勿喷。入门比较不错。
下图以我用的卡为例。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575055.JPG
(原文件名:32feiqu.JPG)

poet_lee 发表于 2010-8-14 18:57:45

谢谢分享~好资料~

fyx2009 发表于 2010-8-14 19:08:43

这么快沙发就没了?效果图。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575056.jpg
(原文件名:mao.jpg)

fyx2009 发表于 2010-8-14 19:12:03

重口味
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575061.jpg
(原文件名:feng.jpg)

fyx2009 发表于 2010-8-14 19:20:51

bmp图片像素记录顺序是从下到上的。因此。在设置彩屏的扫描方式的时候要选择从下到上扫描。否则图片是反的。
如果用Photoshop处理图片可以把一些图片改成合适的大小。然后用批处理操作就可以把大量的图片按相同的方式处理完。别忘了把图片保存成16位的。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575062.jpg
(原文件名:16wei.jpg)

wanglituan 发表于 2010-8-14 19:26:34

不错,不错楼主能把整个工程拿出来对我们这些新手就更好了

vipcff 发表于 2010-8-14 19:30:48

很好! 使用winhex软件方便知道SD卡里到底有哪些数据

fyx2009 发表于 2010-8-14 19:40:56

给大家一个下载页面,是一千多张精美手机壁纸,分辨率是320×240,符合大多数我们玩的手机屏的分辨率。
里面多数是jpg格式的图片,也有少部分png和gif格式的。gif的图片无法转换成16位bmp格式。png的不清楚。
可以用Photoshop的批处理功能把数十张图片在十几秒内迅速转换完。
不过多数屏幕是竖着看的。那就让它从下到上扫描。并且在Photoshop中把图片旋转一下。变成240×320的分辨率,别忘改成16位

33.8M
http://www.800disk.com/filedown_344246.aspx

fyx2009 发表于 2010-8-14 19:46:21

回复【5楼】wanglituan 小王
不错,不错楼主能把整个工程拿出来对我们这些新手就更好了
-----------------------------------------------------------------------

我的SD卡读写模块和彩屏读写模块基本也是扒的。而且sd卡的通用性差。大家也很容易看懂。这里没有公开的价值。
fat32的读写函数估计大家看过高手们写的。太庞大了,函数变量模块非常多。对我们估计眼花缭乱无从下手。因此我写了一个非常简单的方法供大家参考。这是我的态度。

maidilong 发表于 2010-8-15 00:45:52

mark

gc56198 发表于 2010-8-15 01:11:55

重口味。。。。

kbdcj2000 发表于 2010-8-15 01:34:45

mark

chenao 发表于 2010-8-15 07:36:08

标记一下

zlj2008 发表于 2010-8-15 09:23:41

强_暴-暴强的贴,不顶怎么能行

Semiconductor 发表于 2010-8-15 11:04:08

还好,本人口问不重,灌水

cuikai12345 发表于 2010-8-15 11:09:17

mark

wxfx2006 发表于 2010-8-15 12:02:02

MARK

yusufu 发表于 2010-8-15 12:38:53

mark

liudeen 发表于 2010-8-16 15:57:01

请问,写正常簇的(除了第一簇),它的扇区号KK跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢??

liudeen 发表于 2010-8-16 16:14:56

for(n2=0;n2<16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思??

MCU678 发表于 2010-8-16 16:31:51

mark

maybe_it 发表于 2010-8-16 21:51:39

mark

fyx2009 发表于 2010-8-17 00:28:55

回复【19楼】liudeen
请问,写正常簇的(除了第一簇),它的扇区号kk跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢??
-----------------------------------------------------------------------

写比读复杂多了。我写的这玩意估计让人看了笑话。
写簇的话需要加上相应的头文件。写簇的话得自己找空塞进去,而且还得把fat表改好。挺复杂的。

fyx2009 发表于 2010-8-17 00:30:32

回复【20楼】liudeen
for(n2=0;n2&lt;16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思??

-----------------------------------------------------------------------

说错了。是一个扇区分成16块。我自己蒙出来的想法。因为这些关键字都是隔行出现的。

liudeen 发表于 2010-8-17 08:37:12

楼主,能不能把你的源码公开放上来呢,好让大家学习学习

kneken 发表于 2010-8-17 08:47:59

mark!

dianzifanfan 发表于 2010-8-17 09:51:36

mark

liudeen 发表于 2010-8-17 10:09:40

楼主,能不能公开你的源码啊??发扬OURAVR精神

andrew_dj 发表于 2010-8-17 14:29:14

期待 学习

chenfzg 发表于 2010-8-18 08:37:07

tp3=m&0b11111;
m=((m&0b1111111111100000)<<1)|(tp3);//把555格式转换成565格式,m为565格式的一个像素值。
writedata(m);//这是往tft写像素点的函数,在别处定义。

这段编译不通过~?
还有个问题就是在winhex看是看物理驱动?

chenfzg 发表于 2010-8-18 14:21:38

谢谢了,看懂了!

236076313 发表于 2010-8-19 14:48:04

强烈抗议论坛上出现凤姐照片

xstt 发表于 2010-8-19 17:02:32

mark

bluelool 发表于 2010-8-19 18:17:59

mark

lininglive 发表于 2010-8-19 21:04:06

markmark

wjhltk 发表于 2010-9-4 18:30:30

mark

stm8s 发表于 2010-9-5 00:45:56

MARK

hdd961140543 发表于 2010-9-5 09:36:20

mark一下

wjhltk 发表于 2010-9-15 00:38:52

mark

swustlx86 发表于 2010-9-15 17:07:52

mark

akcheng 发表于 2010-9-15 17:24:55

mark

qwert12131 发表于 2010-10-4 16:15:19

mark   凤姐无处不在啊

adai 发表于 2010-10-5 20:20:01

mark

worldly_guest 发表于 2010-10-5 21:19:08

学习

tomy 发表于 2010-10-6 11:55:53

楼主可否将原理图及一些相关材料上传啊?!?!

cuikai12345 发表于 2010-10-7 17:36:25

mark

feixuehanyi 发表于 2010-10-8 13:57:01

mark

hclmcu 发表于 2010-10-10 19:33:41

mark~~~

hailing 发表于 2010-10-10 22:58:13

mark

673710663 发表于 2010-10-12 19:53:42

mark

jwc_210 发表于 2010-11-13 14:56:45

mark

wt19891211 发表于 2010-11-13 19:28:25

标记啦、

yunlong 发表于 2010-11-13 21:26:03

吃素的路过。。。。。。。。。。。。。。。。。。。。

passjordan 发表于 2010-12-14 14:37:42

OK!!!
I found it hard!

ju748 发表于 2010-12-15 01:06:33

mark

laoyin 发表于 2010-12-15 20:02:30

初学(我是说自己)

Bisu 发表于 2010-12-17 16:55:03

mark

xsx728 发表于 2010-12-21 18:30:09

撒泡尿,做个标记

sun8406 发表于 2010-12-29 16:56:31

mark

lsy5110 发表于 2011-1-20 16:21:21

mark

turf456 发表于 2011-1-20 17:29:52

回复【61楼】lsy5110
mark
-----------------------------------------------------------------------

葫芦岛的,握个手

416446891 发表于 2011-1-20 20:39:27

MARK

yan716 发表于 2011-1-20 20:57:53

学习了

lsy5110 发表于 2011-1-21 23:03:40

【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡

turf456 发表于 2011-1-21 23:19:21

回复【65楼】lsy5110
【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡
-----------------------------------------------------------------------

我在上学。家不是这的

kongan 发表于 2011-1-29 16:26:07

收藏

fwt11 发表于 2011-1-29 21:00:09

学习!

woniuxiaoan 发表于 2011-2-27 10:51:14

楼主,能否看看你电子相册完整的的源程序呢???我的毕业设计正是51单片机做电子相册。。。。我的邮箱是zawlxj@126.com....

ljc0124 发表于 2011-3-9 21:51:26

学习了

weiwdr05 发表于 2011-3-15 22:08:26

mark

kaikai23 发表于 2011-3-22 20:10:58

我也刚刚好要玩SD,参考一下先

snakevip 发表于 2011-3-23 11:54:14

回复【3楼】fyx2009 寂寞
重口味


(原文件名:feng.jpg)
引用图片
-----------------------------------------------------------------------

这个太象八两金了

sankunchai 发表于 2011-3-23 12:57:09

MARK

ringan865 发表于 2011-3-23 20:41:54

mark

nhdsong 发表于 2011-4-11 23:23:56

mark

136420962 发表于 2011-4-14 22:03:07

MAKR

longjiajia234 发表于 2011-5-3 22:16:08

回复【楼主位】fyx2009 寂寞
-----------------------------------------------------------------------

太好了我太需要了

lewisz 发表于 2011-7-15 01:33:55

mark

miaoran1990 发表于 2011-8-18 10:42:02

mark

ARMVSAVR 发表于 2011-8-19 00:38:52

MMMM

wyftm 发表于 2011-8-19 17:50:31

mark

1013269594 发表于 2011-8-30 22:25:52

mark;

abcdzhy 发表于 2011-8-30 22:32:31

mark

kingboy100 发表于 2011-8-31 07:51:58

mark

homa 发表于 2011-9-3 10:27:18

mark!

huangjinyi 发表于 2011-9-27 13:24:59

mark

lixiansong 发表于 2011-9-27 22:41:19

先分享一下,正好要用到这个。

WinLiu 发表于 2011-10-20 18:26:23

mark

l09046162 发表于 2011-11-12 10:48:47

mark!!!1

jemmy 发表于 2011-11-12 14:07:50

mark

Joyliz 发表于 2011-11-12 14:37:21

mark

bluelool 发表于 2011-11-12 18:48:37

mark

Tankng 发表于 2011-11-12 23:57:40

一定要弄会!!!

yanghc 发表于 2011-11-13 08:49:00

看看,学习了

logic.pn 发表于 2011-11-13 17:00:22

mark

borage 发表于 2011-11-13 18:23:19

xue xi le

TROYWINDON 发表于 2011-12-3 11:00:22

mark

TROYWINDON 发表于 2011-12-3 11:20:47

屏幕不一样大的话,进行一些修改就能用吧?

beijix1988 发表于 2012-4-11 22:03:50

{:smile:}你好 我最近也在sd卡 你能不能给我发一下你的代码参考下 我用的是430            824580747@qq.com 谢谢!

wyz.0413 发表于 2012-4-23 15:08:24

貌似很有用
页: [1] 2
查看完整版本: 制作电子相册(sd卡读取bmp图片显示在tft彩屏上)读取fat32的步骤非常简单的方法(简单意