阅读:2280回复:0
小弟在玩单片机读写SD的一些心得
我用的是51单片机模拟spi总线来读写SD卡的,呵呵,其实51速度很是落后啦,即使是增强型的速度也就那吧,不说这个,谁让他用的多呢(连68013都是增强型51核的)。 在用51读写SD卡的实验过程中,我通过不断地优化代码也使读写速度有所提高。
其实速度的提高关键在于SD读写字节的代码优化,下面是我写的几个代码: 函数名:char SD_Byte_read(void); 功能:模拟spi读SD卡的一个字节。 涉及定义:SD_IN(SD卡的数据写入引脚),SD_OUT(SD卡的数据输出引脚),SD_CLK都是IO口的一个位定义, 如在8051中,可定义sbit SD_IN=P0^0:其它的类似。 代码1(C语言版): char SD_Byte_read(void) { uchar i,out_data; SD_IN=1; out_data=0; for(i=0;i<8;i++) { SD_CLK=0; out_data<<=1; //循环移位 SD_CLK=1; If(SD_OUT) out_data|=0x01;//置位最低位 } return out_data; } 代码2(C语言版): uchar bdata out_data; //定义即可位寻址又可字节寻址的变量 sbit out_data0=out_data^0; //定义out_data个bit位 sbit out_data1=out_data^1; sbit out_data2=out_data^2; sbit out_data3=out_data^3; sbit out_data4=out_data^4; sbit out_data5=out_data^5; sbit out_data6=out_data^6; sbit out_data7=out_data^7; char SD_Byte_read(void) { SD_IN=1; SD_CLK=0; SD_CLK=1; sbit out_data7=out_data^7; SD_CLK=0; SD_CLK=1; sbit out_data6=out_data^6; SD_CLK=0; SD_CLK=1; sbit out_data5=out_data^5; SD_CLK=0; SD_CLK=1; sbit out_data4=out_data^4; SD_CLK=0; SD_CLK=1; sbit out_data3=out_data^3; SD_CLK=0; SD_CLK=1; sbit out_data2=out_data^2; SD_CLK=0; SD_CLK=1; sbit out_data1=out_data^1; SD_CLK=0; SD_CLK=1; sbit out_data0=out_data^0; return out_data; } 代码3(C语言中嵌套汇编): char SD_Byte_read(void) { #pragma asm SETB SD_IN CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A CLR SD_CLK SETB SD_CLK MOV C,SD_OUT RRC A #pragma endasm return A; } 以上三段代码完成同一功能,但代码却各不相同。 从代码的简洁性来说,第一段代码是最简洁的,代码功能清楚明了,占用内存小,但是他是最优代码吗? 从代码占用内存量上来说,第一个是最好的(当然,如果把上述代码用汇编的循环语句形式写出将是最省空间的,但汇编的不好掌握以及灵活性差,移植性差等缺点是很多人选C的直接原因,我也是有这个思想的,但最近写程序让我打消了对汇编的轻视,这也是我写这篇文章的原因)。 但是,我们常常需要提高代码的功能执行速度(尤其是在时钟频率相对较低的微处理器,如8051中),而不看重代码的内存占用。可以看出,要是论代码执行速度,第一段代码却是最差的(尤其是在反汇编后看的更明白,大家可在Keil C中看看反汇编后的代码),占用指令周期是最多的,也就是代码冗余度是最大的。下面从代码占用指令周期数来考虑这些代码,我们看: 首先,第二,第三段代码都省去循环语句,以节约时间。 其次,第二段代码表面上看上去和第三段占用时间应该一样,但其实不然。 先看看第二点代码的反汇编(大致是这样的,用的是Keil C51编译器): SETB SD_IN CLR SD_CLK SETB SD_CLK MOV C,SD_OUT MOV C,out_data0 .......... .......... .......... CLR SD_CLK SETB SD_CLK MOV C,SD_OUT MOV C,out_data7 .......... .......... .......... 可看出和自己编的代码的不同之处是 MOV C,out_data0 ;反汇编 RRC A ;自己编的 学习过单片机(8051核的)指令的就看出这其中的不同了, MOV C,out_data0 ;占用两个指令周期 RRC A ;占用一个指令周期 至此,我们看出了汇编的强悍之处,进一步把这段代码(我就是用这段代码来读写SD卡的,几个代码段我都试验了)执行512次(对SD卡一次常读写512字节)或更长,就会感到明显的时间差距(这对低速微处理器提高SD卡读写速度是很有意义的)。 综上, 1.C语言用起来很方便,这点是大家公认的(甚至有些人鄙视汇编,说它过时了) 2.但是汇编是效率最高的(一般情况下,别抬杠呀)。 3.C与汇编结合是最好的,二者优势相结合,很牛。 4.想提高读或写的速度,那读写代码要分开写。 最后,小弟还想说的是在单片机上使用SD卡时并不一定要懂FAT16或FAT32,他们只是一种协议,让PC机能读SD卡的协议,去掉协议单片机照样可以存储数据到SD中,只不过这时电脑就不认SD卡了而已(用WinHex好像还可以读)。 还有,你若有空,完全可以自己定义一个自己的文件系统,然后接上USB接口,如68013,然后再写一个上位机然见照样可以读写你自己的文件系统里的文件。呵呵,一切都是协议,对上就行。 |
|
|