制作电子相册(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+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图片,不能直接移植到其它用途。因为写的太简单了,漏洞百出。高手勿喷。入门比较不错。
下图以我用的卡为例。

原文地址:http://www.amobbs.com/forum.php?mod=viewthread&tid=4209354&highlight=fat

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值