打印

关于51读写SDHC卡的问题

[复制链接]
2684|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hxc134|  楼主 | 2012-2-26 12:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在仿真的时候都没问题,但是烧入芯片后串口没反应,芯片和串口都测试过没问题,希望各位高手给解答下,代码如下:

#include <reg51.h>
#include "string.h"
#define F_CPU 11059200//18432000
void delay(unsigned int time)
{
while(time--);
}
void UART_Init()
{
EA=0;     //暂时关闭中断
PCON|=0x80;   //PCON的最高位SMOD=1时波特率加倍
SCON = 0x50;  //串行传输方式1,允许接收,开串行中断
TMOD = 0x20;  //定时器方式1,16位计时
TL1 = TH1 =  0xfd; //11.0592M晶振时,0xf4为2400,0xfa为4800,0xfd为9600
// TL1 = TH1 =  0xf6; //18.432M晶振时,0xf6为9600
TR1=1;           //启动定时器1
EA=1;            //允许中断
}
void UART_Send_Byte(unsigned char mydata)
{
mydata = mydata;
ES=0;
TI=0;
SBUF=mydata;
while(!TI);
TI=0;
ES=1;
}
void uart_putc_hex(unsigned char b)
{
if((b >> 4) < 0x0a)
  UART_Send_Byte((b >> 4) + '0');
else
  UART_Send_Byte((b >> 4) - 0x0a + 'a');
if((b & 0x0f) < 0x0a)
  UART_Send_Byte((b & 0x0f) + '0');
else
  UART_Send_Byte((b & 0x0f) - 0x0a + 'a');
}
void UART_Send_Enter()
{
  UART_Send_Byte(0x0d);
  UART_Send_Byte(0x0a);
}
void uart_puts_p(char *s)
{
int len=strlen(s)-1;
int i;
for(i=0;i<len;i++)
{
  UART_Send_Byte(s[i]);
}
if(s[i]=='\n')
{
  UART_Send_Enter();
}
else
{
  UART_Send_Byte(s[i]);
}
}
sbit SD_SCL=P3^5;  //SD卡同步时钟  输入,C51的15脚
sbit SD_SI =P3^6;  //SD卡同步数据  输入,C51的16脚
sbit SD_CS =P3^7;  //SD卡片选    输入    C51的17脚
sbit SD_SO =P2^0;  //SD卡同步数据  输出, C51的21脚
sbit sda_1161 =P1^3;
#define SD_RAW_WRITE_SUPPORT 1  // 写操作支持位
#define SD_RAW_WRITE_BUFFERING 0  // 支持写缓冲区
#define SD_RAW_SAVE_RAM 0  // 静态RAM缓存
#define SD_RAW_SDHC 1  // 默认支持SDHC卡
#define configure_pin_mosi()
#define configure_pin_sck()
#define configure_pin_ss()
#define configure_pin_miso()
#define configure_pin_available()
#define configure_pin_locked()
#define get_pin_available() 0
#define get_pin_locked()  1
#define select_card() SD_CS = 0// 成立
#define unselect_card() SD_CS = 1// 成立
#define offset_t double
#define SD_RAW_FORMAT_HARDDISK 0
#define SD_RAW_FORMAT_SUPERFLOPPY 1
#define SD_RAW_FORMAT_UNIVERSAL 2
#define SD_RAW_FORMAT_UNKNOWN 3
/* CMD0: response R1 */
#define CMD_GO_IDLE_STATE 0x00
/* CMD1: response R1 */
#define CMD_SEND_OP_COND 0x01
/* CMD8: response R7 */
#define CMD_SEND_IF_COND 0x08
/* CMD9: response R1 */
#define CMD_SEND_CSD 0x09
/* CMD10: response R1 */
#define CMD_SEND_CID 0x0a
/* CMD12: response R1 */
#define CMD_STOP_TRANSMISSION 0x0c
/* CMD13: response R2 */
#define CMD_SEND_STATUS 0x0d
/* CMD16: arg0[31:0]: block length, response R1 */
#define CMD_SET_BLOCKLEN 0x10
/* CMD17: arg0[31:0]: data address, response R1 */
#define CMD_READ_SINGLE_BLOCK 0x11
/* CMD18: arg0[31:0]: data address, response R1 */
#define CMD_READ_MULTIPLE_BLOCK 0x12
/* CMD24: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_SINGLE_BLOCK 0x18
/* CMD25: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_MULTIPLE_BLOCK 0x19
/* CMD27: response R1 */
#define CMD_PROGRAM_CSD 0x1b
/* CMD28: arg0[31:0]: data address, response R1b */
#define CMD_SET_WRITE_PROT 0x1c
/* CMD29: arg0[31:0]: data address, response R1b */
#define CMD_CLR_WRITE_PROT 0x1d
/* CMD30: arg0[31:0]: write protect data address, response R1 */
#define CMD_SEND_WRITE_PROT 0x1e
/* CMD32: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_START 0x20
/* CMD33: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_END 0x21
/* CMD34: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_SECTOR 0x22
/* CMD35: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_START 0x23
/* CMD36: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_END 0x24
/* CMD37: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_ERASE_GROUP 0x25
/* CMD38: arg0[31:0]: stuff bits, response R1b */
#define CMD_ERASE 0x26
/* ACMD41: arg0[31:0]: OCR contents, response R1 */
#define CMD_SD_SEND_OP_COND 0x29
/* CMD42: arg0[31:0]: stuff bits, response R1b */
#define CMD_LOCK_UNLOCK 0x2a
/* CMD55: arg0[31:0]: stuff bits, response R1 */
#define CMD_APP 0x37
/* CMD58: arg0[31:0]: stuff bits, response R3 */
#define CMD_READ_OCR 0x3a
/* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
#define CMD_CRC_ON_OFF 0x3b
#define R1_IDLE_STATE 0
#define R1_ERASE_RESET 1
#define R1_ILL_COMMAND 2
#define R1_COM_CRC_ERR 3
#define R1_ERASE_SEQ_ERR 4
#define R1_ADDR_ERR 5
#define R1_PARAM_ERR 6
#define R2_CARD_LOCKED 0
#define R2_WP_ERASE_SKIP 1
#define R2_ERR 2
#define R2_CARD_ERR 3
#define R2_CARD_ECC_FAIL 4
#define R2_WP_VIOLATION 5
#define R2_INVAL_ERASE 6
#define R2_OUT_OF_RANGE 7
#define R2_CSD_OVERWRITE 7
#define R2_IDLE_STATE (R1_IDLE_STATE + 8)
#define R2_ERASE_RESET (R1_ERASE_RESET + 8)
#define R2_ILL_COMMAND (R1_ILL_COMMAND + 8)
#define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8)
#define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8)
#define R2_ADDR_ERR (R1_ADDR_ERR + 8)
#define R2_PARAM_ERR (R1_PARAM_ERR + 8)
#define R3_OCR_MASK (0xffffffffUL)
#define R3_IDLE_STATE (R1_IDLE_STATE + 32)
#define R3_ERASE_RESET (R1_ERASE_RESET + 32)
#define R3_ILL_COMMAND (R1_ILL_COMMAND + 32)
#define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32)
#define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32)
#define R3_ADDR_ERR (R1_ADDR_ERR + 32)
#define R3_PARAM_ERR (R1_PARAM_ERR + 32)
#define DR_STATUS_MASK 0x0e
#define DR_STATUS_ACCEPTED 0x05
#define DR_STATUS_CRC_ERR 0x0a
#define DR_STATUS_WRITE_ERR 0x0c
#define SD_RAW_SPEC_1 0 // 第1种类型卡
#define SD_RAW_SPEC_2 1 // 第2种类型卡
#define SD_RAW_SPEC_SDHC 2// SDHC类型卡
static unsigned char xdata raw_block[512];
static offset_t raw_block_address;
static unsigned char sd_raw_card_type;
volatile unsigned int DELAY_TIME = 1000;
void SpiSpeedLow62KHZ(void)
{
DELAY_TIME = 20;
}
void SpiSpeedHigh4MHZ(void)
{
DELAY_TIME = 0;
}
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_raw_send_byte(unsigned char x)
{
_dat=x;
SD_SI=_dat7;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat6;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat5;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat4;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat3;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat2;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat1;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
SD_SI=_dat0;
SD_SCL=0;
delay(DELAY_TIME);
SD_SCL=1;
delay(DELAY_TIME);
}
unsigned char sd_raw_rec_byte(void)
{
SD_SO=1;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat7=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat6=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat5=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat4=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat3=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat2=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat1=SD_SO;
SD_SCL=1;
delay(DELAY_TIME);
SD_SCL=0;
delay(DELAY_TIME);
_dat0=SD_SO;
return (_dat);
}
unsigned char sd_raw_send_command(unsigned char command, unsigned long arg)
{
    unsigned char response;
unsigned char i;
    sd_raw_rec_byte();
    sd_raw_send_byte(0x40 | command);
    sd_raw_send_byte((arg >> 24) & 0xff);
    sd_raw_send_byte((arg >> 16) & 0xff);
    sd_raw_send_byte((arg >> 8) & 0xff);
    sd_raw_send_byte((arg >> 0) & 0xff);
    switch(command)
    {
        case CMD_GO_IDLE_STATE:
           sd_raw_send_byte(0x95);
           break;
        case CMD_SEND_IF_COND:
           sd_raw_send_byte(0x87);
           break;
        default:
           sd_raw_send_byte(0xff);
           break;
    }
    for(i = 0; i < 10; ++i)
    {
        response = sd_raw_rec_byte();
        if(response != 0xff)
            break;
    }
    return response;
}
#define uint8_t unsigned char
#define uint16_t unsigned int
#define uintptr_t unsigned int
uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
{
offset_t block_address;
uint16_t block_offset;
uint16_t read_length;
uint8_t *cache;
uint16_t i;
while(length > 0)
{
  block_offset = (uint16_t)offset & 0x01ff;
  block_address = offset - block_offset;
  read_length = 512 - block_offset;
  if(read_length > length)
  {
   read_length = length;
  }
  if(block_address != raw_block_address)
  {
   select_card();
#if SD_RAW_SDHC
            if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
#else
            if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address))
#endif
   {
    unselect_card();
    return 0;
   }
   /* wait for data block (start byte 0xfe) */
   while(sd_raw_rec_byte() != 0xfe);
   /* read byte block  */
   cache = raw_block;
   for(i = 0; i < 512; ++i)
    *cache++ = sd_raw_rec_byte();
   raw_block_address = block_address;
   memcpy(buffer, raw_block + block_offset, read_length);
   buffer += read_length;
   /* read crc16  */
   sd_raw_rec_byte();
   sd_raw_rec_byte();
   /* deaddress card */
   unselect_card();
   /* let card some time to finish */
   sd_raw_rec_byte();
  }
  else
  {
   /* use cached data */
   memcpy(buffer, raw_block + block_offset, read_length);
   buffer += read_length;
  }
  length -= read_length;
  offset += read_length;
}
return 1;
}
unsigned char sd_raw_init()
{
unsigned char i;
unsigned char response;
unsigned int i2;
unsigned int i3;
configure_pin_mosi();  // 输出
configure_pin_sck();  // 输出
configure_pin_ss(); // 输出
configure_pin_miso();  // 输入
unselect_card();   // 禁止cs
/* initialize SPI with lowest frequency; max. 400kHz during identification mode of card
初始化为spi模式,注意现在需在400kHZ频率以内 */
SpiSpeedLow62KHZ();
/* initialization procedure */
sd_raw_card_type = 0;  // 卡类型变量复位
/* card needs 74 cycles minimum to start up */
for(i = 0; i < 0x0f; ++i)  // 74个前期时钟
{
  /* wait 8 clock cycles */
  sd_raw_send_byte(0xff);   // spi总线发送oxff
}
/* address card */
select_card();     // 使能sd卡
/* reset card */
for(i2 = 0; ; ++i2)
{
  response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);
  // 复位置于spi模式
  if(response == (1 << R1_IDLE_STATE))
  break;
  uart_putc_hex(response);
  UART_Send_Enter();
  if(i2 == 0x1ff)
  {
   unselect_card();   // 禁止卡
   return 0;
  }
}
#if SD_RAW_SDHC
/* check for version of SD card specification */
response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */);
if((response & (1 << R1_ILL_COMMAND)) == 0)
{
  sd_raw_rec_byte();
  sd_raw_rec_byte();
  if((sd_raw_rec_byte() & 0x01) == 0)
   return 0; /* card operation voltage range doesn't match */
  if(sd_raw_rec_byte() != 0xaa)
   return 0; /* wrong test pattern */
  /* card conforms to SD 2 card specification */
  sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
}
else
#endif
{
  /* determine SD/MMC card type */
  sd_raw_send_command(CMD_APP, 0);  // 0x37 判断是SD卡还是MMC卡
  response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0);  // 0x29
  if((response & (1 << R1_ILL_COMMAND)) == 0)  // 1<<2
  {
   /* card conforms to SD 1 card specification */
   sd_raw_card_type |= (1 << SD_RAW_SPEC_1); // 为SD卡
  }
  else
  {
   /* 为 MMC card 卡*/
  }
}
/* wait for card to get ready 等待SD卡忙完 */
for(i3 = 0; ; ++i3)
{
  if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)))
  {
   unsigned long arg = 0;
#if SD_RAW_SDHC
   if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
   arg = 0x40000000;
#endif
   sd_raw_send_command(CMD_APP, 0);
   response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);   // 激活卡内部初始化
  }
  else
  {
   response = sd_raw_send_command(CMD_SEND_OP_COND, 0);    // 激活卡内部初始化
  }
  if((response & (1 << R1_IDLE_STATE)) == 0)
   break;
  if(i3 == 0x7fff)
  {
   unselect_card();
   return 0;
  }
}
#if SD_RAW_SDHC
if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
{
  if(sd_raw_send_command(CMD_READ_OCR, 0))
  {
   unselect_card();
   return 0;
  }
  if(sd_raw_rec_byte() & 0x40)
   sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);
  sd_raw_rec_byte();
  sd_raw_rec_byte();
  sd_raw_rec_byte();
}
#endif
/* set block size to 512 bytes 设置512字节为1块 */
if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512))
{
  unselect_card();
  return 0;
}
/* deaddress card  */
unselect_card();
/* switch to highest SPI frequency possible */
// 转换spi总线到高速模式
SpiSpeedHigh4MHZ();
#if !SD_RAW_SAVE_RAM
/* the first block is likely to be accessed first, so precache it here */
// 第1个块可能首先使用,先准备好缓冲
raw_block_address = (offset_t) -1;
if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
  return 0;
#endif
return 1;
}
uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length)
{
offset_t block_address;
uint16_t block_offset;
uint16_t write_length;
uint8_t *cache;
uint16_t i;
    while(length > 0)
    {
        block_offset = (uint16_t)offset & 0x01ff;
        block_address = offset - block_offset;
        write_length = 512 - block_offset; /* write up to block border */
        if(write_length > length)
            write_length = length;
        if(block_address != raw_block_address)
        {
            if(block_offset || write_length < 512)
            {
                if(!sd_raw_read(block_address, raw_block, sizeof(raw_block)))
                    return 0;
            }
            raw_block_address = block_address;
        }
        if(buffer != raw_block)
        {
            memcpy(raw_block + block_offset, buffer, write_length);
        }
        /* address card  */
        select_card();
        /* send single block request */
#if SD_RAW_SDHC
        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
#else
        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address))
#endif
        {
            unselect_card();
            return 0;
        }
        sd_raw_send_byte(0xfe);
        cache = raw_block;
        for(i = 0; i < 512; ++i)
            sd_raw_send_byte(*cache++);
        sd_raw_send_byte(0xff);
        sd_raw_send_byte(0xff);
        while(sd_raw_rec_byte() != 0xff);
        sd_raw_rec_byte();
        unselect_card();
        buffer += write_length;
        offset += write_length;
        length -= write_length;
    }
    return 1;
}
// sfr STC89X51_AUXR = 0x8E;
#define ADDR 0x808001
// unsigned char tempfor = 1;
uint8_t temp[20];
void DelayMs(unsigned int temp)
{
unsigned char i;
while(temp--)
  for(i = 0;i<125;i++);
                  {  sda_1161 = 1;
                     sda_1161 = 0; }
}
void main(void)
{
uint8_t flag= 0xff;
uint16_t i;
DelayMs(4000);        
// STC89X51_AUXR &= 0x01; // 启动STC内部xdata的RAM
UART_Init();
uart_puts_p("P89V51 uart OK\n");
while(1)
{
  if(!sd_raw_init())
  {
   uart_puts_p("SDHC initialization failed\n");
   while(1);
  }
  uart_puts_p("OK\n");
  for(i=0;i<sizeof(temp);i++)
  {
   temp[i] = i;
  }
  flag = sd_raw_write(0x808001, temp, sizeof(temp));
  uart_puts_p("SDHC Write flag is : ");
  uart_putc_hex(flag);
  UART_Send_Enter();
  uart_puts_p("SDHC Write OK \n");
  for(i=0;i<sizeof(temp);i++)
  {
   temp[i] = 0;
  }
  flag = sd_raw_read(0x808001,temp,sizeof(temp));
  uart_puts_p("SDHC Read flag is : ");
  uart_putc_hex(flag);
  UART_Send_Enter();
  for(i=0;i<sizeof(temp);i++)
  {
   uart_putc_hex(temp[i]);
   uart_puts_p(",");
  }
  UART_Send_Enter();
  UART_Send_Enter();
  while(1);
}
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

2

帖子

0

粉丝