原创 SD卡读写程序设计(六)

2009-11-16 20:58 5606 8 8 分类: MCU/ 嵌入式

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

https://static.assets-stash.eet-china.com/album/old-resources/2009/11/16/48a25ccc-b857-4943-bd8d-c031fbd098c1.rar 用于智林STM32开发板

一、概述


经过两天的修改、调试,SD卡的读写程序已经可以正常工作了(擦除还不好用,原因未知),获取容量的函数也工作正常,基本用于文件系统移植的底层函数都准备完成了。现在来做一个简单的总结。


二、程序框架分析


1、串口命令


该程序建立在简单串口命令界面上实现,对于SD卡的操作实现了两个命令:sdrdsdwr。比如在串口输入命令sdrd后,通过命令处理函数调用函数void UartCmdSDRead(void)


2、命令处理函数


void UartCmdSDRead(void)中,首先对SD进行配置:调用SD_Config()函数。主要工作是复位、激活、设置块长度512、禁止CRC和设置SPI高速。


然后调用SD_GetCardInfo( &SDCardInfo )得到卡的块数量、块长度和容量,并在串口中断显示。


接着调用函数SD_ReadMultiBlock( BlockIndex,2,SDReadBuf )将开始两个块的数据共1024个字节读取到缓冲区,然后转变为十六进制字符串,在串口终端显示。


 


3SD卡用户层


共实现7个函数:


u8 SD_Config( void );


u8 SD_GetCardInfo( CardInfo * CardInfoPtr );


u8 SD_ReadBlock( u32 BlockIndex, u8* ReadBuf );


u8 SD_WriteBlock( u32 BlockIndex, u8* WriteBuf );


u8 SD_EraseBlock( u32 BlockIndex, u32 BlockNum );


u8 SD_WriteMultiBlock( u32 BlockIndex,u32 BlockNum, u8* WriteBuf );


u8 SD_ReadMultiBlock( u32 BlockIndex,u32 BlockNum, u8* ReadBuf );


各个函数的意义就在函数名称中,而各个函数的实现依据SD卡操作时序而来。比如其中SD_ReadMultiBlock函数的实现:


u8 SD_WriteMultiBlock( u32 BlockIndex,u32 BlockNum, u8* WriteBuf ){


  u16 i,j;


  u8 TmpByte; //发写单块命令24


  BlockIndex <<=9;


  if ( BlockNum ==0 )return 1;


  if ( SD_CmdWriteMulti( BlockIndex ) )


    {   SD_CSDisable( );  SPI_PutByte( 0xFF ); return 1; }


  for ( j="0"; j<BlockNum; j++ )


  {


         SPI_PutByte ( 0xFC );   //多块数据起始令牌


         for ( i="0"; i<BlockLen; i++ )


             SPI_PutByte( WriteBuf); //写入SD卡缓冲区


         SPI_PutByte( 0xEE );


         SPI_PutByte ( 0xEE );    //CRC校验,这里不使用


      


         TmpByte =SPI_GetByte( ); //获取数据响应


         if ( TmpByte&0x05 !=0x05 )


                {   SD_CSDisable( );  SPI_PutByte( 0xFF ); return 1; }


         SD_WaitInBusy( ); //SD忙时,一直等待。


 


         WriteBuf +=BlockLen; //缓冲区移动512字节


  }


  if ( SD_CmdStopTransmit( ) )       //发出停止传输命令


        {   SD_CSDisable( );  SPI_PutByte( 0xFF ); return 1; }


  SD_WaitInBusy( );  //SD忙时,一直等待。


  SD_CSEnable( );


  SPI_PutByte( 0xFF );


  return 0;


}


4SD卡命令层


主要是函数u8 SD_SendCmd()的实现,然后将一些基本操作封装起来。


比如:u8 SD_Reset( void);


u8 SD_Activate( void);


u8 SD_SetBlockLen( u16 BlockSize );


u8 SD_DisableCRC( void );


u8 SD_CmdGetCSD( void );


 


u8 SD_CmdReadSingle( u32 BlockIndex );


u8 SD_CmdWriteSingle( u32 BlockIndex );


void SD_WaitInBusy(void ); 等等。这些函数基本工作是调用命令发送函数来完成。


u8 SD_Reset( void ){


   u8 Reply;


   Reply =SD_SendCmd ( CmdReset, 0, 0x95 ) ;


   if ( Reply != 0x01 )return 1;


   SD_CSDisable( );


   SPI_PutByte( 0xFF );


   return 0;


}


5、底层操作:


void SD_CSEnable( void );


void SD_CSDisable( void );


void SPI_HighSpeed( void );


u8 SPI_GetByte( void );


void SPI_PutByte( u8 SendByte);


包括SD卡选择操作、SPI的发送和接收操作,SPI高速设置操作。


 


三、实现结果演示。


先执行sdrd,显示如下所示,第一个扇区结束有55 AA字符。


 750df597-5d9f-41dd-970c-ebb986e41ad1.JPG


点击看大图


然后执行sdwr,这个命令在第一扇区全部写入0x11,第二个扇区写入0x22,这是执行后的结果。读取第1扇区,显示全部为11.


点击看大图


 

文章评论0条评论)

登录后参与讨论
我要评论
0
8
关闭 站长推荐上一条 /2 下一条