欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

自編基于51單片機的sD卡程序

作者:佚名   來源:本站原創   點擊數:  更新時間:2012年01月08日   【字體:
#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

    //錯誤碼定義//

#define cmd0_error 0x01

#define cmd1_error 0x02

#define write_error 0x03

#define read_error 0x04

    /*位定義*/

sbit so=P1^0; //定義主機接收位

sbit clk=P1^1;    //定義時鐘位

sbit si=P1^2; //定義主機發送數據位

sbit cs=P1^3; //定義片選位

uchar xdata shuju[512]={0};     //定義數據緩沖數組

uchar flag_time;         

//定義標志時間,因為當sd卡進行初始化時需要降低

//通信速度,所以通過該標志來寫1來降低速度

void delay(uint x)       //通信延時函數

{

    while(x--)

    _nop_();

}

void delay1(uint a)     

{

    uint i,j;

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

        for(j=0;j<120;j++);

}

//寫一字節數據//

void write_sd(uchar date)  

{

    uchar i;

    CY=0;

    clk=1;

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

    {

        clk=0;

        date=date<<1;

        si=CY;

        if(flag_time==1)  //用來判斷是否處于初始化,如果是降低通信速度

        delay(10);

        _nop_();   //用來讓io口數據更穩定,也可以省略

        clk=1;

        _nop_();

        if(flag_time==1)

        delay(10);

    }

}

//讀取sd卡一個字節數據//

uchar read_sd()      

{

    uchar i,temp=0;

    so=1;          //一定要先將其置1否則會出現錯誤

    //因為如果先置0單片機io口寄存器相應位電平為低當

    //當接收到高電平后可能sd卡電平不足使其io變為高電平

    clk=1;

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

    {

        clk=0;

        if(flag_time==1)

        delay(10);

        temp<<=1;

        temp=temp|so;

        _nop_();

        clk=1;

        _nop_();

        if(flag_time==1)

        delay(10);

    }

    return temp;

}

//向sd卡寫命令//

uchar write_cmd(uchar *cmd)

{

    uchar i,time,temp;  

    si=1;

    for(i=0;i<6;i++)  //發送六字節命令

    {

        write_sd(cmd[i]);

    }

    time=0;

    do

    {  

        temp=read_sd();

        time++;

    }

    while((temp==0xff)&&(time<100));

    //判斷命令是否寫入成功,當讀取到so不為0xff時命令寫入成功

    //當temp==0xff時為真且沒發送100次為真繼續執行

    //但是又不能無限制等待所以讓命令寫入100次結束

    return temp;      //返回讀取的數據

}

//復位函數//

uchar sd_reset()

{

    uchar i,temp=0xff,time;

    uchar table[]={0x40,0x00,0x00,0x00,0x00,0x95};

    flag_time=1;

    cs=1;

    for(i=0;i<0x0f;i++)      //復位時最少寫入74個時鐘周期

    {

        write_sd(0xff);

    }  

    cs=0;

    time=0;//打開片選

    do

    {

        temp=write_cmd(table);   //寫入cmd0

        time++;

        if(time==100)

        return(cmd0_error);

    }

    while(temp!=0x01);       //等待命令CMD0的響應

    cs=1;                  //關閉片選

    write_sd(0xff);           //補償8個時鐘

    return 0;

}

//初始化函數此函數決定SD卡的工作模式 選擇SPI還是SD模式//

uchar sd_init()

{

    uchar time=0,temp=0xff;

    uchar table[]={0x41,0x00,0x00,0x00,0x00,0xff};       //命令碼

    flag_time=1;

    cs=0;

    time=0;

    do

    {

        temp=write_cmd(table);

        time++;

        if(time==100)

        return 0x02;

    }

    while(temp!=0x00);       //等待命令CMD1響應

    flag_time=0;

    cs=1;

    write_sd(0xff);           //補償8個時鐘

    return 0;

}

//寫sd卡扇區//

uchar xie_sd_shanqu(unsigned long int add,uchar *buffer)

{

    uchar temp,time;

    uint i;

    uchar table[]={0x58,0x00,0x00,0x00,0x00,0xff};

    add=add<<9;       //add=add*512

    //由于sd卡操作一次性只能寫一個扇區也就是512個字節

    //所以這里通過將長整型地址左移九位來將地址乘上512

    //用于地址操作

    table[1]=((add&0xff000000)>>24);

    table[2]=((add&0x00ff0000)>>16);

    table[3]=((add&0x0000ff00)>>8);

    cs=0;

    time=0;

    do

    {

        temp=write_cmd(table);       //寫入寫扇區命令

        time++;

        if(time==100)

        {

            return(write_error);

        }

    }

    while(temp!=0x00);               //判斷命令是否寫入成功成功時返回0x00

    for(i=0;i<20;i++)     //補充若干時鐘

    {

        write_sd(0xff);

    }

    write_sd(0xfe);       //寫入開始字節0xfe,后面要寫入512字節數據

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

    {

        write_sd(buffer[i]);

    }

    write_sd(0xff);  

    write_sd(0xff);           //兩字節奇偶校驗

 

    temp=read_sd();           //讀取返回值

    if((temp&0x1f)!=0x05)        //如果返回值是 xxx00101 說明數據已經被寫入

    {

        cs=1;

        return(write_error);

    }

    while(read_sd()!=0xff);          //等待sd卡不忙 數據寫入成功

    cs=1;                  //關閉片選

    write_sd(0xff);           //補償8 個時鐘

    return 0;

}

//讀取sd卡扇區//

uchar duqushanqu(unsigned long add,uchar *buffer)

{

    uchar temp,time=0;

    uint i;

    uchar  table[]={0x51,0x00,0x00,0x00,0x00,0xff};

    add=add<<9;

    table[1]=((add&0xff000000)>>24);

    table[2]=((add&0x00ff0000)>>16);

    table[3]=((add&0x0000ff00)>>8);

    cs=0;                          //打開片選

    do

    {

        temp=write_cmd(table);       //寫命令

        time++;

        if(time==100)

        {

            return read_error;

        }

    }

    while(temp!=0);

    write_sd(0xff);               //補償8個時鐘

    while(read_sd()!=0xfe);      //一直讀取等待0xfe

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

    {

        buffer[i]=read_sd();

    }

    write_sd(0xff);           //兩字節奇偶校驗位

    write_sd(0xff);

    cs=1;

    write_sd(0xff);           //補償8個時鐘

    return 0;

}

/*在P0上接八個發光二極管用來顯示讀取到的數據

首先在數組(shuju)里面放入i用于顯示,再將其

寫入SD卡扇區,然后在讀取出SD卡里的數據*/

void main()

{

    uint i=0;

    P2=0x00;

    P0=0xff;

    sd_reset();  

    sd_init();     ///初始化sd卡

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

    {

        shuju[i]=i;           //向數據數組里面寫入數據

    }

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

    {

        xie_sd_shanqu(1,shuju);      //將數據數組里面的數據寫入sd卡

    }

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

    {

        shuju[i]=0;           //清零數據數組用來存儲從sd卡讀取到的數據

    }         

    duqushanqu(1,shuju);     //讀取扇區數據

    while(1)

    {

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

        {

            P0=shuju[i];      //顯示扇區數據

            delay1(200);

        }

    }

}
關閉窗口

相關文章