5373|8

4

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

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

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

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

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

对应DO和DI么?


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


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

#include
#include
#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);        
}




此帖出自51单片机论坛

最新回复

看前边的偏移地址  详情 回复 发表于 2016-1-29 22:52
点赞 关注
 

回复
举报

1万

帖子

25

TA的资源

裸片初长成(高级)

沙发
 
楼主看看SD协议吧,看懂后就会了
此帖出自51单片机论坛
 
 
 

回复

1469

帖子

0

TA的资源

五彩晶圆(中级)

板凳
 
本帖最后由 anqi90 于 2016-1-27 10:58 编辑

MISO就是master out,slave in,SD卡的DO就是data out
------------更正,MOSI是master out,slave in,上面看着楼主的写反了,自己写的时候想着写反的结果反错了

楼主先确认屏幕能正常显示,再确认SD卡能读出数据,然后再试着读出数据来显示
做事要一步一步来,直接就一股脑的堆进去就跑,这程序根本没有办法调的

此帖出自51单片机论坛

点评

MISO就是master out,slave in ?写反了?  详情 回复 发表于 2016-1-27 10:53
 
 
 

回复

2002

帖子

24

TA的资源

五彩晶圆(高级)

4
 
anqi90 发表于 2016-1-27 00:16
MISO就是master out,slave in,SD卡的DO就是data out
楼主先确认屏幕能正常显示,再确认SD卡能读出数据, ...

MISO就是master out,slave in  ?写反了?
此帖出自51单片机论坛

点评

好吧,看着楼主写反了,自己写的时候又反了...  详情 回复 发表于 2016-1-27 10:54
 
 
 

回复

1469

帖子

0

TA的资源

五彩晶圆(中级)

5
 
shower.xu 发表于 2016-1-27 10:53
MISO就是master out,slave in  ?写反了?

好吧,看着楼主写反了,自己写的时候又反了...
此帖出自51单片机论坛
 
 
 

回复

2002

帖子

24

TA的资源

五彩晶圆(高级)

6
 
本帖最后由 shower.xu 于 2016-1-27 11:21 编辑

读扇区的话数据文件格式要和你写屏的顺序一直才行,这个需要仔细研究。可以参考
https://bbs.eeworld.com.cn/forum. ... 149&highlight=apple
https://bbs.eeworld.com.cn/forum. ... 343&highlight=apple
https://bbs.eeworld.com.cn/thread-315169-1-1.html

此帖出自51单片机论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

7
 
shower.xu 发表于 2016-1-27 10:53
MISO就是master out,slave in  ?写反了?

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

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

回复

4

帖子

0

TA的资源

一粒金砂(初级)

8
 
shower.xu 发表于 2016-1-27 11:19
读扇区的话数据文件格式要和你写屏的顺序一直才行,这个需要仔细研究。可以参考
http://bbs.eeworld.com.c ...

现在不怎么理解winhex扇区地址的看法   我程序里是用逻辑扇区的地址  
但是在winhex查看的地址写进去没有用,我用的是1G的SD卡
此帖出自51单片机论坛

点评

看前边的便宜地址  详情 回复 发表于 2016-1-29 22:52
 
 
 

回复

2002

帖子

24

TA的资源

五彩晶圆(高级)

9
 
森森森123 发表于 2016-1-29 22:41
现在不怎么理解winhex扇区地址的看法   我程序里是用逻辑扇区的地址  
但是在winhex查看的地址写进 ...

看前边的偏移地址
此帖出自51单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表