分立元件 发表于 2020-10-31 21:12:54

求51单片机SD卡和25Q80的驱动程序!

搞了一天了都没有解决这两个存储器,网上找的,卖家发的都不能正常使用,不知道坛友们有没有这两个存储器的驱动程序!

这两个是SD卡程序,不知道是不是因为我用8G卡的原因还是程序不行,不能正常工作
#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

    //错误码定义//

#define cmd0_error 0x01

#define cmd1_error 0x02

#define write_error 0x03

#define read_error 0x04

    /*位定义*/

sbit cs=P1^0; //定义片选位

sbit clk=P1^1;//定义时钟位

sbit si=P1^2; //定义主机发送数据位

sbit so=P1^3; //定义主机接收位

uchar xdata shuju={0};   //定义数据缓冲数组

uchar flag_time;         

//定义标志时间,因为当sd卡进行初始化时需要降低

//通信速度,所以通过该标志来写1来降低速度

void delay(uint x)       //通信延时函数

{

    while(x--)

    _nop_();

}

void delay1(uint a)   

{

    uint i,j;

    for(i=0;i<a;i++)

      for(j=0;j<120;j++);

}

//写一字节数据//

void write_sd(uchar date)

{

    uchar i;

    CY=0;

    clk=1;

    for(i=0;i<8;i++)

    {

      clk=0;

      date=date<<1;

      si=CY;

      if(flag_time==1)//用来判断是否处于初始化,如果是降低通信速度

      delay(10);

      _nop_();   //用来让io口数据更稳定,也可以省略

      clk=1;

      _nop_();

      if(flag_time==1)

      delay(10);

    }

}

//读取sd卡一个字节数据//

uchar read_sd()      

{

    uchar i,temp=0;

    so=1;          //一定要先将其置1否则会出现错误

    //因为如果先置0单片机io口寄存器相应位电平为低当

    //当接收到高电平后可能sd卡电平不足使其io变为高电平

    clk=1;

    for(i=0;i<8;i++)

    {

      clk=0;

      if(flag_time==1)

      delay(10);

      temp<<=1;

      temp=temp|so;

      _nop_();

      clk=1;

      _nop_();

      if(flag_time==1)

      delay(10);

    }

    return temp;

}

//向sd卡写命令//

uchar write_cmd(uchar *cmd)

{

    uchar i,time,temp;

    si=1;

    for(i=0;i<6;i++)//发送六字节命令

    {

      write_sd(cmd);

    }

    time=0;

    do

    {

      temp=read_sd();

      time++;

    }

    while((temp==0xff)&&(time<100));

    //判断命令是否写入成功,当读取到so不为0xff时命令写入成功

    //当temp==0xff时为真且没发送100次为真继续执行

    //但是又不能无限制等待所以让命令写入100次结束

    return temp;      //返回读取的数据

}

//复位函数//

uchar sd_reset()

{

    uchar i,temp=0xff,time;

    uchar table[]={0x40,0x00,0x00,0x00,0x00,0x95};

    flag_time=1;

    cs=1;

    for(i=0;i<0x0f;i++)      //复位时最少写入74个时钟周期

    {

      write_sd(0xff);

    }

    cs=0;

    time=0;//打开片选

    do

    {

      temp=write_cmd(table);   //写入cmd0

      time++;

      if(time==100)

      return(cmd0_error);

    }

    while(temp!=0x01);       //等待命令CMD0的响应

    cs=1;                  //关闭片选

    write_sd(0xff);         //补偿8个时钟

    return 0;

}

//初始化函数此函数决定SD卡的工作模式 选择SPI还是SD模式//

uchar sd_init()

{

    uchar time=0,temp=0xff;

    uchar table[]={0x41,0x00,0x00,0x00,0x00,0xff};       //命令码

    flag_time=1;

    cs=0;

    time=0;

    do

    {

      temp=write_cmd(table);

      time++;

      if(time==100)

      return 0x02;

    }

    while(temp!=0x00);       //等待命令CMD1响应

    flag_time=0;

    cs=1;

    write_sd(0xff);         //补偿8个时钟

    return 0;

}

//写sd卡扇区//

uchar xie_sd_shanqu(unsigned long int add,uchar *buffer)

{

    uchar temp,time;

    uint i;

    uchar table[]={0x58,0x00,0x00,0x00,0x00,0xff};

    add=add<<9;       //add=add*512

    //由于sd卡操作一次性只能写一个扇区也就是512个字节

    //所以这里通过将长整型地址左移九位来将地址乘上512

    //用于地址操作

    table=((add&0xff000000)>>24);

    table=((add&0x00ff0000)>>16);

    table=((add&0x0000ff00)>>8);

    cs=0;

    time=0;

    do

    {

      temp=write_cmd(table);       //写入写扇区命令

      time++;

      if(time==100)

      {

            return(write_error);

      }

    }

    while(temp!=0x00);               //判断命令是否写入成功成功时返回0x00

    for(i=0;i<20;i++)   //补充若干时钟

    {

      write_sd(0xff);

    }

    write_sd(0xfe);       //写入开始字节0xfe,后面要写入512字节数据

    for(i=0;i<512;i++)

    {

      write_sd(buffer);

    }

    write_sd(0xff);

    write_sd(0xff);         //两字节奇偶校验



    temp=read_sd();         //读取返回值

    if((temp&0x1f)!=0x05)      //如果返回值是 xxx00101 说明数据已经被写入

    {

      cs=1;

      return(write_error);

    }

    while(read_sd()!=0xff);          //等待sd卡不忙 数据写入成功

    cs=1;                  //关闭片选

    write_sd(0xff);         //补偿8 个时钟

    return 0;

}

//读取sd卡扇区//

uchar duqushanqu(unsigned long add,uchar *buffer)

{

    uchar temp,time=0;

    uint i;

    uchartable[]={0x51,0x00,0x00,0x00,0x00,0xff};

    add=add<<9;

    table=((add&0xff000000)>>24);

    table=((add&0x00ff0000)>>16);

    table=((add&0x0000ff00)>>8);

    cs=0;                        //打开片选

    do

    {

      temp=write_cmd(table);       //写命令

      time++;

      if(time==100)

      {

            return read_error;

      }

    }

    while(temp!=0);

    write_sd(0xff);               //补偿8个时钟

    while(read_sd()!=0xfe);      //一直读取等待0xfe

    for(i=0;i<512;i++)

    {

      buffer=read_sd();

    }

    write_sd(0xff);         //两字节奇偶校验位

    write_sd(0xff);

    cs=1;

    write_sd(0xff);         //补偿8个时钟

    return 0;

}

/*在P0上接八个发光二极管用来显示读取到的数据

首先在数组(shuju)里面放入i用于显示,再将其

写入SD卡扇区,然后在读取出SD卡里的数据*/

void main()

{

    uint i=0;
        uint a=0xaa;

    P1=0x00;

    P0=0xff;

    sd_reset();

    sd_init();   ///初始化sd卡

    for(i=0;i<512;i++)

    {

      shuju=a;         //向数据数组里面写入数据

    }

    for(i=0;i<512;i++)

    {

      xie_sd_shanqu(1,shuju);      //将数据数组里面的数据写入sd卡

    }

    for(i=0;i<512;i++)

    {

      shuju=0;         //清零数据数组用来存储从sd卡读取到的数据

    }         

    duqushanqu(1,shuju);   //读取扇区数据

    while(1)

    {

      for(i=0;i<512;i++)

      {

            P0=shuju;      //显示扇区数据

            delay1(200);

      }

    }

}


分立元件 发表于 2020-10-31 21:13:17

这是淘宝卖家给的SD卡程序
                                                                       /*
* SD模块测试程序
*
* 用途:SD模块测试程序
*
* 作者                                        日期                                备注
* Huafeng Lin                        20010/10/03                        新增
* Huafeng Lin                        20010/10/03                        修改
*
*/

#include "REG52.H"
////////////////////////****************/
unsigned char *SDInfo1="SD Init Success.";
unsigned char *SDInfo2="SD Init Fail.";
unsigned int xdata ReadBuffer;
unsigned int xdata WriteBuffer ;
unsigned int BlockSize;
unsigned long int BlockNR;

//sbit sd_clk=P3^2;
//sbit sd_cse=P3^0;
//sbit sd_dai=P3^3; //Do
//sbit sd_dao=P3^1;//DI

sbit sd_cse=P1^0;
sbit sd_dao=P1^2;//DI
sbit sd_clk=P1^1;
sbit sd_dai=P1^3;//Do

void Delay5us()
{
        unsigned char a=0;
        for(a=0;a<40;a++)
        ;
}
//********************************************
void SD_2Byte_Write(unsigned int IOData)
{
        unsigned char BitCounter;
               
        for (BitCounter=0;BitCounter<16;BitCounter++)
        {
                sd_clk=0;//CLK Low
               
                if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
                        sd_dao=1;//Do High
                else
                        sd_dao=0;//Do Low
                               
                sd_clk=1;//CLK High
                Delay5us();
               
                IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
        }
}
//********************************************
void SD_Write(unsigned int IOData)
{
        unsigned char BitCounter;
        IOData=IOData<<8;
       
        for (BitCounter=0;BitCounter<8;BitCounter++)
        {
                sd_clk=0;//CLK Low
               
                if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
                        sd_dao=1;//Do High
                else
                        sd_dao=0;//Do Low
                               
                sd_clk=1;//CLK High
                Delay5us();
               
                IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
        }
}
//********************************************
unsigned int SD_2Byte_Read()
{
        unsigned int Buffer;
        unsigned char BitCounter;
        Buffer=0;
       
        for (BitCounter=0;BitCounter<16;BitCounter++)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
                                 //Because the LSB will be damaged, we can not put this line under next line.
                if(sd_dai)
                        Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.               
        }
       
        return Buffer;
}
//********************************************
unsigned int SD_Read()
{
        unsigned int Buffer;
        unsigned char BitCounter;
        Buffer=0xffff;
       
        for (BitCounter=0;BitCounter<8;BitCounter++)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
                                 //Because the LSB will be damaged, we can not put this line under next line.
                if(sd_dai)
                        Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.               
        }
       
        return Buffer;
}
//********************************************
unsigned int SD_CMD_Write(unsigned int CMDIndex,unsigned long CMDArg,unsigned int ResType,unsigned int CSLowRSV)//ResType:Response Type, send 1 for R1; send 2 for R1b; send 3 for R2.
{        //There are 7 steps need to do.(marked by -)
        unsigned int temp,Response,Response2,CRC,MaximumTimes;
        Response2=0;
        MaximumTimes=10;
        CRC=0x0095;//0x0095 is only valid for CMD0
        if (CMDIndex!=0) CRC=0x00ff;
       
        sd_cse=0;// CS Low
       
        SD_2Byte_Write(((CMDIndex|0x0040)<<8)+(CMDArg>>24));// Transmit Command_Index & 1st Byte of Command_Argument.
        SD_2Byte_Write((CMDArg&0x00ffff00)>>8);                                // 2nd & 3rd Byte of Command_Argument
        SD_2Byte_Write(((CMDArg&0x000000ff)<<8)+CRC);                // 4th Byte of Command_Argument & CRC only for CMD0
       
        sd_dao=1;// Do High
                                                // Restore Do to High Level
       
       for (temp=0;temp<8;temp++)// Provide 8 extra clock after CMD
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        switch (ResType)// wait response
        {
                case 1://R1
                                {
                                        do
                                                Response=SD_Read();
                                        while (Response==0xffff);
                                        break;
                                }
                case 2://R1b
                                {
                                        do
                                                Response=SD_Read();
                                        while (Response==0xffff);//Read R1 firstly
                                       
                                        do
                                                Response2=SD_Read()-0xff00;
                                        while (Response2!=0);//Wait until the Busy_Signal_Token is non-zero
                                        break;       
                                }
                case 3: Response=SD_2Byte_Read();break;//R2
        }
       
        if (CSLowRSV==0) sd_cse=1;// CS High (if the CMD has data block response CS should be kept low)
       
       for (temp=0;temp<8;temp++)// Provide 8 extra clock after card response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
        return Response;
}
//********************************************
unsigned int SD_Reset_Card()
{
        unsigned int temp,MaximumTimes;
        MaximumTimes=10;
       
        for (temp=0;temp<80;temp++)//Send 74+ Clocks
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
               
        return SD_CMD_Write(0x0000,0x00000000,1,0);//Send CMD0
}
//********************************************
unsigned int SD_Initiate_Card()//Polling the card after reset
{
        unsigned int temp,Response,MaximumTimes;
        MaximumTimes=50;
       
        for(temp=0;temp<MaximumTimes;temp++)
        {
                Response=SD_CMD_Write(0x0037,0x00000000,1,0);//Send CMD55
                Response=SD_CMD_Write(0x0029,0x00000000,1,0);//Send ACMD41
                if (Response==0xff00)
                        temp=MaximumTimes;
        }

        return Response;
}
//********************************************
unsigned int SD_Get_CardInfo()//Read CSD register
{
        unsigned int temp,Response,MaximumTimes;
        MaximumTimes=50;
       
        for(temp=0;temp<MaximumTimes;temp++)
        {
                Response=SD_CMD_Write(9,0x00000000,1,1);//Send CMD9
                if (Response==0xff00)
                        temp=MaximumTimes;
        }
       
       for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        for (temp=0;temp<8;temp++) ReadBuffer=SD_2Byte_Read();//Get the CSD data
       
        for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        sd_cse=1;//CS_High()
       
        for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        BlockNR=((ReadBuffer<<2)&0x0fff)+((ReadBuffer>>14)&0x0003)+1;//Calcuate MULT
        BlockNR=BlockNR*(0x0002<<(((ReadBuffer<<1)&0x0007)+((ReadBuffer>>15)&0x0001)+1));//Calcuate Block_Number
        return Response;
}
//********************************************
unsigned int SD_Overall_Initiation()
{
        unsigned int Response,Response_2;
        Response=0x0000;
        Response_2=0xff00;
       
        sd_dao=1;// Do High
                                                // Do must be High when there is no transmition
        do
                Response=SD_Reset_Card();// Send CMD0
        while (Response!=0xff01);
       
        if (Response!=0xff01) Response_2+=8;
       
        //Response=SD_CMD_Write(8,0x00000000,1,0);//Send CMD8
       
        Response=SD_Initiate_Card();// Send CMD55+ACMD41
        if (Response==0xff00)
                ;
        else
                {
                Response_2+=4;
                ;
                }
       
        do
                Response=SD_Get_CardInfo();// Read CSD
        while (Response!=0xff00);
        if (Response==0xff01) Response_2+=2;
       
        return Response_2;
//        0000|0000||0000|0000 Response_2
//                  |||_CSD Fail
//                  ||__CMD55+ACMD41 Fail
//                  |___CMD0 Fail
}
//********************************************
unsigned int SD_Get_CardID()//Read CID register
{
        unsigned int temp,Response,MaximumTimes;
        MaximumTimes=10;
       
        for(temp=0;temp<MaximumTimes;temp++)
        {
                Response=SD_CMD_Write(10,0x00000000,1,1);//Send CMD9
                if (Response==0xff00)
                        temp=MaximumTimes;
        }
       
       for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        for (temp=0;temp<8;temp++) ReadBuffer=SD_2Byte_Read();//Get the CID data
       
        for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        sd_cse=1;//CS_High()
       
        for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        return Response;
}
//********************************************
unsigned int Read_Single_Block(unsigned long int BlockAddress)
{
        unsigned int temp,Response,MaximumTimes;
        MaximumTimes=10;
       
        if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range?
       
        for(temp=0;temp<MaximumTimes;temp++)
        {
                Response=SD_CMD_Write(17,BlockAddress,1,1);//Send CMD17
                if (Response==0xff00)
                        temp=MaximumTimes;
        }
       
        while (SD_Read()!=0xfffe) {;}
        //这里为了使只有512byte的单片机能够读写SD卡,特意节省了RAM的使用量,每次读写只有两个重复的128byte
        //如果您使用的单片机拥有1K以上的RAM请将"%128"去掉       
        for (temp=0;temp<256;temp++) ReadBuffer=SD_2Byte_Read();//Get the readed data
       
        for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        sd_cse=1;//CS_High()
       
        for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        return Response;
}
//********************************************
unsigned int Write_Single_Block(unsigned long int BlockAddress)
{
        unsigned int temp,Response,MaximumTimes;
        MaximumTimes=10;
       
        if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range?
       
        for(temp=0;temp<MaximumTimes;temp++)
        {
                Response=SD_CMD_Write(24,BlockAddress,1,1);//Send CMD24
                if (Response==0xff00)
                        temp=MaximumTimes;
        }
       
        for (temp=0;temp<8;temp++)//Provide 8 extra clock after CMD response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        SD_Write(0x00fe);//Send Start Block Token
        //这里为了使只有512byte的单片机能够读写SD卡,特意节省了RAM的使用量,每次读写只有两个重复的128byte
        //如果您使用的单片机拥有1K以上的RAM请将"%128"去掉
        for (temp=0;temp<256;temp++) SD_2Byte_Write(WriteBuffer);//Data Block
        SD_2Byte_Write(0xffff);//Send 2 Bytes CRC
       
        Response=SD_Read();
        while (SD_Read()!=0xffff) {;}
       
        sd_cse=1;//CS_High()
       
        for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
        {
                sd_clk=0;//CLK Low
                Delay5us();
                sd_clk=1;//CLK High
                Delay5us();
        }
       
        return Response;
}

/* 串行通信初始化*/
void UartInit()
{
        SCON = 0x50;                  // uart 模式1 (8 bit), REN=1;
        TMOD = TMOD | 0x20 ;      // 定时器1 模式2;
//        TH1= 0xF7;                // 9600 Bds at 32MHz
//        TL1= 0xF7;       


        TH1= 0xFD;                // 9600 Bds at 11.059MHz
        TL1= 0xFD;       
//        TH1= 0xFA;                // 9600 Bds at 22.1184MHz
//        TL1= 0xFA;       

        ES = 1;                   //允许uart中断;
        EA = 1;                          //允许CPU中断;
        TR1 = 1;                //运行定时器1:
}
       
void send_char_com(unsigned char ch)
{
    SBUF=ch;
    while(TI==0);
    TI=0;
}

//向串口发送一个字符串
void send_string_com(unsigned char *str,unsigned int len)
{
    unsigned char k=0;

    do
    {
      send_char_com(*(str + k));
      k++;
    } while(k <len);

}

main()
{
        unsigned int Data,M_Response;
    unsigned char i;

        //初始化要写入的数据
    for(i=0;i<128;i++)
        {
      if (i < 64)
          {
          WriteBuffer=0x4141;
          }
          else
          {
                  WriteBuffer=0x4242;
          }
        }

    UartInit();
        TI = 0;       
    M_Response=0x0000;
        M_Response=SD_Overall_Initiation();
        M_Response=SD_CMD_Write(16,512,1,0);
        Data=SD_Get_CardID();
        Write_Single_Block(0x0000);
    Read_Single_Block(0x0000);

    for(i=0; i<128; i++)
        {        
   send_char_com(ReadBuffer>>8); //向串口发送高8位数据
   send_char_com(ReadBuffer );
        }
       
        while(1);        
}

矿坛铁粉 发表于 2020-10-31 21:29:19

分立元件 发表于 2020-10-31 21:52:32

矿坛铁粉 发表于 2020-10-31 21:29
你问问卖家这是啥时候的代码,是否支持大容量的SD。
早期的单片机SD卡驱动大多是走SPI,最大支持4GB。

卖家也无法解决:L :L :L

矿坛铁粉 发表于 2020-10-31 21:59:25

分立元件 发表于 2020-10-31 22:10:37

矿坛铁粉 发表于 2020-10-31 21:59
因为最初sd卡的通讯协议只支持最大4g的卡,后来容量越做越大升级了一次协议。。。

那要找4G以下的卡试试才行了!

iffi123 发表于 2020-11-1 00:57:40

本帖最后由 iffi123 于 2020-11-1 01:18 编辑

TF我最近在玩,你这个小板只支持SPI模式,我测试开始用的4G卡,速度太慢, 现在改用16G卡

实际上我都是根据资料,完全自己写的代码,如果出错也比较好查, 高频读写都正常,不过我现在对写的速度比较敏感,想办法提高

巧的是,我的板子也有一块串行flash, W25Q128,华邦的芯片, 容量16Mbyte, 这个比tf卡简单,我用来存取音频数据,蛮有意思的, 如果是16bit/44.1kHz格式, 可以存储94秒,音质非常好,说明数据没有丢失:D

分立元件 发表于 2020-11-1 01:05:02

iffi123 发表于 2020-11-1 00:57
TF我最近在玩,你这个板只支持SPI模式,从4G开始,SD规范版本2.0以上

实际上我都是自己写的代码,如果出 ...

你玩多大的TF卡,都玩通了吧

iffi123 发表于 2020-11-1 01:13:20

本帖最后由 iffi123 于 2020-11-1 01:17 编辑

分立元件 发表于 2020-11-1 01:05
你玩多大的TF卡,都玩通了吧

读写功能倒是调通了, 如果实时写入音频,程序处理还存在点问题,速度有点跟不上会丢数据, 还要修改,毕竟实时记录24bit/96kHz对速度要求高,写入速度要700Kbyte/s,SPI本身又是阉割模式,速度比起SD模式差的远。支持SD模式的cpu不多

双11准备再买一块64G, 卡本身写入速度高对程序来说降低难度

分立元件 发表于 2020-11-1 01:45:06

iffi123 发表于 2020-11-1 01:13
读写功能倒是调通了, 如果实时写入音频,程序处理还存在点问题,速度有点跟不上会丢数据, 还要修改, ...

能给个TF卡测试程序吗?

iffi123 发表于 2020-11-1 07:14:56

分立元件 发表于 2020-11-1 01:45
能给个TF卡测试程序吗?

stm32的,你用不了

分立元件 发表于 2020-11-1 08:54:01

iffi123 发表于 2020-11-1 07:14
stm32的,你用不了

好吧,在找找了,不行的话只能自己写一个试试
页: [1]
查看完整版本: 求51单片机SD卡和25Q80的驱动程序!