求助,51单片机SPI通信读取SD卡的数据,不成功,显示不出图片

2019-03-24 17:46发布

最近假期在家里玩51单片机,看到有大神做了用51单片机和12864和SD卡模块来播放bad apple 【一个视频】觉得很厉害

自己就想也来尝试下,现在程序弄好了,SD卡程序是在网上找参考别人的。但是并没有用,也不懂错在哪里,问了别人

别人用这个程序是可以实现的,可是我自己就不行 想求各位大神解答一下。另外想问下SD卡模块的 MOSI,MISO是分别

对应DO和DI么?
111.jpg

目前程序烧进去,屏幕就显示乱码。插不插SD卡都是现实乱码
111.jpg

然后程序是这样。。。求大神帮看看哪里有错

#include <reg52.h>
#include <INTRINS.H>
#define uchar unsigned char
#define uint unsigned int
uint i=0;
uchar ints;         //初始化变速标志

sbit lcden=P2^7;
sbit lcdrw=P2^5;
sbit lcdrs=P2^6;
sbit rst=P2^4;
sbit psb=P2^2;           //串/并方式控制

sbit cs =P1^7;          //片选
sbit di =P1^6;         //SD卡数据输入  mosi
sbit clk=P1^5;         //时钟
sbit d0=P1^4;        //SD卡数据输出         miso

uchar xdata table[1024]; //设置片外指针

//错误代码//
#define cmd0        0x01         //复位错误
#define cmd1        0x02           //初始化错误
#define sdw                0x03   //sd写错误
#define sdr                0x0f  //sd读错误

void delay(uchar z)   //LCD延时
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}

void delay2(uint z)
{
  while(z--);
}

/*****************并行基本函数*******************/
void lcd_busy(void)   //忙检测
{
        uchar busy;
    lcdrs=0;lcdrw=1;
         do{
             lcden=1;
                delay2(16);
                 /*_nop_();
                 _nop_();*/
                 busy=P3;
                delay2(15);
                 /*_nop_();
                 _nop_();*/
                 lcden=0;
           }while(busy&0x80);         
}


void write_com(uchar com)
{        
        lcd_busy();//测忙
        lcdrs=0;
        lcdrw=0;
        P3=com;
        lcden=1;
        _nop_();
        _nop_();
        //delay2(1);
        lcden=0;        
}
void write_data(uchar date)
{        
        lcd_busy();//测忙
        lcdrs=1;
        lcdrw=0;
        P3=date;
        lcden=1;
        _nop_();
        _nop_();
        //delay2(1);
        lcden=0;
}

void init(void)      //初始化函数
{
    rst=1;        
    psb=1;
        delay(10);
        write_com(0x30);//基本指令集
        delay(10);
        write_com(0x0c);//显示ON,游标OFF,游标位置OFF
        delay(10);
        write_com(0x01);//清除显示
        delay(10);
}

void T_display(uchar *p) //图片数据提取函数
{  
        uchar x,y,a,b,c;   
        //write_com(0x34); //关闭绘图功能  
        x=0x88;//设置水平坐标X  
        y=0x80;//设置垂直坐标Y   
        for(c=0;c<2;c++)  
        {   
                for(a=0;a<32;a++)   
                {   
                        write_com(y+a);   
                        write_com(x);                     
                        for(b=0;b<16;b++)     
                                write_data(*p++); //写入8位数据   
                }   
                x=0x80;//转换半屏   
        }   
        //write_com(0x36); //打开绘图功能  
        //write_com(0x30);   
}

void QP()  //清除DDRAM的数据:送入0
{  
        uchar x,y,a,b,c;  
        x=0x80;
        y=0x80;   
        write_com(0x34);//关闭绘图功能  
        for(a=0;a<2;a++)  
        {   for(b=0;b<32;b++)     
                {
                       write_com(y+b);   
                        write_com(x);   
                                for(c=0;c<16;c++)      
                                        write_data(0x00);   
                }   
                x=0x88;   
        }   
        write_com(0x36);//打开绘图功能  
        write_com(0x30);   
}

//***************************************************************************************//
//*********************************spi驱动**********************************************//
void spi_w(uchar dat)                //写数据
{
        unsigned char i;
        for(i=8;i;i--)
        {
                clk=0;
                 if(dat&0x80)
                        d0=1;
                else
                        d0=0;
               
                  dat<<=1;
                   clk=1;
         }
                d0=1;
}

uchar spi_r(void)  //读数据
{
        unsigned char n,j;
          for(j=8;j;j--)
          {
                clk=0;
                delay2(40);        
                clk=1;
            delay2(40);         
                n<<1;
                if(di) n |= 1;
          }
          return (n);
}
//*********************************spi驱动**********************************************//
//***************************************************************************************//








//***************************************************************************************//
//*********************************SD卡驱动**********************************************//
uchar sd_com(uchar *com)
{
        
        uchar i,temp,time=0;
        cs=1; spi_w(0xff); cs=0;

        for(i=0;i<0x06;i++)    //写命令
        {
                spi_w(*com++);
        }
        spi_r();
        do
        {
                temp=spi_r();  //读到有返回
                time++;
        } while((temp==0xff)&&(time<100));
        return(temp);               
}


uchar sd_reset()
{
        uchar time,temp,i;
        uchar cmd[]={0x40,0x00,0x00,0x00,0x00,0x95};

        ints=1;//开启初始化延时
        cs=1;
        for(i=0;i<20;i++)//至少74个时钟
                 {spi_w(0xff);}

        cs=0;
        time=0;
        do                          //写cmd0
        {
                temp=sd_com(cmd);
                time++;
                if(time>=200)
                {return(0x01); }
        }while(temp!=0x01);

        cs=1;
        spi_w(0xff);
        return 0;
}

uchar sd_int()
{
        uchar time,temp;
        uchar cmd[]={0x41,0x00,0x00,0x00,0x00,0xff};
        cs=0;
        time=0;
        do
        {
                temp=sd_com(cmd);
                time++;
                if(time==100)
                  {return(0x02);}
        }while(temp!=0)        ;
        ints=0;        
        cs=1;
        spi_w(0xff);
        return 0;
}         

uchar sd_r(unsigned long add,uchar *buf)
{
        uchar time,temp;
        uint j;
        uchar cmd[]={0x51,0x00,0x00,0x00,0x00,0xff};//cmd17
        add<<=9;//  等于add*512 扇区地址转换为字节地址
        cmd[1]=((add&0xff000000)>>24);
        cmd[2]=((add&0x00ff0000)>>16);
        cmd[3]=((add&0x0000ff00)>>8);
        cs=0;
        time=0;
        do
        {
                temp=sd_com(cmd);
                time++;
                if(time==100)
                {return(1);}
        } while(temp!=0);  //说明命令写入成功


        while(spi_r()!=0xfe);//读到数据的开头

        for(j=0;j<512;j++)
        {
                *buf++ = spi_r();
        }

        spi_r();
        spi_r();//读2个CRC

        cs=1;
        spi_w(0xff);
        return (0);
}


//*********************************SD卡驱动**********************************************//
//***************************************************************************************//

void main()
{
        uint pic;
        unsigned long add=512;//定义扇区地址
        sd_reset();//SD卡复位
        sd_int(); //SD卡初始化
        init();        //12864初始化                                                
        QP();        //12864清屏

        for(pic=0;pic<8000;pic++)         //一共xxx张图
        {
        sd_r(add++,table);
        sd_r(add++,table+512);//读取两个扇区1024字节
        write_com(0x36);//开启绘图  
        T_display(table);
        if(pic<780)delay(45);
        if(pic>780&&pic<1200)delay(50);
        if(pic>1200&&pic<1600)delay(60);
        if(pic>1600&&pic<2000)delay(50);
        if(pic>2000&&pic<2300)delay(55);
        if(pic>2300)delay(50);
        if(pic)delay(60);
        }
        while(1);        
}




此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
dontium
1楼-- · 2019-03-25 00:08
楼主看看SD协议吧,看懂后就会了
anqi90
2楼-- · 2019-03-25 00:13
 精彩回答 2  元偷偷看……
shower.xu
3楼-- · 2019-03-25 01:54
anqi90 发表于 2016-1-27 00:16
MISO就是master out,slave in,SD卡的DO就是data out
楼主先确认屏幕能正常显示,再确认SD卡能读出数据, ...

MISO就是master out,slave in  ?写反了?
anqi90
4楼-- · 2019-03-25 05:55
shower.xu 发表于 2016-1-27 10:53
MISO就是master out,slave in  ?写反了?

好吧,看着楼主写反了,自己写的时候又反了...
shower.xu
5楼-- · 2019-03-25 11:14
 精彩回答 2  元偷偷看……
森森森123
6楼-- · 2019-03-25 14:08
shower.xu 发表于 2016-1-27 10:53
MISO就是master out,slave in  ?写反了?

目前测试出 屏幕可以正常显示 但是SD卡的扇区数据读取不成功,读取bin文件  屏幕显示不出来。

但是我自己写数据进SD卡,然后在读取,他是可以读取显示出来,然后现在我就觉得是扇区的地址不对的问题,但是我是winhex查看的 不应该不对的啊

一周热门 更多>