搜索
bottom↓
回复: 130

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

  [复制链接]

出0入0汤圆

发表于 2010-8-14 18:43:11 | 显示全部楼层 |阅读模式
看着高手们写的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+1];//读第2*j像素高字节
                tp1=buf[2*j];//读第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[2*j+1];//同上
                        tp1=buf[2*j];//                       
                        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[2*j+1];
                        tp1=buf[2*j];
                        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[n2*32+8];
                tp2=buf[n2*32+9];
                tp3=buf[n2*32];//文件名首字节
                tp4=buf[n2*32+29];
                tp5=buf[n2*32+30];
                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[n2*32+27]<<8)|buf[n2*32+26];//记下文件第一簇簇号,一共有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图片,不能直接移植到其它用途。因为写的太简单了,漏洞百出。高手勿喷。入门比较不错。
下图以我用的卡为例。

(原文件名:32feiqu.JPG)

出0入0汤圆

发表于 2010-8-14 18:57:45 | 显示全部楼层
谢谢分享~好资料~

出0入0汤圆

 楼主| 发表于 2010-8-14 19:08:43 | 显示全部楼层
这么快沙发就没了?效果图。

(原文件名:mao.jpg)

出0入0汤圆

 楼主| 发表于 2010-8-14 19:12:03 | 显示全部楼层
重口味

(原文件名:feng.jpg)

出0入0汤圆

 楼主| 发表于 2010-8-14 19:20:51 | 显示全部楼层
bmp图片像素记录顺序是从下到上的。因此。在设置彩屏的扫描方式的时候要选择从下到上扫描。否则图片是反的。
如果用Photoshop处理图片可以把一些图片改成合适的大小。然后用批处理操作就可以把大量的图片按相同的方式处理完。别忘了把图片保存成16位的。

(原文件名:16wei.jpg)

出0入0汤圆

发表于 2010-8-14 19:26:34 | 显示全部楼层
不错,不错楼主能把整个工程拿出来对我们这些新手就更好了

出0入0汤圆

发表于 2010-8-14 19:30:48 | 显示全部楼层
很好! 使用winhex软件方便知道SD卡里到底有哪些数据

出0入0汤圆

 楼主| 发表于 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

出0入0汤圆

 楼主| 发表于 2010-8-14 19:46:21 | 显示全部楼层
回复【5楼】wanglituan 小王
不错,不错楼主能把整个工程拿出来对我们这些新手就更好了
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-8-15 00:45:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-15 01:11:55 | 显示全部楼层
重口味。。。。

出0入0汤圆

发表于 2010-8-15 01:34:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-15 07:36:08 | 显示全部楼层
标记一下

出0入0汤圆

发表于 2010-8-15 09:23:41 | 显示全部楼层
强_暴-暴强的贴,不顶怎么能行

出0入9汤圆

发表于 2010-8-15 11:04:08 | 显示全部楼层
还好,本人口问不重,灌水

出0入0汤圆

发表于 2010-8-15 11:09:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-15 12:02:02 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-8-15 12:38:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-16 15:57:01 | 显示全部楼层
请问,写正常簇的(除了第一簇),它的扇区号KK跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢??

出0入0汤圆

发表于 2010-8-16 16:14:56 | 显示全部楼层
for(n2=0;n2<16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思??

出0入0汤圆

发表于 2010-8-16 16:31:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-16 21:51:39 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-8-17 00:28:55 | 显示全部楼层
回复【19楼】liudeen
请问,写正常簇的(除了第一簇),它的扇区号kk跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢??
-----------------------------------------------------------------------

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

出0入0汤圆

 楼主| 发表于 2010-8-17 00:30:32 | 显示全部楼层
回复【20楼】liudeen
for(n2=0;n2&lt;16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思??  

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

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

出0入0汤圆

发表于 2010-8-17 08:37:12 | 显示全部楼层
楼主,能不能把你的源码公开放上来呢,好让大家学习学习

出0入0汤圆

发表于 2010-8-17 08:47:59 | 显示全部楼层
mark!

出0入0汤圆

发表于 2010-8-17 09:51:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-17 10:09:40 | 显示全部楼层
楼主,能不能公开你的源码啊??发扬OURAVR精神

出0入0汤圆

发表于 2010-8-17 14:29:14 | 显示全部楼层
期待 学习

出0入0汤圆

发表于 2010-8-18 08:37:07 | 显示全部楼层
tp3=m&0b11111;
m=((m&0b1111111111100000)<<1)|(tp3);//把555格式转换成565格式,m为565格式的一个像素值。
writedata(m);//这是往tft写像素点的函数,在别处定义。

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

出0入0汤圆

发表于 2010-8-18 14:21:38 | 显示全部楼层
谢谢了,看懂了!

出0入0汤圆

发表于 2010-8-19 14:48:04 | 显示全部楼层
强烈抗议论坛上出现凤姐照片

出0入16汤圆

发表于 2010-8-19 17:02:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-19 18:17:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-19 21:04:06 | 显示全部楼层
markmark

出0入0汤圆

发表于 2010-9-4 18:30:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-5 00:45:56 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-9-5 09:36:20 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2010-9-15 00:38:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-15 17:07:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-15 17:24:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-4 16:15:19 | 显示全部楼层
mark   凤姐无处不在啊

出0入0汤圆

发表于 2010-10-5 20:20:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-5 21:19:08 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-10-6 11:55:53 | 显示全部楼层
楼主可否将原理图及一些相关材料上传啊?!?!

出0入0汤圆

发表于 2010-10-7 17:36:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 13:57:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-10 19:33:41 | 显示全部楼层
mark~~~

出70入145汤圆

发表于 2010-10-10 22:58:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-12 19:53:42 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-13 14:56:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-13 19:28:25 | 显示全部楼层
标记啦、

出0入0汤圆

发表于 2010-11-13 21:26:03 | 显示全部楼层
吃素的路过。。。。。。。。。。。。。。。。。。。。

出0入0汤圆

发表于 2010-12-14 14:37:42 | 显示全部楼层
OK!!!
I found it hard!

出0入0汤圆

发表于 2010-12-15 01:06:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-15 20:02:30 | 显示全部楼层
初学(我是说自己)

出0入0汤圆

发表于 2010-12-17 16:55:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-21 18:30:09 | 显示全部楼层
撒泡尿,做个标记

出0入0汤圆

发表于 2010-12-29 16:56:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-20 16:21:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-20 17:29:52 | 显示全部楼层
回复【61楼】lsy5110
mark
-----------------------------------------------------------------------

葫芦岛的,握个手

出0入0汤圆

发表于 2011-1-20 20:39:27 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-20 20:57:53 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-1-21 23:03:40 | 显示全部楼层
【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡

出0入0汤圆

发表于 2011-1-21 23:19:21 | 显示全部楼层
回复【65楼】lsy5110
【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡
-----------------------------------------------------------------------

我在上学。家不是这的

出0入0汤圆

发表于 2011-1-29 16:26:07 | 显示全部楼层
收藏

出0入0汤圆

发表于 2011-1-29 21:00:09 | 显示全部楼层
学习!

出0入0汤圆

发表于 2011-2-27 10:51:14 | 显示全部楼层
楼主,能否看看你电子相册完整的的源程序呢???我的毕业设计正是51单片机做电子相册。。。。我的邮箱是zawlxj@126.com....

出0入0汤圆

发表于 2011-3-9 21:51:26 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-3-15 22:08:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-22 20:10:58 | 显示全部楼层
我也刚刚好要玩SD,参考一下先

出0入0汤圆

发表于 2011-3-23 11:54:14 | 显示全部楼层
回复【3楼】fyx2009 寂寞
重口味


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

这个太象八两金了

出0入0汤圆

发表于 2011-3-23 12:57:09 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-3-23 20:41:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-11 23:23:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-14 22:03:07 | 显示全部楼层
MAKR

出0入0汤圆

发表于 2011-5-3 22:16:08 | 显示全部楼层
回复【楼主位】fyx2009 寂寞
-----------------------------------------------------------------------

太好了我太需要了

出0入0汤圆

发表于 2011-7-15 01:33:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-18 10:42:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-19 00:38:52 | 显示全部楼层
MMMM

出0入0汤圆

发表于 2011-8-19 17:50:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-30 22:25:52 | 显示全部楼层
mark;

出0入0汤圆

发表于 2011-8-30 22:32:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-31 07:51:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-3 10:27:18 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-9-27 13:24:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-27 22:41:19 | 显示全部楼层
先分享一下,正好要用到这个。

出0入0汤圆

发表于 2011-10-20 18:26:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-12 10:48:47 | 显示全部楼层
mark!!!1

出0入0汤圆

发表于 2011-11-12 14:07:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-12 14:37:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-12 18:48:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-12 23:57:40 | 显示全部楼层
一定要弄会!!!

出0入0汤圆

发表于 2011-11-13 08:49:00 | 显示全部楼层
看看,学习了

出0入0汤圆

发表于 2011-11-13 17:00:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-13 18:23:19 | 显示全部楼层
xue xi le

出0入0汤圆

发表于 2011-12-3 11:00:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-3 11:20:47 | 显示全部楼层
屏幕不一样大的话,进行一些修改就能用吧?

出0入0汤圆

发表于 2012-4-11 22:03:50 | 显示全部楼层
你好 我最近也在sd卡 你能不能给我发一下你的代码参考下 我用的是430            824580747@qq.com 谢谢!

出0入0汤圆

发表于 2012-4-23 15:08:24 | 显示全部楼层
貌似很有用
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 22:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表