单片机读写SD卡最简单最基本的程序.docx

上传人:b****6 文档编号:6265212 上传时间:2023-01-04 格式:DOCX 页数:14 大小:19.17KB
下载 相关 举报
单片机读写SD卡最简单最基本的程序.docx_第1页
第1页 / 共14页
单片机读写SD卡最简单最基本的程序.docx_第2页
第2页 / 共14页
单片机读写SD卡最简单最基本的程序.docx_第3页
第3页 / 共14页
单片机读写SD卡最简单最基本的程序.docx_第4页
第4页 / 共14页
单片机读写SD卡最简单最基本的程序.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

单片机读写SD卡最简单最基本的程序.docx

《单片机读写SD卡最简单最基本的程序.docx》由会员分享,可在线阅读,更多相关《单片机读写SD卡最简单最基本的程序.docx(14页珍藏版)》请在冰豆网上搜索。

单片机读写SD卡最简单最基本的程序.docx

单片机读写SD卡最简单最基本的程序

处理器:

s3c44b0(arm7)

SD卡与处理器的引脚连接:

MISO-->SIORxD  MOSI-->SIOTxD  CLK-->SCLK  CS-->PE5

包括四个文件:

sd_drive.c:

用户API函数,移植时不需修改

                        sd_cmd.c:

中间层函数,移植时不需修改

                        sd_hard.c:

硬件层函数,移植时需修改

                        sd_config.h:

一些功能的宏定义,移植时需修改

第一次读写SD卡时,需调用SD_Init(void),然后就可以条用Read_Single_Block或者Write_Single_Block进行读写操作

注意:

进行写操作时,最好不要写前700个扇区,应为这些扇区都是FAT文件系统的重要扇区,一旦误写则可能会导致SD无法被电脑识别,需格式化。

/*******************************************************

文件名:

sd_drive.c

作用:

用户API函数,包括四个函数,

          读取一块扇区(512字节)U8Read_Single_Block(U32blk_addr,U8*rx_buf)

          写一个扇区(512字节)U8Write_Single_Block(U32blk_addr,U8*tx_buf)

          获取SD卡基本信息,即读CSD寄存器信息(16字节):

voidSD_info()

          SD卡初始化:

U8SD_Init(void)

********************************************************/

/********************************************

功能:

读取一个block

输入:

blk_addr为第几个block,rx_buf为数据缓存区首地址

输出:

返回NO_ERR则成功,其它则读取失败

********************************************/

U8Read_Single_Block(U32blk_addr,U8*rx_buf)

{

U16rsp=1;

U8i=0;

SD_sel();     //使能SD卡

while(rsp&&(i<100))

{

  write_cmd(CMD17,blk_addr<<9);//写命令CMD17

  rsp=Get_rsp(R1);    //获取答应

  send_clk();

}

if(i>99)     //如果命令超时,则执行超时处理     

{

  SD_desel();

  Uart_Printf("failinwritingCMD17\n");

  returnWR_SGL_BLK_ERR;

}

spi_ro_mode();

send_clk();        //发送8个clk

read_data(rx_buf);//读取512字节

SD_desel();   

Uart_Printf("succeedinreadingthe%dstblock!

!

!

\n",blk_addr);

returnNO_ERR;

}

/********************************************

功能:

写一个block

输入:

blk_addr为要写第几个block,tx_buf为数据区

输出:

返回NO_ERR则成功,其它则读取失败

********************************************/

U8Write_Single_Block(U32blk_addr,U8*tx_buf)

{

U16rsp=1;

U8i=0;

SD_sel();     //使能SD卡

while(rsp&&(i<100))

{

  write_cmd(CMD24,blk_addr<<9);//写命令CMD24

  rsp=Get_rsp(R1);    //获取答应

  send_clk();

}

if(i>99)     //如果命令超时,则执行超时处理     

{

  SD_desel();

  Uart_Printf("failinwritingCMD17\n");

  returnWR_SGL_BLK_ERR;

}

spi_ro_mode();

send_clk();         //发送8个clk

write_data(tx_buf);//读取512字节

SD_desel();   

Uart_Printf("succeedinwritingablock!

!

!

\n");

returnNO_ERR;

}

/********************************************

功能:

SD卡初始化

输入:

输出:

返回NO_ERR则成功,其它则读取失败

********************************************/

U8SD_Init(void)

{

U16rsp=1;

U8i=0;

spi_port_init();//初始化spi端口

spi_low_speed();//初始化时SPI的速度必须低于400khz

spi_ro_mode();  //只读模式

SD_sel();   //选择SD卡

for(i=0;i<10;i++)  //发送至少75个clk

  send_clk();  

while(rsp&&(i++<100))

{

  write_cmd(CMD0,0);  //写命令CMD0

  rsp=Get_rsp(R1);   //获取答应

  if(rsp==1)   //rsp为0则初始化成功,为1则继续写CMD0

   break;

  send_clk();

}

SD_desel();

if(i>99)              //初始化超时处理

{

  Uart_Printf("failinwritingCMD0!

!

!

\n");

  returnINIT_FAIL;

}

i=0;

SD_sel();

while(rsp&&(i++<100))

{

  write_cmd(CMD1,0);//写CMD1

  rsp=Get_rsp(R1);//获取答应

  send_clk();

}

SD_desel();

if(i>99)

{

  Uart_Printf("failinwritingCMD1!

!

!

\n");

  returnINIT_FAIL;

}

Uart_Printf("SDcardinitOK!

!

!

\n");

spi_high_speed();       //初始化工作全部完毕,SPI进入模式模式

spi_rt_mode();    

returnNO_ERR;

}

/********************************************

功能:

获取SD卡信息

输入:

输出:

********************************************/

voidSD_info()

{

U8rsp=0;

U8csd[16];

SD_sel();

write_cmd(CMD9,0);

rsp=Get_rsp(R1);

if(rsp!

=0)

{

  SD_desel();

  Uart_Printf("erroringettingSDinfo!

!

!

\n");

  return;//GET_INFO_ERR;

}

if(read_register(16,csd)!

=NO_ERR)

{

  SD_desel();

  return;

}

SD_desel();

  

Uart_Printf("SDinformation:

\n");

if(csd[0]&0x40==0x40)

{

  Uart_Printf("version2.0\n");

  Uart_Printf("sizeis:

%d\n",1024*(csd[8]<<8+csd[9]));

}

  else

  {

   Uart_Printf("version1.x\n");

   Uart_Printf("sizeis:

%dMByte\n",((((csd[6]&0x03)<<10)|(csd[7]<<2)|((csd[8]&0xC0)>>6)+1)*(1<<((((csd[9]&0x03)<<1)|((csd[10]&0x80)>>7))+2)))>>11);

  }

Uart_Printf("maxblocklenghtis:

%d\n",1<<(csd[5]&0x0f));  

}

/****************************************************************************

文件名:

sd_cmd.c

作用:

中间层函数

****************************************************************************/

/********************************************

功能:

向SD写入一个命令

输入:

cmd为命令,addr为SD卡片内地址

输出:

********************************************/

voidwrite_cmd(U8cmd,U32addr)

{

U8i=0;

U8temp[4];

spi_rt_mode();  //spi发送与接收模式

if(cmd<=13)  //前13个命令与地址无关

{

  spi_write_byte((cmd&0x3F)|0x40);     //命令最高两位必须是01

  for(i=0;i<4;i++)      //发送4个0,协议规定的

   spi_write_byte(0);

  if(cmd==0)                            

   spi_write_byte(0x95);   //如果是CMD0,则要发送CRC校正

   elsespi_write_byte(0xff);  //非CMD0,则无需CRC校正,默认为0xFF

}

  else

  {

   for(i=0;i<4;i++)           //将32位的地址分割成4个字节,准备发送

    temp[i]=(char)(addr>>(24-8*i));

   spi_write_byte((cmd&0x3F)|0x40);//命令最高两位必须是01

   for(i=0;i<4;i++)

    spi_write_byte(temp[i]);   //发送地址,共4个字节

   spi_write_byte(0xff);     //非CMD0,则无需CRC校正,默认为0xFF    

  }

}

/********************************************

功能:

获取SD卡的答应字节,可能是一个或者两个字节

输入:

type为答应类型

输出:

答应字节,个数有答应类型而定

********************************************/

U16Get_rsp(U8type)

{

U16rsp,temp;

spi_ro_mode();   //spi只读模式

send_clk();     //先发送8个clk

rsp=spi_read_byte();  //用spi读取答应字节

if(rsp&0x8)    

  rsp=spi_read_byte();

if(type==R2)     //如果是R2类型,则答应为两个字节,须再次读取

{

  temp=rsp<<8;

  rsp=spi_read_byte();

  rsp=temp|rsp;   

}

returnrsp;

}

/********************************************

功能:

读取SD的一个block的内容,一般为512字节

输入:

buffer为数据缓存区头地址

输出:

********************************************/

voidread_data(U8*buffer)

{

U32i;

U8rsp=0;

while(!

(rsp==0xfe))           //答应字节的最低为0则代表起始位

  rsp=spi_read_byte();

for(i=0;i

  buffer[i]=spi_read_byte();

for(i=0;i<2;i++)   //读两个CRC校正码

  send_clk();

send_clk();      //读结束字节

}

/********************************************

功能:

写入SD的一个block的内容,一般为512字节

输入:

buffer为数据缓存区头地址

输出:

********************************************/

U8write_data(U8*buffer)

{

U16rsp=0,tmp=0,busy=0,i=6;

spi_rt_mode();

spi_write_byte(0xfe);   //起始位

for(i=0;i<512;i++)  //发送512个字节

  spi_write_byte(buffer[i]);

for(i=0;i<2;i++)   //发送16位的CRC校正

  spi_write_byte(0xff);

spi_ro_mode();     //等待答应

while(!

(rsp==0x1))

{

  rsp=(U16)spi_read_byte();

  tmp=rsp;

  rsp&=0x11;

}

while(!

(busy==0xff))   //判忙

{

  busy=spi_read_byte();

}

tmp&=0xe;

if(tmp==4)

  returnNO_ERR;

  else

  {

   Uart_Printf("writingerror!

!

!

\n");

   returnWR_SGL_BLK_ERR;

  }

}

/********************************************

功能:

输入:

输出:

********************************************/

U8read_register(U8len,U8*buffer)

{

U8rsp=0xff,i=0;

spi_ro_mode();

while((rsp==0xff)&&(i<100))

{

  rsp=spi_read_byte();

}

if(i>99)

{

  Uart_Printf("ERRinreaddingregister!

!

!

\n");

  returnrsp;

}

if(rsp!

=0xfe)

{

  buffer[0]=rsp;

  i=1;

}

  else

   i=0;

for(;i

  buffer[i]=spi_read_byte();

for(i=0;i<2;i++)

  send_clk();

send_clk();

returnNO_ERR;

}

/*******************************************************************

文件名:

sd_hard.c

作用:

硬件层函数,移植时需根据处理器或者硬件结构的不同,对该文件的函数进行修改

********************************************************************/

/********************************************

功能:

使能SPI,发送CLK

输入:

输出:

********************************************/

voidsend_clk()

{

rSIOCON|=(1<<3);            //使能SPI

while(!

(rINTPND&BIT_SIO));  //等待发送完毕

rI_ISPC|=BIT_SIO;     //清除中断标志

}  

/********************************************

功能:

用SPI发送一个字节

输入:

dat为要发送的字节

输出:

********************************************/

voidspi_write_byte(U8dat)

{

rSIODAT=dat;

send_clk();  //SPI发送          

}

/********************************************

功能:

用SPI读取外设一个字节

输入:

输出:

读到的一个字节

********************************************/

U8spi_read_byte(void)

{

send_clk();  //SPI发送

returnrSIODAT;

}

/********************************************

功能:

初始化SPI的端口

输入:

输出:

********************************************/

voidspi_port_init()     

{

rIVTCNT=0;       

rPCONF=(rPCONF&0xe3ff)|0x1B0C00;//除了CLK,MISO,MOSI外,不改变其他位

rPUPF|=0x160;                       //使能MISO的上拉电阻

}

/***************************************************************

文件名:

sd_config.h

作用:

相关功能的宏定义,以便被以上三个文件调用,便于移植

         移植时需修改

***************************************************************/

#ifndef_SD_CONG

#define_SD_CONG

#defineBLOCK_LEN  (512)  //一个block的长度

#defineCMD00

#defineCMD11  //读OCR寄存器

#defineCMD99  //读CSD寄存器

#defineCMD1010//读CID寄存器

#defineCMD1212//停止读多块时的数据传输

#defineCMD1313//读Card_Status寄存器

#defineCMD1616//设置块的长度

#defineCMD1717//读单块

#defineCMD1818//读多块,直至主机发送CMD12

#defineCMD2424//写单块

#defineCMD2525//写多块

#defineCMD2727//写CSD寄存器

#defineCMD2828//Setthewriteprotectionbitoftheaddressedgroup

#defineCMD2929//Clearthewriteprotectionbitoftheaddressedgroup

#defineCMD3030//Askthecardforthestatusofthewriteprotectionbits

#defineCMD3232//设置擦除块的起始地址

#defineCMD3333//设置擦除块的终止地址

#defineCMD3838//擦除所选择的块

#defineCMD4242//设置/复位密码或上锁/解锁卡

#defineCMD5555//禁止下一个命令为应用命令

#defineCMD5656//应用命令的通用I/O

#defineCMD5858//读OCR寄存器

#defineCMD5959//使能或禁止

//错误返回

#defineINIT_FAIL  0

#defineNO_ERR   1

#defineWR_SGL_BLK_ERR2

#defineGET_INFO_ERR3

#defineR11//SD卡答应类型,表示一个字节

#defineR22//SD卡答应类型,表示两个字节

//一下是移植时需修改的内容

#defineSD_desel()rPDATE=0x20;//使能SD卡

#defineSD_sel()rPDATE=0x00;     //放开SD卡

#definespi_high_speed()rSBRDR=5;  //spi高速模式

#definespi_l

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1