新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機讀寫SD卡最簡單最基本的程序

        單片機讀寫SD卡最簡單最基本的程序

        作者: 時間:2016-11-25 來源:網絡 收藏
          卡最簡單最基本的程序
        />
        />  2010-11-01 21:14

          轉載自 刀禁凱森

          最終編輯 zlulu2008

          處理器: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無法被電腦識別,需格式化。

          

          

          U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf)

          {

          U16 rsp = 1;

          U8 i = 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("fail in writing CMD17");

          return WR_SGL_BLK_ERR;

          }

          spi_ro_mode();

          send_clk(); //發送8個clk

          read_data(rx_buf); //讀取512字節

          SD_desel();

          Uart_Printf("succeed in reading the %dst block!!!", blk_addr);

          return NO_ERR;

          }

          

          U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf)

          {

          U16 rsp = 1;

          U8 i = 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("fail in writing CMD17");

          return WR_SGL_BLK_ERR;

          }

          spi_ro_mode();

          send_clk(); //發送8個clk

          write_data(tx_buf); //讀取512字節

          SD_desel();

          Uart_Printf("succeed in writing a block!!!");

          return NO_ERR;

          }

          

          U8 SD_Init(void)

          {

          U16 rsp = 1;

          U8 i = 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則初始化成功http://www.tea176.com,為1則繼續寫CMD0

          break;

          send_clk();

          }

          SD_desel();

          if (i > 99) //初始化超時處理

          {

          Uart_Printf("fail in writing CMD0!!!");

          return INIT_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("fail in writing CMD1!!!");

          return INIT_FAIL;

          }

          Uart_Printf("SD card init OK!!!");

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

          spi_rt_mode();

          return NO_ERR;

          }

          

          void SD_info()

          {

          U8 rsp=0;

          U8 csd[16];

          SD_sel();

          write_cmd(CMD9, 0);

          rsp = Get_rsp(R1);

          if (rsp != 0)

          {

          SD_desel();

          Uart_Printf("error in getting SD info!!!");

          return ;//GET_INFO_ERR;

          }

          if (read_register(16, csd) != NO_ERR)

          {

          SD_desel();

          return ;

          }

          SD_desel();

          Uart_Printf("SD information :");

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

          {

          Uart_Printf("version 2.0");

          Uart_Printf("size is : %d",1024 * (csd[8]<<8 + csd[9]));

          }

          else

          {

          Uart_Printf("version 1.x ");

          Uart_Printf("size is : %d MByte", ((((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("max block lenght is : %d",1<<(csd[5]&0x0f));

          }

          

          

          void write_cmd(U8 cmd, U32 addr)

          {

          U8 i = 0;

          U8 temp[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校正

          else spi_write_byte(0xff); //非CMD0,則無需CRC校正,默認為0xFF

          }

          else

          {

          for(i = 0; i < 4; i++) //將32位的地址分割成4個字節,準備發送

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

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

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

          spi_write_byte(temp); //發送地址,共4個字節

          spi_write_byte(0xff); //非CMD0,則無需CRC校正,默認為0xFF

          }

          }

          

          U16 Get_rsp(U8 type)

          {

          U16 rsp, 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;

          }

          return rsp;

          }

        上一頁 1 2 下一頁

        關鍵詞: 單片機讀寫SD

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 长子县| 铁岭县| 美姑县| 镇坪县| 潮安县| 叶城县| 仁寿县| 蒲江县| 洛阳市| 衡水市| 许昌县| 桂东县| 南木林县| 都昌县| 子洲县| 陕西省| 安多县| 吉木萨尔县| 恩施市| 南乐县| 鹤山市| 噶尔县| 大新县| 潞西市| 策勒县| 灵台县| 小金县| 荥经县| 萨迦县| 临泉县| 招远市| 湟中县| 南丰县| 白沙| 黎川县| 澄迈县| 荃湾区| 汤原县| 巴中市| 和静县| 北票市|