制作电子相册(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) 谢谢分享~好资料~ 这么快沙发就没了?效果图。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575056.jpg
(原文件名:mao.jpg) 重口味
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575061.jpg
(原文件名:feng.jpg) bmp图片像素记录顺序是从下到上的。因此。在设置彩屏的扫描方式的时候要选择从下到上扫描。否则图片是反的。
如果用Photoshop处理图片可以把一些图片改成合适的大小。然后用批处理操作就可以把大量的图片按相同的方式处理完。别忘了把图片保存成16位的。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_575062.jpg
(原文件名:16wei.jpg) 不错,不错楼主能把整个工程拿出来对我们这些新手就更好了 很好! 使用winhex软件方便知道SD卡里到底有哪些数据 给大家一个下载页面,是一千多张精美手机壁纸,分辨率是320×240,符合大多数我们玩的手机屏的分辨率。
里面多数是jpg格式的图片,也有少部分png和gif格式的。gif的图片无法转换成16位bmp格式。png的不清楚。
可以用Photoshop的批处理功能把数十张图片在十几秒内迅速转换完。
不过多数屏幕是竖着看的。那就让它从下到上扫描。并且在Photoshop中把图片旋转一下。变成240×320的分辨率,别忘改成16位
33.8M
http://www.800disk.com/filedown_344246.aspx 回复【5楼】wanglituan 小王
不错,不错楼主能把整个工程拿出来对我们这些新手就更好了
-----------------------------------------------------------------------
我的SD卡读写模块和彩屏读写模块基本也是扒的。而且sd卡的通用性差。大家也很容易看懂。这里没有公开的价值。
fat32的读写函数估计大家看过高手们写的。太庞大了,函数变量模块非常多。对我们估计眼花缭乱无从下手。因此我写了一个非常简单的方法供大家参考。这是我的态度。 mark 重口味。。。。 mark 标记一下 强_暴-暴强的贴,不顶怎么能行 还好,本人口问不重,灌水 mark MARK mark 请问,写正常簇的(除了第一簇),它的扇区号KK跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢?? for(n2=0;n2<16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思?? mark mark 回复【19楼】liudeen
请问,写正常簇的(除了第一簇),它的扇区号kk跟写第一簇相同吗??相同的话,那么它们的簇的地址怎么知道呢??
-----------------------------------------------------------------------
写比读复杂多了。我写的这玩意估计让人看了笑话。
写簇的话需要加上相应的头文件。写簇的话得自己找空塞进去,而且还得把fat表改好。挺复杂的。 回复【20楼】liudeen
for(n2=0;n2<16;n2++)//把一个簇分成16块,在相应位置查找关键字。(把sd卡格式化,保存几个文件,找找规律就明白了)??
问什么一个簇可以分成16块,一个簇有8个扇区,分成16块是什么意思??
-----------------------------------------------------------------------
说错了。是一个扇区分成16块。我自己蒙出来的想法。因为这些关键字都是隔行出现的。 楼主,能不能把你的源码公开放上来呢,好让大家学习学习 mark! mark 楼主,能不能公开你的源码啊??发扬OURAVR精神 期待 学习 tp3=m&0b11111;
m=((m&0b1111111111100000)<<1)|(tp3);//把555格式转换成565格式,m为565格式的一个像素值。
writedata(m);//这是往tft写像素点的函数,在别处定义。
这段编译不通过~?
还有个问题就是在winhex看是看物理驱动? 谢谢了,看懂了! 强烈抗议论坛上出现凤姐照片 mark mark markmark mark MARK mark一下 mark mark mark mark 凤姐无处不在啊 mark 学习 楼主可否将原理图及一些相关材料上传啊?!?! mark mark mark~~~ mark mark mark 标记啦、 吃素的路过。。。。。。。。。。。。。。。。。。。。 OK!!!
I found it hard! mark 初学(我是说自己) mark 撒泡尿,做个标记 mark mark 回复【61楼】lsy5110
mark
-----------------------------------------------------------------------
葫芦岛的,握个手 MARK 学习了 【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡 回复【65楼】lsy5110
【62楼】 turf456 圄困囿囡囚
--------------------------------
老乡
-----------------------------------------------------------------------
我在上学。家不是这的 收藏 学习! 楼主,能否看看你电子相册完整的的源程序呢???我的毕业设计正是51单片机做电子相册。。。。我的邮箱是zawlxj@126.com.... 学习了 mark 我也刚刚好要玩SD,参考一下先 回复【3楼】fyx2009 寂寞
重口味
(原文件名:feng.jpg)
引用图片
-----------------------------------------------------------------------
这个太象八两金了 MARK mark mark MAKR 回复【楼主位】fyx2009 寂寞
-----------------------------------------------------------------------
太好了我太需要了 mark mark MMMM mark mark; mark mark mark! mark 先分享一下,正好要用到这个。 mark mark!!!1 mark mark mark 一定要弄会!!! 看看,学习了 mark xue xi le mark 屏幕不一样大的话,进行一些修改就能用吧? {:smile:}你好 我最近也在sd卡 你能不能给我发一下你的代码参考下 我用的是430 824580747@qq.com 谢谢! 貌似很有用
页:
[1]
2