5568|9

849

帖子

0

TA的资源

纯净的硅(高级)

楼主
 

SD+TFT+ZNFAT32+8962 [复制链接]

#include "systemInit.h"
#include "sd.h"
#include "myfun.h"
#include "pin_define.h"
#include "uart_init.h"

//定义初始化变量标志
unsigned char is_init;                         //在初始化的时候设置此变量为1,同步数据传输(SPI)会放慢

unsigned char _dat;
/********************************************************************************
 - 功能描述:向SD卡以SPI模式写数据
 - 隶属模块:SD卡模块
 - 参数说明:无
 - 返回说明:返回类型为void
 --形参说明:该参数为写向SD卡的数据
 ********************************************************************************/
void SD_spi_write(unsigned char x)

 unsigned char i;
 
 for(i=0;i<8;i++)
 {
  if((x>>(7-i)&0x01)==0x01)
   GPIOPinWrite(SD_COM_PORT,SD_DIN_F_SO,0x04);
  else 
   GPIOPinWrite(SD_COM_PORT,SD_DIN_F_SO,0x00);
   
     GPIOPinWrite(SD_COM_PORT,SD_CLK_F_CLK,0X00);
   if(is_init) SysCtlDelay(DELAY_TIME1*TheSysClock/DELAY_TIME);//delay(DELAY_TIME); 
   GPIOPinWrite(SD_COM_PORT,SD_CLK_F_CLK,0X02);
   if(is_init) SysCtlDelay(DELAY_TIME1*TheSysClock/DELAY_TIME);//delay(DELAY_TIME);
 }
}

/******************************************************************
 - 功能描述:IO模拟SPI,读取一个字节
 - 隶属模块:SD卡模块
 - 函数属性:内部
 - 参数说明:无
 - 返回说明:返回读到的字节
 ******************************************************************/
unsigned char SD_spi_read() //SPI读一个字节

 unsigned char ulStatus;
 unsigned char i;
 _dat=0x00;

 for(i=0;i<8;i++)
 { 
     GPIOPinWrite(SD_COM_PORT,SD_OUT_F_SI,0X01);
  ulStatus=GPIOPinRead(SD_COM_PORT,SD_OUT_F_SI);

  GPIOPinWrite(SD_COM_PORT,SD_CLK_F_CLK,0X02);
   if(is_init) SysCtlDelay(DELAY_TIME1*TheSysClock/DELAY_TIME);//delay(DELAY_TIME);
   GPIOPinWrite(SD_COM_PORT,SD_CLK_F_CLK,0X00);
   if(is_init) SysCtlDelay(DELAY_TIME1*TheSysClock/DELAY_TIME);//delay(DELAY_TIME);

  if(ulStatus&0x01)
   _dat|=0x01<<(7-i); 
  else
      _dat&=0xfe<<(7-i);
 }    
  return (_dat);
}

/******************************************************************
 - 功能描述:向SD卡写命令
 - 隶属模块:SD卡模块
 - 函数属性:内部
 - 参数说明:SD卡的命令是6个字节,pcmd是指向命令字节序列的指针
 - 返回说明:命令写入后,SD卡的回应值,调用不成功,将返回0xff
******************************************************************/ 
//向SD卡写命令,pcmd是命令字节序列的首地址
unsigned char SD_Write_Cmd(unsigned char *pcmd)
{
 unsigned char temp,time=0;

  GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
  SD_spi_write(0xff); //提高兼容性,如果没有这里,有些SD卡可能不支持  
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X00);

  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();//一直读,直到读到的不是0xff或超时
    time++;
  }while((temp==0xff)&&(time<TRY_TIME));
 UARTprintf("is ok read cmd.\r\n");
  return(temp);
}

/********************************************************************************
 - 功能描述:复位SD卡,用到CMD0,使用SD卡切换到SPI模式
 - 隶属模块:SD卡模块
 - 参数说明:无
 - 返回说明:调用成功,返回0x00,否则返回INIT_CMD0_ERROR (Pin_Define.h中有定义)
 ********************************************************************************/
unsigned char SD_Reset(void)//SD卡复位,进入SPI模式,使用CMD0(0号命令)
{
 unsigned char time,temp,i;
  unsigned char pcmd[] = {0x40,0x00,0x00,0x00,0x00,0x95};
 UARTprintf("go into sd_reset.\r\n");
 is_init=0x01;                               //设置初始化标志位
 GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
  for(i=0;i<0xff;i++)                         //初始时,首先要发送最少74个时钟信号,这是必须的!!!
  {
    SD_spi_write(0xff);                     //120个时钟周期
  }
 GPIOPinWrite(SD_COM_PORT,SD_CS,0X00);
  time=0;
  do
  {
    temp=SD_Write_Cmd(pcmd);                //写入CMD0
    time++;
    if(time==TRY_TIME)
    {  
   GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
   UARTprintf("INIT_CMD0_ERROR\r\n");
      return(INIT_CMD0_ERROR);            //CMD0写入失败
    }
  }while(temp!=0x01);
 GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
  SD_spi_write(0xff);                         //按照SD卡的操作时序在这里补8个时钟
 UARTprintf("go out sd_reset.\r\n");
  return 0;                                   //返回0,说明复位操作成功
}

/******************************************************************************
 - 功能描述:初始化SD卡,使用CMD1
 - 隶属模块:SD卡模块
 - 函数属性:内部
 - 参数说明:无
 - 返回说明:调用成功,返回0x00,否则返回INIT_CMD1_ERROR (Pin_Define.h中有定义)
 ******************************************************************************/
unsigned char SD_Init(void) //初始化,使用CMD1(1号命令)

 unsigned char time,temp;
  unsigned char pcmd[] = {0x41,0x00,0x00,0x00,0x00,0xff};
 UARTprintf("go into sd_init.\r\n");
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X00);

  time=0;
  do
  { 
    temp=SD_Write_Cmd(pcmd);
    time++;
    if(time==TRY_TIME)
    {
   GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
      return(INIT_CMD1_ERROR);            //CMD1写入失败
    }
  }while(temp!=0);
     
  is_init=0;                                  //初始化完毕,将is_init设置为0,为了提高以后的数据传输速度
  
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);       //关装SD卡的片选

  SD_spi_write(0xff);                         //按照SD卡的操作时序在这里补8个时钟
 UARTprintf("go out sd_init.\r\n");
  return(0);                                  //返回0,说明初始化操作成功
}

/***********************************************************************************************
 - 功能描述:将buffer指向的512个字节的数据写入到SD卡的addr扇区中
 - 隶属模块:SD卡模块
 - 函数属性:内部
 - 参数说明:addr:扇区地址
             buffer:指向数据缓冲区的指针
 - 返回说明:调用成功,返回0x00,否则返回WRITE_BLOCK_ERROR (Pin_Define.h中有定义)
 - 注:SD卡初始化成功后,读写扇区时,尽量将SPI速度提上来,提高效率,is_init不为0时可提高SPI速度
 ***********************************************************************************************/
//向SD卡中的指定地址的扇区写入512个字节,使用CMD24(24号命令)    
unsigned char SD_Write_Sector(unsigned long addr,unsigned char *Buffer) 

 unsigned char temp,time;
  unsigned int i;
 //向SD卡中单个块(512字节,一个扇区)写入数据,用CMD24
  unsigned char pcmd[] = {0x58,0x00,0x00,0x00,0x00,0xff};
 //addr = addr * 512 将块地址(扇区地址)转为字节地址 [这里就限制了SD卡的最大容量为4G]
  addr<<=9;
 //将字节地址写入到CMD24字节序列中
  pcmd[1]=((addr&0xff000000)>>24);
  pcmd[2]=((addr&0x00ff0000)>>16);
  pcmd[3]=((addr&0x0000ff00)>>8);
 //打开SD卡片选
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X00);

  time=0;
  do
  { 
    temp=SD_Write_Cmd(pcmd);
    time++;
    if(time==TRY_TIME)
    {  
   GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
      //命令写入失败
      return(temp);
    }
  }while(temp!=0);
 //这里要插入若干时钟信号
  for(i=0;i<100;i++)
  {
    SD_spi_read();
  }
 //写入开始字节 0xfe,后面就是要写入的512个字节的数据
  SD_spi_write(0xfe); 
 //将缓冲区中要写入的512个字节写入SD卡
  for (i=0;i<512;i++)
  {
    SD_spi_write(*Buffer++);
  }
   //两个字节的CRC校验码,不用关心
  SD_spi_write(0xFF);
  SD_spi_write(0xFF);
  
    //读取返回值
  temp=SD_spi_read();
 //如果返回值是 XXX00DELAY_TIME1 说明数据已经被SD卡接受了 
  if((temp & 0x1F)!=0x05)
  {
    GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);
  //写块数据失败
    return(WRITE_BLOCK_ERROR);
  }
  //等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的FLASH中,需要一个时间)
  while(SD_spi_read()!=0xff);
 //忙时,读回来的值为0x00,不忙时,为0xff     
 //关闭片选
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);

  SD_spi_write(0xFF);//按照SD卡的操作时序在这里补8个时钟
  return(0);   //返回0,说明写扇区操作成功
}

/****************************************************************************
 - 功能描述:读取addr扇区的512个字节到buffer指向的数据缓冲区
 - 隶属模块:SD卡模块
 - 函数属性:内部
 - 参数说明:addr:扇区地址
             buffer:指向数据缓冲区的指针
 - 返回说明:调用成功,返回0x00,否则返回READ_BLOCK_ERROR (sd.h中有定义)
 - 注:SD卡初始化成功后,读写扇区时,尽量将SPI速度提上来,提高效率
 ****************************************************************************/
//从SD卡的指定扇区中读出512个字节,使用CMD17(17号命令)
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的字节序列
    //sector = sector * 512    将块地址(扇区地址)转为字节地址
  addr<<=9;

  pcmd[1]=((addr&0xFF000000)>>24);
  pcmd[2]=((addr&0x00FF0000)>>16);
  pcmd[3]=((addr&0x0000FF00)>>8);
 //打开片选
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X00);

  time=0;
  do
  { 
  //写入CMD17 ,写入17号命令
    temp=SD_Write_Cmd(pcmd);
    time++;
    if(time==TRY_TIME)
    {
      return(READ_BLOCK_ERROR); //读块失败
    }
  }while(temp!=0);
    //一直读,当读到0xfe时,说明后面的是512字节的数据了  
  while (SD_spi_read() != 0xfe);
 //将数据写入到数据缓冲区中
  for(j=0;j<512;j++) 
  { 
    buffer[j]=SD_spi_read();
  }
 //读取两个字节的CRC校验码,不用关心它们
  SD_spi_read();
  SD_spi_read();
 //SD卡关闭片选
  GPIOPinWrite(SD_COM_PORT,SD_CS,0X08);   
 //按照SD卡的操作时序在这里补8个时钟
  SD_spi_write(0xFF);

  return 0;
}

此帖出自ARM技术论坛

最新回复

SD卡有没有格式化为FAT32格式呢  详情 回复 发表于 2011-10-30 09:53
点赞 关注
个人签名只有想不到,没有做不到。
 

回复
举报

849

帖子

0

TA的资源

纯净的硅(高级)

沙发
 

。。

请问一下各们,以上是一个SD+ZNFAT32+8962+tft的一个系统。由于IO口的紧缺,我用GPIO口模拟了一组SPI模式口作为SD卡的SPI模式口。但是在超级终端跟踪的时候,总是发现SD卡初始化不到,进入了复位程序后,它就一直在里面循环,接收不到0X01。各位老大,给点意见 。。。。。
此帖出自ARM技术论坛
 
个人签名只有想不到,没有做不到。
 
 

回复

2

帖子

0

TA的资源

禁止访问

板凳
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复

109

帖子

0

TA的资源

纯净的硅(初级)

4
 

建议

你最好是用示波器看一下你的模拟SPI程序是否对的?
特别是时序方面,在模拟spi读sd卡的时候,其它功能你可以先屏蔽掉.
如果你手头上的板子多的话,可否焊一块给我,我给你调试看看.
QQ:1246696660
此帖出自ARM技术论坛
 
 
 

回复

849

帖子

0

TA的资源

纯净的硅(高级)

5
 

  还是没的个所以然。我是用8962的开发板做的。。。呵呵。。。
此帖出自ARM技术论坛
 
个人签名只有想不到,没有做不到。
 
 

回复

849

帖子

0

TA的资源

纯净的硅(高级)

6
 
楼上的哥们,
我屏了其它的功能了,现在就只剩下UART模块的SD卡模块了,但还是不行。我就不了解哪里有问题了。  
    初始化时候,我放慢了速度 , 而且很慢了,但还是读不起。马上交作品了,我呕。。。
此帖出自ARM技术论坛
 
个人签名只有想不到,没有做不到。
 
 

回复

720

帖子

0

TA的资源

纯净的硅(中级)

7
 
不是有错误定义代码么?你可以在子程序里都加一下,单步执行看是在什么地方返回错误代码的,然后看错误代码是什么,就根据错误代码解决……不过这得你模拟SPI得先正确才说!

[ 本帖最后由 cuizhihao 于 2010-11-20 17:00 编辑 ]
此帖出自ARM技术论坛
 
 
 

回复

849

帖子

0

TA的资源

纯净的硅(高级)

8
 
懂了。。。
    MARK。。。。
此帖出自ARM技术论坛
 
个人签名只有想不到,没有做不到。
 
 

回复

36

帖子

0

TA的资源

一粒金砂(中级)

9
 
LZ问题如何解决的啊???我现在遇到了相同的问题,初始化跳进那个循环不出来,不返回0x01啊。。。
此帖出自ARM技术论坛
 
 
 

回复

55

帖子

0

TA的资源

一粒金砂(中级)

10
 
SD卡有没有格式化为FAT32格式呢
此帖出自ARM技术论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表