<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STC52單片機(jī)的SD卡底層驅(qū)動(dòng)——SPI

          STC52單片機(jī)的SD卡底層驅(qū)動(dòng)——SPI

          作者: 時(shí)間:2016-11-22 來源:網(wǎng)絡(luò) 收藏

          最近在做SD卡以及單片機(jī)上的FAT32文件系統(tǒng),這個(gè)是我參考別人的源程序以后寫出來的自己的SD卡驅(qū)動(dòng),如有不完整的地方,還望大家不吝指教。

          本文引用地址:http://www.ex-cimer.com/article/201611/319664.htm

          定義聲明:

          #ifndef _SD_H_
          #define _SD_H_

          #include

          sbit SD_CS=P2^7; //SD卡片選信號(hào)
          sbit SD_SI=P2^6; //SD卡數(shù)據(jù)輸入
          sbit SD_SCL=P2^5; //SD卡時(shí)鐘信號(hào)
          sbit SD_SO=P2^4; //SD卡數(shù)據(jù)輸出

          #define DELAY_TIME 100 //SD卡的復(fù)位與初始化時(shí)SPI延時(shí)
          #define TRY_TIME 200 //SD卡寫入命令以后,讀取SD卡的回應(yīng)次數(shù)


          #define INIT_CMD0_ERROR 0x01 //CMD0錯(cuò)誤
          #define INIT_CMD1_ERROR 0x02//CMD1錯(cuò)誤
          #define WRITE_BLOCK_ERROR 0x03//寫塊錯(cuò)誤
          #define READ_BLOCK_ERROR 0x04//讀塊錯(cuò)誤


          unsigned char SD_Reset();
          unsigned char SD_Init();
          unsigned char SD_Write_Sector(unsigned long addr,unsigned char *buffer);
          unsigned char SD_Read_Sector(unsigned long addr,unsigned char *buffer);

          #endif

          代碼實(shí)現(xiàn):

          #include"SD.h"
          #include"myfun.h"

          unsigned char Is_init;

          unsigned char bdata _dat;
          sbit _dat7 = _dat^7;
          sbit _dat6 = _dat^6;
          sbit _dat5 = _dat^5;
          sbit _dat4 = _dat^4;
          sbit _dat3 = _dat^3;
          sbit _dat2 = _dat^2;
          sbit _dat1 = _dat^1;
          sbit _dat0 = _dat^0;



          void SD_spi_write(unsigned char x)
          {
          _dat=x;

          SD_SI = _dat7;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat6;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat5;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat4;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat3;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat2;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat1;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          SD_SI = _dat0;
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL=1;
          if(Is_init) Delay20us(DELAY_TIME);

          }

          unsigned char SD_spi_read()
          {
          SD_SO = 1;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat7 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat6 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat5 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat4 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat3 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat2 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat1 = SD_SO;

          SD_SCL = 1;
          if(Is_init) Delay20us(DELAY_TIME);
          SD_SCL = 0;
          if(Is_init) Delay20us(DELAY_TIME);
          _dat0 = SD_SO;

          return(_dat);
          }

          unsigned char SD_Write_Cmd(unsigned char *pcmd)
          {
          unsigned char temp,time=0;

          SD_CS=1;
          SD_spi_write(0xff); //提高程序的兼容性
          SD_CS=0;

          SD_spi_write(pcmd[0]);
          SD_spi_write(pcmd[1]);
          SD_spi_write(pcmd[2]);
          SD_spi_write(pcmd[3]);
          SD_spi_write(pcmd[4]);
          SD_spi_write(pcmd[5]);
          do
          {
          temp = SD_spi_read();
          time++;
          }
          while((temp==0xff)&&(timereturn(temp);
          }

          unsigned char SD_Reset()
          {
          unsigned char time,temp,i;
          unsigned char pcmd[] = {0x40,0x00,0x00,0x00,0x00,0x95};

          Is_init = 1;

          SD_CS = 1; //關(guān)閉片選
          for(i=0;i<0x0f;i++){
          SD_spi_write(0xff); //補(bǔ)充120個(gè)時(shí)鐘,喚醒SPI
          }
          SD_CS = 0; //打開片選
          time=0;
          do{
          temp=SD_Write_Cmd(pcmd);//寫入CMD0
          time++;
          if(time==TRY_TIME){
          SD_CS = 1; //關(guān)閉片選
          return(INIT_CMD0_ERROR); //CMD0 寫入失敗
          }
          }while(temp!=0x01);

          SD_CS = 1; //關(guān)閉片選

          SD_spi_write(0xff);//補(bǔ)充8個(gè)時(shí)鐘,提高兼容性

          return 0 ; //返回0,復(fù)位操作成功
          }

          unsigned char SD_Init()
          {
          unsigned char time,temp;
          unsigned char pcmd[] = {0x41,0x00,0x00,0x00,0x00,0xff};
          SD_CS = 0; //打開片選

          time = 0;
          do{
          temp = SD_Write_Cmd(pcmd);
          time++;
          if(time==TRY_TIME){ //CMD1寫入失敗
          SD_CS=1;
          return(INIT_CMD1_ERROR);
          }
          }while(temp!=0);

          Is_init = 0; //講Is_init設(shè)置為0,提高SPI速度
          SD_CS = 1;//關(guān)閉片選
          SD_spi_write(0xff); //補(bǔ)充8個(gè)時(shí)鐘
          return(0);
          }



          unsigned char SD_Write_Sector(unsigned long addr,unsigned char *buffer)
          {
          unsigned char temp,time;
          unsigned int i;
          unsigned char pcmd[]={0x58,0x00,0x00,0x00,0x00,0xff};

          addr<<=9;
          pcmd[1] = ((addr&0xff000000)>>24);
          pcmd[2] = ((addr&0x00ff0000)>>16);
          pcmd[3] = ((addr&0x0000ff00)>>8);

          SD_CS = 0;
          time = 0;

          do{
          temp=SD_Write_Cmd(pcmd);//寫入CMD0
          time++;
          if(time == TRY_TIME)
          {
          SD_CS = 1; //關(guān)閉片選
          return(temp); //寫入失敗
          }
          }while(temp!=0);

          for(i=0;i<100;i++) //插入若干個(gè)字節(jié)的時(shí)鐘,保持穩(wěn)定性
          {
          SD_spi_write(0xff);
          }

          SD_spi_write(0xfe); //寫入0xfe,后面就是要寫入的數(shù)據(jù)

          for(i=0;i<512;i++)
          {
          SD_spi_write(buffer[i]);
          }

          SD_spi_write(0xff); //兩個(gè)字節(jié)的CRC校驗(yàn)碼
          SD_spi_write(0xff);

          temp = SD_spi_read(); //讀取返回值
          if((temp&0x1f)!=0x05){
          SD_CS = 1;
          return(WRITE_BLOCK_ERROR); //寫塊數(shù)據(jù)失敗
          }
          while(SD_spi_read()!=0xff);//SD卡忙狀態(tài),等待

          SD_CS = 1;

          SD_spi_write(0xff);//補(bǔ)充8個(gè)時(shí)鐘
          return(0);

          }


          unsigned char SD_Read_Sector(unsigned long addr,unsigned char *buffer)
          {
          unsigned int j;
          unsigned char time,temp;
          unsigned char pcmd[]={0x51,0x00,0x00,0x00,0x00,0xff}; //CMD17的字節(jié)序列

          addr<<=9; //addr=addr*512 將塊地址(扇區(qū)地址)轉(zhuǎn)為字節(jié)地址

          pcmd[1]=((addr&0xff000000)>>24);//將字節(jié)地址寫入到CMD17字節(jié)序列中
          pcmd[2]=((addr&0x00FF0000)>>16);
          pcmd[3]=((addr&0x0000FF00)>>8);

          SD_CS=0;//打開片選

          time=0;
          do{
          temp = SD_Write_Cmd(pcmd);
          time++;
          if(time==TRY_TIME){
          return(READ_BLOCK_ERROR);
          }
          }while(temp!=0);

          while(SD_spi_read()!=0xfe); //讀到0xfe,說明后面是512字節(jié)的數(shù)據(jù)

          for(j=0;j<512;j++)
          {
          buffer[j]=SD_spi_read();
          }

          SD_spi_read(); //讀取兩個(gè)字節(jié)的CRC校驗(yàn)碼
          SD_spi_read();

          SD_CS=1;

          SD_spi_write(0xff); //補(bǔ)充8個(gè)時(shí)鐘

          return 0;

          }



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();