川九-EveRYouNg 2021-08-20 15:11 采纳率: 66.7%
浏览 108
已结题

有关micro SD卡读写问题——只能读写半个扇区即256字节?

在对Micro SD卡的读写过程中,我发现我只能对SD卡一个扇区的前256字节进行读写,小于256字节时读写正常,大于256字节在写入时会变成规律重复的一段数据,且在后256字节的数据无法读出。

该SD卡为某宝5元1张的2G普通SD卡,文件系统现格式化为FAT16(该卡默认),在电脑上正常使用。

读取用的单片机为STC89C52RC
img

img
写入512字节0x77

img
写入300字节0xA5

大家看看这是什么原因?

主要代码如下(不是我写的,但我看了下对比了其他人写的感觉也没啥问题啊)

#include "public.h"
#include "SD.h"
#include "port.h"

//定义512字节数据缓冲区
u8 xdata BUFFER_DATA[1024]={0};

//使用位操作加快SPI读写速度
u8 bdata Byte_data;
sbit Byte_data7=Byte_data^7;
sbit Byte_data6=Byte_data^6;
sbit Byte_data5=Byte_data^5;
sbit Byte_data4=Byte_data^4;
sbit Byte_data3=Byte_data^3;
sbit Byte_data2=Byte_data^2;
sbit Byte_data1=Byte_data^1;
sbit Byte_data0=Byte_data^0;

//SPI写入一个字节(字节数据)
void SPI_write_Byte(u8 Byte)
{
    SPI_MOSI=1;
    Byte_data=Byte;
    SPI_CLK=0;SPI_MOSI=Byte_data7;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data6;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data5;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data4;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data3;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data2;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data1;SPI_CLK=1;
    SPI_CLK=0;SPI_MOSI=Byte_data0;SPI_CLK=1;
    SPI_MOSI=1;
}

//SPI读取一个字节(返回值为数据)
u8 SPI_read_Byte()
{
    SPI_MISO=1;
    SPI_CLK=0;Byte_data7=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data6=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data5=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data4=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data3=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data2=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data1=SPI_MISO;SPI_CLK=1;
    SPI_CLK=0;Byte_data0=SPI_MISO;SPI_CLK=1;
    SPI_MISO=1;
    return Byte_data;
}

//检测SD卡的响应
u8 SD_response()
{
    u8 i;
    u8 response;

    for(i=0;i<9;++i)
    {
        response=SPI_read_Byte();
        if((response==0x00)||(response==0x01)) break;
    }
    return response;
} 

//MCUSD卡写入命令
void MCU_write_SD_command(u8 command,u32 argument,u8 CRC)
{
    SPI_write_Byte(command|0x40);
    SPI_write_Byte(((u8 *)&argument)[0]);
    SPI_write_Byte(((u8 *)&argument)[1]);
    SPI_write_Byte(((u8 *)&argument)[2]);
    SPI_write_Byte(((u8 *)&argument)[3]);
    SPI_write_Byte(CRC);
}

//SD卡初始化
u8 SD_init()
{
    u8 i;
    u8 response=0x01;
    
    SD_CS=1;
    for(i=0;i<10;++i) SPI_write_Byte(0xFF);
    SD_CS=0;
    
    MCU_write_SD_command(0x00,0x00000000,0x95);//发送命令0将MMC置于SPI模式

    response=SD_response();

    if(response!=0x01) return 0;
    while(response)
    {
        SD_CS=1;
        SPI_write_Byte(0xFF);
        SD_CS=0;
        MCU_write_SD_command(0x01,0x00FFC000,0xFF);
        response=SD_response();
    }
    SD_CS=1;
    SPI_write_Byte(0xFF);
    return 1;
}

//MCUSD卡写入数据,一次最多512字节(扇区,数据长度(最大为512,建议填512))
u8 MCU_write_SD_512Byte(u32 block,u16 data_length)
{
    u16 i;
    u8 *block_data_pointer;//扇区数据指针
    u8 dataResp;
    
    block_data_pointer=BUFFER_DATA;//指针指向缓冲数据
    
    SD_CS=0;
    
    MCU_write_SD_command(0x18,512*block,0xFF);//发送写入命令

    if(!SD_response())
    {
        SPI_write_Byte(0xFF);
        SPI_write_Byte(0xFF);
        SPI_write_Byte(0xFF);
        //命令成功-现在MCUSD卡写入数据
        SPI_write_Byte(0xFE);//数据将在发送0xFE后开始写入
        //现在MCUSD卡写入数据
        for(i=0;i<data_length;++i) 
        {
            SPI_write_Byte(*block_data_pointer);
            ++block_data_pointer;
        }
        for(;i<512;++i) SPI_write_Byte(0x00);
        
        //数据块发送-现在发送校验和
        SPI_write_Byte(0xFF);//两字节CRC校验,为0XFFFF,不考虑CRC
        SPI_write_Byte(0xFF);

        dataResp=SPI_read_Byte();//现在读取数据响应
        //在数据响应之后是一个繁忙的字节数,一个零字节表示MMCwhile(!SPI_read_Byte());

        dataResp=dataResp&0x0F; //屏蔽数据响应令牌的高字节
        
        SD_CS=1;
        
        SPI_write_Byte(0xFF);
        if(dataResp==0x0B) return 0;//数据不被CARD接受
        if(dataResp==0x05) return 1;//无效的数据响应
        return 0;
    }
    //写入命令0x18没有被MMC接收
    return 0;
}

//MCUSD卡读取数据,一次最多512字节(扇区,数据长度(最大为512,建议填512))
u8 MCU_read_SD_512Byte(u32 block,u16 data_length)
{
    u16 i;
    u8 *block_data_pointer;//扇区数据指针
    
    block_data_pointer=BUFFER_DATA;//指针指向缓冲数据
    
    SD_CS=0;
    MCU_write_SD_command(0x11,512*block,0xFF);//然后发送写命令

    if(!SD_response())
    {
        while(SPI_read_Byte()!=0xFE);//发送命令成功,现在发送数据,数据在接收0xFE之后

        for(i=0;i<data_length;++i) 
        {
            
            *block_data_pointer=SPI_read_Byte();
            ++block_data_pointer;
        }
        for(;i<512;++i) SPI_read_Byte();

        //数据块发送-现在发送校验和
        SPI_read_Byte();
        SPI_read_Byte();
        //现在读入数据响应
        SD_CS=1;
        SPI_read_Byte();
        return 1;
    }
    //读命令0x11没有被MMC的接收
    return 0;
}


  • 写回答

1条回答 默认 最新

  • 川九-EveRYouNg 2021-08-22 15:33
    关注

    我自己搞明白了居然还没有人答(ー_ー)!!
    其实是芯片RAM不够
    89c52有512字节的RAM,但好像一半在内部一半在外部。
    所以xdata最多只能装256字节数据。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 8月30日
  • 已采纳回答 8月22日
  • 创建了问题 8月20日

悬赏问题

  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败
  • ¥15 树莓派5怎么用camera module 3啊
  • ¥20 java在应用程序里获取不到扬声器设备
  • ¥15 echarts动画效果的问题,请帮我添加一个动画。不要机器人回答。
  • ¥15 Attention is all you need 的代码运行