乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      深入理解SD卡基礎(chǔ)原理以及內(nèi)部結(jié)構(gòu)的總結(jié)

       昵稱1325155 2010-09-19
      1、 簡介:
      SD卡(Secure Digital Memory Card)是一種為滿足安全性、容量、性能和使用環(huán)境等各方面的需求而設(shè)計的一種新型存儲器件,SD卡允許在兩種模式下工作,即SD模式和SPI模式,本 系統(tǒng)采用SPI模式。本小節(jié)僅簡要介紹在SPI模式下,STM32處理器如何讀寫SD卡,如果讀者如希望詳細(xì)了解SD卡,可以參考相關(guān)資料。
      SD 卡內(nèi)部結(jié)構(gòu)及引腳如下圖所示:

       

      點擊看大圖

      SD卡內(nèi)部圖.JPG



      2、SD卡管腳圖:
      點擊看大圖

      SD卡圖.JPG



      3、SPI模式下SD各管腳名稱為:
      sd 卡:
      點擊看大圖

      SPI模式下SD各管腳名稱 為.JPG



      注: 一般SD有兩種模式:SD模式和SPI模式,管腳定義如下:
      (A)、SD MODE 1、CD/DATA3   2、CMD 3、VSS1 4、VDD 5、CLK 6、VSS2 7、DATA0 8、DATA1 9、DATA2
      (B)、SPI MODE 1、CS             2、DI 3、VSS 4、VDD 5、SCLK 6、VSS2 7、DO           8、RSV 9、RSV

      SD 卡主要引腳和功能為:
      CLK:時鐘信號,每個時鐘周期傳輸一個命令或數(shù)據(jù)位,頻率可在0~25MHz之間變化,SD卡的總線管理器可以不受任何限制的自由產(chǎn)生0~25MHz 的頻率;
      CMD:雙向命令和回復(fù)線,命令是一次主機到從卡操作的開始,命令可以是從主機到單卡尋址,也可以是到所有卡;回復(fù)是對之前命令的回答,回復(fù)可以來自單 卡或所有卡;
      DAT0~3:數(shù)據(jù)線,數(shù)據(jù)可以從卡傳向主機也可以從主機傳向卡。
      SD卡以命令形式來控制SD卡的讀寫等操作??筛鶕?jù)命令對多塊或單塊進行讀寫操作。在SPI模式下其命令由6個字節(jié)構(gòu)成,其中高位在前。SD卡命令 的格式如表1所示,其中相關(guān)參數(shù)可以查閱SD卡規(guī)范。


      4、MicroSD卡管腳圖:
      點擊看大圖

      MicroSD卡管腳圖.JPG


      5、MicroSD卡管腳名稱:
      點擊看大圖

      MicroSD卡管腳名 稱.JPG



      SD 卡與MicroSD卡僅僅是封裝上的不同,MicroSD卡更小,大小上和一個SIM卡差不多,但是協(xié)議與SD卡相同。
      一般我們用單片機操作SD 卡時,都不需要對FAT分區(qū)表信息做處理,原因如下:
      1)、操作FAT分區(qū)表要增加程序代碼量、增加SRAM的消耗,對于便攜應(yīng)用來說代碼大小和 占用SRAM的多少至關(guān)重要。
      2)、即使我們對FAT分區(qū)表不做任何了解,實際上我們一樣可以向SD卡上寫入數(shù)據(jù),這就表明使用FAT對我們做數(shù) 據(jù)存儲應(yīng)用來說如同雞肋。
      3)、耗費大量經(jīng)歷和時間去了解FAT分區(qū)表對于我們做嵌入式軟件開發(fā)的人來說有些得不償失。
      4)、SD卡支持 兩種操作模式,SD模式和SPI模式,SPI模式做SD數(shù)據(jù)操作時根本不需要知道FAT,這時候SD卡對于我們來說實際上就是個大的、快速的、方便的、容 量可變的外部存儲器。
      基于以上原因,一般情況下對SD卡的操作只需要了解SPI通訊就可以了,而現(xiàn)在大部分單片機都有SPI接口,那么操作SD卡 易如反掌。


      以下是做SD卡試驗時使用的電路圖:
      點擊看大圖

      SD卡試驗時使用的電路 圖.JPG


      SD_CS/ 連接到單片機的片選SD管腳,只有單片機設(shè)置SD_CS/為低電平時才可以操作SD卡。
      MOSI連接單片機SPI總線的MOSI管腳(SPI數(shù)據(jù) 輸入),單片機從這個管腳讀取SD卡內(nèi)的數(shù)據(jù)。
      MISO連接單片機SPI總線的MISO管腳(SPI數(shù)據(jù)輸出)、單片機通過這個管腳向SD卡內(nèi)寫 入數(shù)據(jù)。
      SCK連接單片機SPI總線的SCK(SPI時鐘)
      SD管腳實際上在SD卡內(nèi)部連接到了GND,當(dāng)SD插座上沒插入SD卡時,單 片機從這個管腳能讀到高電平(前提是使用單片機內(nèi)部上拉輸入,或者外部增加一個上拉電阻),一旦插入SD卡,這個管腳就變成低電平,這個功能用來檢測是否 插入SD卡。
      RSV1和RSV2是保留功能管腳,不需要操作。
      MicroSD卡的連接和SD卡大同小異,只是MicroSD卡比SD卡少 一個GND管腳,所以不能使用上面做的這種插入卡的檢測,實際上現(xiàn)在很多SD卡/MicroSD卡插座都有插入檢測管腳,當(dāng)然,一分錢一分貨,價格上當(dāng)然 也要貴一些
      順便提一下,普通SD卡插座最多5塊錢。

      SPI命令格式

      Byte 1

      Byte2-5

      Byte 6

      7

      6

      5        0

      31       0

      7

      0

      0

      1

      Command

      Command Argument

      CRC

      1


      以下是一個簡單的測試SD卡讀 寫的程序,程序是基于Atmega128單片機編寫的,對于Atmega的其他單片機僅需要做管腳改動就可以使用,其他單片機更改要更大。
      sd.h
      //******************************************************************
      //SPI 各線所占用的端口
      #define SD_SS          PB6                         
      #define SD_SCK         PB1
      #define SD_MOSI        PB2
      #define SD_MISO        PB3
      //******************************************************************

      #define SD_DDR         DDRB
      #define SD_PORT        PORTB
      #define SD_PIN         PINB

      #define SD_SS_H        SD_PORT |= (1<
      #define SDSS_L        SD_PORT &= ~(1<
      #define SD_SCK_H       SD_PORT |= (1<
      #define SD_SCK_L       SD_PORT &= ~(1<
      #define SD_MOSI_H      SD_PORT |= (1<
      #define SD_MOSI_L      SD_PORT &= ~(1<

      #define SD_MISO_IN     (SD_PIN&(1<
      //-------------------------------------------------------------
      // 錯誤號
      //-------------------------------------------------------------
      #define INIT_CMD0_ERROR         0xFF
      #define INIT_CMD1_ERROR         0xFE
      #define WRITE_BLOCK_ERROR       0xFD
      #define READ_BLOCK_ERROR        0xFC
      #define TRUE                    0x01
      //-------------------------------------------------------------
      // MMC/SD 命令(命令號從40開始,只列出基本命令,并沒有都使用)
      //-------------------------------------------------------------
      #define SD_RESET                0x40 + 0                  
      #define SD_INIT                0x40 + 1
      #define SD_READ_CSD            0x40 + 9
      #define SD_READ_CID            0x40 + 10
      #define SD_STOP_TRANSMISSION    0x40 + 12
      #define SD_SEND_STATUS            0x40 + 13
      #define SD_SET_BLOCKLEN        0x40 + 16
      #define SD_READ_BLOCK            0x40 + 17
      #define SD_READ_MULTI_BLOCK    0x40 + 18
      #define SD_WRITE_BLOCK            0x40 + 24
      #define SD_WRITE_MULTI_BLOCK    0x40 + 25

      //片選關(guān)(MMC/SD-Card Invalid)
      #define SD_Disable()   SD_SS_H
      //片選開 (MMC/SD-Card Active)
      #define SD_Enable()    SD_SS_L

      SD_TEST.C
      //****************************************************************************************/
      //ICC-AVR application builder : 03-5-20 8:39:11
      // Target : M128
      // Crystal: 3.6864Mhz

      #include
      #include
      #include 'sd.h'
      void uart0_init(void);
      void putchar(unsigned char content);
      void putstr(unsigned char *s);
      void SD_Port_Init(void);
      unsigned char SD_Init(void);
      unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer);
      unsigned char SD_read_sector(unsigned long addr,unsigned char *Buffer);
      unsigned char SPI_TransferByte(unsigned char byte);
      unsigned char Write_Command_SD(unsigned char cmd,unsigned long address);
      unsigned long SD_find(void);
      //**************************************************************************
      // 串口調(diào)試程序
      //**************************************************************************
      void uart0_init(void)
      {
      UCSR0B = 0x00; //disable while setting baud rate
      UCSR0A = 0x00;
      UCSR0C = 0x06; // 00000110 UART0設(shè)置為異步模式、無奇偶校驗、1位停止位、8位數(shù)據(jù)位
      UBRR0L = 0x17; //set baud rate lo
      UBRR0H = 0x00; //set baud rate hi 設(shè)置UART0口通信速率9600
      UCSR0B = 0x18;
      }
      void putchar(unsigned char content)
      {

      while(!(UCSR0A & (1 << UDRE0))); /*    判斷上次發(fā)送有沒有完成    */
      UDR0 = content;    /*    發(fā)送數(shù)據(jù)    */

      }
      void putstr(unsigned char *s)
      {

      while(*s)
      {
      putchar(*s);
      s++;
      }

      }

      //****************************************************************************
      // 端口初始化
      void SD_Port_Init(void)
      //****************************************************************************
      {
      SD_PORT        |= (1<<
      SD_DDR         |= (1<<<
      SD_DDR         &= ~(1<
      }

      //****************************************************************************
      // 初始化 MMC/SD 卡為SPI模式
      unsigned char SD_Init(void)
      //****************************************************************************
      {
      unsigned char retry,temp;
      unsigned char i;


      SPCR=0x53;                           //設(shè)定SPI為128分頻,慢速進行初始化
      SPSR=0x00;

      for (i=0;i<0x0f;i++)          
      {
      SPI_TransferByte(0xff); //延遲74個以上的時鐘
      }

      SD_Enable();                    //開片選

      SPI_TransferByte(SD_RESET);    //發(fā)送復(fù)位命令
      SPI_TransferByte(0x00);
      SPI_TransferByte(0x00);
      SPI_TransferByte(0x00);
      SPI_TransferByte(0x00);
      SPI_TransferByte(0x95);          

      SPI_TransferByte(0xff);
      SPI_TransferByte(0xff);

      retry=0;
      do{
      temp="Write"_Command_SD(SD_INIT,0);      //發(fā)送初始化命令
      retry++;
      if(retry==100)                             //重試100次
      {
      SD_Disable();                     //關(guān)片選

      return(INIT_CMD1_ERROR);      //如果重試100次失敗返回錯誤號

      }
      }while(temp!=0);                            

      MSD_Disable();                                  //關(guān)片選

      SPCR=0x50;                                        //設(shè)置SPI為2分頻。進行高速讀寫
      SPSR=0x01;

      return(TRUE);                                  //返回成功
      }

      //****************************************************************************
      // 發(fā)送命令給 MMC/SD卡
      //Return: 返回MMC/SD卡對命令響應(yīng)的第2字節(jié),作為命令成功判斷
      unsigned char Write_Command_SD(unsigned char cmd,unsigned long address)
      //****************************************************************************
      {
      unsigned char tmp;
      unsigned char retry="0";

      SD_Disable();
      SPI_TransferByte(0xFF);

      SD_Enable();

      SPI_TransferByte(cmd);                     //將32位地址進行移位作為地址字節(jié)                                    
      SPI_TransferByte(address>>24);
      SPI_TransferByte(address>>16);
      SPI_TransferByte(address>>8);
      SPI_TransferByte(address);
      SPI_TransferByte(0xFF);

      SPI_TransferByte(0xFF);

      do{
      tmp = SPI_TransferByte(0xFF);    //發(fā)送8個時鐘接受最后一個字節(jié)                                                                  
      retry++;
      }while((tmp==0xff)&&(retry<8));
      return(tmp);

      }


      //****************************************************************************
      // 寫一個扇區(qū)(512Byte) to MMC/SD-Card
      //如果寫完成返回TRUE
      unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)
      //****************************************************************************
      {
      unsigned char temp;
      unsigned int i;

      SPI_TransferByte(0xFF);                                    //延遲8個時鐘            
      SD_Enable();                                            //開片選

      temp = Write_Command_MMC(MMC_WRITE_BLOCK,addr<<9);        //發(fā)送寫扇區(qū)命令
      if(temp != 0x00)
      {
      SD_Disable();
      return(temp);
      }

      SPI_TransferByte(0xFF);
      SPI_TransferByte(0xFF);
      SPI_TransferByte(0xFE);

      for (i=0;i<512;i++)
      {
      SPI_TransferByte(*Buffer++); //發(fā)送512字節(jié)數(shù)據(jù)
      }

      //CRC-Byte
      SPI_TransferByte(0xFF); //Dummy CRC
      SPI_TransferByte(0xFF); //CRC Code

      temp = SPI_TransferByte(0xFF);   //讀SD卡運行響應(yīng)
      if((temp & 0x1F)!=0x05)             //如果最后4位為0101,為操作成功。否則為操作失敗。
      {
      SD_Disable();

      return(WRITE_BLOCK_ERROR); //返回錯誤
      }

      while (SPI_TransferByte(0xFF) != 0xFF);

      SD_Disable();
      return(TRUE);                            //返回成功
      }
      //****************************************************************************
      // 讀512字節(jié) from MMC/SD-Card
      //如果成功返回TRUE
      unsigned char SD_read_sector(unsigned long addr,unsigned char *Buffer)
      //****************************************************************************
      {
      unsigned char temp;
      unsigned int i;
      unsigned char data;



      SPI_TransferByte(0xff);                                                

      MMC_Enable();

      temp = Write_Command_SD(SD_READ_BLOCK,addr<<9);//發(fā)送讀扇區(qū)命令

      if(temp != 0x00)
      {
      SD_Disable();

      return(READ_BLOCK_ERROR);                //返回錯誤號               
      }

      while(SPI_TransferByte(0xff) != 0xfe);


      for(i=0;i<512;i++)
      {
      data = SPI_TransferByte(0xff);        //存數(shù)據(jù)

      *Buffer++=data;


      }

      SPI_TransferByte(0xff);                        //讀CRC碼
      SPI_TransferByte(0xff);                        //讀CRC碼

      SD_Disable();

      return(TRUE);                                    //返回成功
      }
      //**************************************************************************
      // 查找數(shù)據(jù)開始標(biāo)志(預(yù)設(shè)DATASTART)根據(jù)實際需要刪改
      //**************************************************************************
      unsigned long SD_find(void)                      
      {    
      unsigned long tmp="400";
      unsigned char data[512];

      do
      {
      SD_read_sector(tmp,data);                    //從0扇區(qū)開始查找
      tmp++;                                        //查找DATASTART      

      }while(!((data[0]=='D')&&(data[1]=='A')&&(data[2]=='T')&&(data[3]=='A')&&(data[4]=='S')&&(data[5]=='T')&&(data[6]=='A')&&(data[7]=='R')&&(data[8]=='T')));
      return tmp;                                    //返回開始標(biāo)志的下一個扇區(qū)
      }    
      //**************************************************************************
      // 發(fā)送一個字節(jié)
      //**************************************************************************
      unsigned char SPI_TransferByte(unsigned char byte)
      {
      SPDR = byte;
      while (!(SPSR & 0x80));                               //檢測線路是否空閑                      
      return SPDR;
      }

      //**************************************************************************
      // 主程序例子
      //**************************************************************************
      void main(void)
      {   
      unsigned long temp;
      unsigned char data[512];
      unsigned char data2[512]={'sssssssssssssssssssssssss'};
      unsigned char comm1[]={'\r\nhello world\r\n'};
      unsigned char comm2[]={'\r\nSD_INIT OK\r\n'};
      uart0_init();
      SD_Port_Init();                     //端口初始化
      if(SD_Init()== 0x01)
      {                                      //SD卡初始化,并讀取返回值
      putstr(comm2);
      }
      temp="SD"_find();                      //查找DATASTART數(shù)據(jù)開始標(biāo)志,返回下一扇區(qū)地址
      SD_read_sector(1001,data);             //讀取temp地址的512字節(jié)數(shù)據(jù),512字節(jié)數(shù)據(jù)存入data數(shù)組
      putstr(data);               
      SD_write_sector(temp,data2);         //將data2數(shù)組512字節(jié)數(shù)據(jù)寫入temp扇區(qū)
      }

      測試程序很簡單,僅僅是做了一下讀寫SD卡的測試。

      關(guān)于SD卡的幾點注意事項。
      1、無論我們愿意不愿意,SD卡每次讀寫數(shù)據(jù)的最小單位是1個扇區(qū),即512個字節(jié)。
      2、SD卡與單片機連接的 SPI總線不能太長,要盡量短。這樣的好處是速度可以更快,也不容易出錯。
      3、雖然我們并不關(guān)心FAT文件表,但是我們?nèi)匀灰P(guān)心SD卡的存儲結(jié)構(gòu),如果我們不想使用PC機來讀取保存在SD卡上的數(shù)據(jù)那我們就不用關(guān)心SD存儲結(jié)構(gòu)了。但,作為一個大容量的可移動存儲設(shè)備,不能用PC機來讀取是個很大的遺憾,我解決這個遺憾的方法如下:
      3-1、因為我不了解FAT復(fù)雜的結(jié)構(gòu),所以我做的程序沒法去按照FAT表的各項功能來進行創(chuàng)建文件、刪除文件、創(chuàng)建目錄等等操作。
      3-2、雖然我們的單片機不能創(chuàng)建文件,但是PC機是可以創(chuàng)建文件的啊!所以我使用PC機將SD卡格式化,之后在SD卡上創(chuàng)建一個大文件,比如我的128M的SD卡上我建立了一個100M的文件。這里需要注意一下,一般使用windows創(chuàng)建文件的功能時是沒有辦法指定創(chuàng)建文件的大小的,空文件就是0個字節(jié)的長度,而我們是需要一個固定長度的文件的,所以我用VC編寫了一個小軟件,這個軟件可以為我創(chuàng)建一個100M長度的空文件,記住,這點很重要:一個固定長度的空文件
      3-3、雖然我們建立了個文件在SD卡上,可是我們因為不去了解FAT表,所以我們一樣不知道這個文件到底位于SD卡的什么地方,不要以為它會在0字節(jié)的地方開始,為了找到這個文件的開始位置,我們可以在建立的那個空文件的開頭寫上幾個字符,比如我程序里面寫的“DATASTART”,接下來我們要做的就是一個扇區(qū)一個扇區(qū)的去找這個幾個特殊的字符,這是個笨方法,但卻是最簡單直觀的方法。這個方法有兩個缺點:a、如果文件建立在整個SD卡的后面,那找到這個文件需要漫長的等待。b、如果碰巧某個文件里面也有我們定義的那個特殊字符串的話,那就亂套了!不過好在我們使用的SD卡一般都是專用的,并不能拿去做其他應(yīng)用,比如從公司copy點文件回家之類的,那就能保證這個SD卡上文件的簡單性,即只有我們需要的那個文件,其他文件并不存在,而且這個文件肯定會從SD卡開始的那些扇區(qū)中的某一個開始。這樣說來的話找到這個字符串也不是那么慢嘛!^_^。不過這里要建議一下,在使用SD卡之前最好用windows將它完全格式話一下。
      3-4、一旦我們找到了我們要寫入文件的起始位置(它一般表示為一個扇區(qū)號),那我們就可以在這個起始扇區(qū)的下一個扇區(qū)寫入數(shù)據(jù)了。
      4、OK,看起來很簡單!有了這種存儲方式我們還需要IIC接口的 EEPROM干嗎呢?

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多