-
2019-12-06 18:24:33
stm32 SPI读写储存卡(MicroSD TF卡)
博客原址:http://www.coderframe.com/Info/index/id/123.html
简述
花了较长的时间,来弄读写储存卡(大部分教程讲的比较全但是不是很容易懂),这里希望我的代码经验能够帮助到你。操作分析及实现
0.整个流程
1、上电以后储存卡的初始化
2、如何进行读写
1.上电以后储存卡的初始化
上电给MicroSD卡至少74个时钟信号 发送CDM0 (x041)复位 发送CMD1 让MicroSD卡进入SPI模式
2.如何进行读写
这里主要对1,3进行详细的讨论 你需要知道的是spi通信是怎样进行的就可以完成以上连个任务了
3.下面是具体的过程
//首先看一下我们的函数 char SD_Init(void); //初始化函数 char WriteSectorToMicroSD(long addr,char *buff);//写一个扇区 512bit char ReadSectorFromMicroSD(long sector,char *buffer);// 读一个扇区
下面是主函数里的的部分
//定义读入缓冲区 extern char MicroSDDataBuff[512]; void MicroSDTest() { //这是在内存卡初始化以后的测试进行读写如果不成功还是从读写序列号开始吧 //WriteSectorToMicroSD(2,"Hello I here did you find me!!!"); delay_ms(200); ReadSectorFromMicroSD(2,MicroSDDataBuff); //printf("MicroSD read is:%s!!!!\n\n",MicroSDDataBuff); } int main() { char arr[100]={0},key=-1; int x=0,y=0; SPI2_Init(); uart_init(115200); delay_init(); SD_Init(); MicroSDTest(); printf("Read:%s",MicroSDDataBuff); while(1); }
//下面是MicroSD的初始化及读写函数 #define MicroSD_CS_SET GPIO_SetBits(GPIOB,GPIO_Pin_0) #define MicroSD_CS_RESET GPIO_ResetBits(GPIOB,GPIO_Pin_0) char MicroSDDataBuff[512]={0};//一个扇区的大小 char SentCommandToMicroSD(char cmd,int data,char crc) { char result=0,times=0; MicroSD_CS_SET;//禁止SD卡片选 同步时钟 SPI1_ReadWriteByte(0xff); MicroSD_CS_RESET;//开始传输 SPI1_ReadWriteByte(cmd); for(times=0;times<4;times++) { SPI1_ReadWriteByte((data>>24)&0xff); data<<=8; } SPI1_ReadWriteByte(crc); SPI1_ReadWriteByte(0xff); //八个时钟 times=0; do{ //读取后8位 result = SPI1_ReadWriteByte(0xFF); times++; } while((result==0xff)&&(times<200)); return result; } //初始化化不是很稳定也就是说明传输数据可能不是很稳定 char SD_Init(void) { char i,temp=0; //char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95}; int retry=0; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PB0 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB0 GPIO_SetBits(GPIOB,GPIO_Pin_0); //初始化SPI1 SPI1_Init(); MicroSD_CS_SET; //发送至少74个时钟信号,数据顺便填写 for (i=0;i<0x2f;i++){SPI1_ReadWriteByte(0xff);} //为了能够成功写入CMD0,在这里写200次 do { temp=SentCommandToMicroSD(0x40,0,0x95); retry++; if(retry>800) { //超过200次 //CMD0 Error! return(INIT_CMD0_ERROR); printf("Init MicroSD CMD0 Error!!!Back:%d\n\n",temp); return 0; } } while(temp!=0x01); //回应01h,停止写入 printf("Reset MicroSD successfully!!!times:%d\n\n",retry); //发送CMD1到SD卡 retry=0; do{ //为了能成功写入CMD1,写100次 temp=SentCommandToMicroSD(0x41,0,0xff); retry++; if(retry>800) { //超过100次 printf("Init 1MicroSD CMD1 Error!!!Back:%d\n\n",temp); return 0; } } while(temp!=0x00);//回应00h停止写入 MicroSD_CS_SET; //片选无效 printf("Init MicroSD sent CMD1 successfully!!!times:%d\n\n",retry); //更换更快的SPI速率 SPI1_SetSpeed(SPI_BaudRatePrescaler_4); return 0; } char WriteSectorToMicroSD(long addr,char *buff) { int tmp,retry; unsigned int i; addr = addr << 9; //addr = addr * 512 //写命令24到SD卡中去 retry=0; do{ //为了可靠写入,写100次 tmp=SentCommandToMicroSD(0x58,addr,0xff); retry++; if(retry>800) { printf("Write CMD58 Error!!!\n\r"); return 1; //send commamd Error! } } while(tmp!=0); //在写之前先产生100个时钟信号 for (i=0;i<100;i++) { SPI1_ReadWriteByte(0xff); } //写入开始字节 SPI1_ReadWriteByte(0xfe); //现在可以写入512个字节 for (i=0;i<512;i++) { SPI1_ReadWriteByte(*buff); buff++; } //CRC-Byte spi模式只需要在前两个命令发送,后面的crc自动不校验 SPI1_ReadWriteByte(0xFF); //Dummy CRC SPI1_ReadWriteByte(0xFF); //CRC Code tmp=SPI1_ReadWriteByte(0xff); // read response if((tmp & 0x1F)!=0x05) // 写入的512个字节是未被接受 { MicroSD_CS_SET; printf("Write data didn't accept by MicroSD\n\r"); return 1; //Error! } //等到SD卡不忙为止 //因为数据被接受后,SD卡在向储存阵列中编程数据 while (SPI1_ReadWriteByte(0xff)!=0xff); //禁止SD卡 写入成功 MicroSD_CS_SET; return 0; } char ReadSectorFromMicroSD(long sector,char *buffer) { int retry; //命令16 int times=0; //unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; unsigned char temp; //地址变换 由逻辑块地址转为字节地址 sector = sector << 9; //sector = sector * 512 //将命令16写入SD卡 retry=0; do{ //为了保证写入命令 一共写100次 temp=SentCommandToMicroSD(0x51,sector,0xff); retry++; if(retry>800) { printf("Read sector from MicroSD is failed!!\n\r"); return 1; //block write Error! } } while(temp!=0); //Read Start Byte form MMC/SD-Card (FEh/Start Byte) //Now data is ready,you can read it out. while (SPI1_ReadWriteByte(0xff) != 0xfe); for(times=0;times<512;times++) { MicroSDDataBuff[times]=SPI1_ReadWriteByte(0xff); } //禁止SD卡 读出完成 MicroSD_CS_SET; return 0; }
更多相关内容 -
单片机实现的SD卡读写模块的完整工程,含原理图,代码,说明文档等
2018-11-17 19:47:40单片机实现的SD卡读写模块的完整工程,含原理图,代码,说明文档等 -
SD卡读卡器电路原理图
2010-05-14 17:44:59D:\Downloads\Alcor AU6331方案SD卡读卡器电路原理图.rar -
MicroSD卡(TF卡)SPI模式实现方法
2018-03-19 10:22:19现在我们手机的内存卡多为Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常见。自己曾经也想写写SD卡的读取程序,但又不想特地再去买个SD卡,这时想起手机内存卡不是和SD卡很像吗?在网上查了以后发现SD卡 和Micro SD...原文:https://www.cnblogs.com/einstein-2014731/p/4885382.html
现在我们手机的内存卡多为Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常见。自己曾经也想写写SD卡的读取程序,但又不想特地再去买个SD卡,这时想起手机内存卡不是和SD卡很像吗?在网上查了以后发现SD卡
和Micro SD卡其实也就大小和引脚不一样,它们的操作其实是一样的,所以网上的SD卡读写代码其实可以直接拿来用。关于SD卡和Micro SD卡的引脚定义和不同可见下两表:我们可以发现Micro SD卡只有8个引脚是因为比SD卡少了一个Vss。当然你也可以买个卡套套在Micro SD卡上,这样一来大小就和SD卡一样大,这时候卡套上的9个引脚就和SD卡一样了,你可以完全当做SD卡来操作。
spi下电路的连接非常简单,接上电源线Vdd和地线Vss,再接上spi的CS,SCLK,DI(MOSI)和DO(MISO)就可以了,其他引脚可以 放空。注意SD卡的电源和操作电压都为2.7-3.6V,5V的单片机要进行电平转换或串电阻限流。
还有记得SD卡的CS,SCLKh和DI要用 10~100K的电阻上拉。我是套了卡套接的电路,因为Micro SD卡的引脚太密了,不好焊接,SD卡相对引脚好焊。因为没有卡座,而且也没专门的PCB我就直接焊到卡套上,诶牺牲了一个卡套。
下面是我自己画的电路 图:
上面Micro SD卡的硬件电路就好了,下面我们讲讲Micro SD卡的软件驱动和指令集。
SD卡的命令格式如下,6字节共48位,传输时最高位(MSB)先传输:
SD卡的command(命令)占6 bit,一般叫CMDx或ACMDx,比如CMD1就是1,CMD13就是13,ACMD41就是41,依此类推。Command Argument(命令参数)占4 byte,并不是所有命令都有参数,没有参数的话该位一般就用置0。
最后一个字节由7 bit CRC校验位和1 bit停止位组成。在SPI模式下,CRC是被忽略的,可以都置1或置0.但是发送CMD0时要记得加上CRC,即最后1字节为0x95(因为发送 CMD0时还未进入SPI模式,PS:CMD8也要,
但一般大家都把发送CMD8省略了)。每次发送完一次命令后,SD卡都会有回应。SD卡的回应有多种格式,1字节的R1,2字节的R2等,不过一般在SPI模式中我们只用到R1,下面介绍R1的格式:
关于SD卡SPI和command的发送要注意以下几点:
1.SD卡的SPI总线,在读入数据时SD卡的SPI是CLK的上升沿输入锁存,输出数据也是在上升沿。
2.向SD卡写入一个CMD或者ACMD指令的过程是这样的: 首先使CS为低电平,SD卡使能;其次在SD卡的Din写入指令;写入指令后还要附加8个填充时钟,是SD卡完成内部操作;之后在SD卡的Dout上接受回应;回应接受完毕使CS为低电平,再附加8个填充时钟。
3.在SD卡的Din没有数据写入时,应使Din
保持高电平。关于这一点我可吃透了苦头,本来也记得要保持高电平的,结果不知怎的鬼使神差的置0拉低了。结果程序出现了各种奇怪的貌似偶然的错误,比如连
续两次复位会有一次失败,单步调试成功全速运行又会失败。总之在这个过程中我对时序进行各种改变,每次解决一个问题后又会有新的问题出现,多少次动摇了我
对MicroSD卡和SD卡的操作是一样的这个看法。因为这个低级的错误耽误了我三四天,看来细心很重要啊!我已经不止一次因为不细心浪费大量时间了,希
望大家也引以为戒。好了,现在SD卡的命令和回应清楚了,我们下面讲讲SD卡的复位,初始化和读写方法。
复位方法:
1.拉高CS,发送至少74个clk周期来使SD卡达到正常工作电压和进行同步
2.选低CS,发送CMD0,需要收到回应0x01表示成功进入idle状态
3.拉高CS,发送8个时钟
复位时序图:
初始化:
复位成功后,SD卡就进入了SPI模式,接着应该进行初始化。初始化说白了有两种方法:(1)发送CMD1,(2)发送CMD55+ACMD41。
我从网 上查的资料可以看到这种说法:如果是MMC卡就发CMD1,SD卡则发CMD55+ACMD41。但是关于Micro SD卡要发哪种却讲的不太清楚,网上用这两种方法都有人成功过,但有的都成功不了。
我自己也碰到了这种问题,刚开始拿了自己手机上的写着Nokia的 2GB的Micro SD卡(应该是杂牌的)初始化了两天也没成功,快要放弃的时候想起来为什么不换张试试呢,于是就找室友借了他的手机内存卡,
是2GB的Apacer的 Micro SD卡(当然也可能是杂牌的,室友买那卡的地方一般都是卖各种廉价电子产品的,大家都知道是杂牌的),结果一试就成功了。后来我用了令一种方法发现也可以 初始化,
也就是说两种方法都可以初始化成功。但我的那种怎么就不行呢?难道不是所有Micro SD卡都支持SPI模式。我在网上百度了半天也不能确定是不是所有Micro SD卡都支持SPI模式。
但我想,现在Micro SD卡的生产公司很多,而且你也并不能保证你的Micro SD卡不是杂牌的。你并不知道生产厂家进行了那些改变,因为确实有些厂家生产的SD卡精简了一些命令。所以初始化的时候建议两种都试一下,
不过我记得SD 卡的说明书上推荐使用第二种方法。
下面是初始化方法:
(1)使用CMD1
发送CMD1,收到0x00表示成功
时序图如下:
读多块方法:
1.发送CMD18读,收到0x00表示成功
2.连续读直到读到开始字节0xFE
3.读512字节
4.读两个CRC字节
5.如果还想读下一扇区,重复2-4
6.发送CMD12来停止读多块操作
写单块和多块:
SD卡用CMD24和CMD25来写单块和多块,参数的定义和读操作是一样的。
写单块方法:
1.发送CMD24,收到0x00表示成功
2.发送若干时钟
3.发送写单块开始字节0xFE
4.发送512个字节数据
5.发送2字节CRC(可以均为0xff)
6.连续读直到读到XXX00101表示数据写入成功
7.继续读进行忙检测(读到0x00表示SD卡正忙),当读到0xff表示写操作完成
写单块时序图:
写多块方法:
1.发送CMD25,收到0x00表示成功
2.发送若干时钟
3.发送写多块开始字节0xFC
4.发送512字节数据
5.发送两个CRC(可以均为0xff)
6.连续读直到读到XXX00101表示数据写入成功
7.继续读进行忙检测,直到读到0xFF表示写操作完成
8.如果想读下一扇区重复2-7步骤
9.发送写多块停止字节0xFD来停止写操作
10.进行忙检测直到读到0xFF
-
TF卡 MicroSD卡使用信息
2018-06-29 14:28:39TF卡 或者SD卡封装,带自谈的TF卡 或者SD卡封装,带自谈的
SD卡介绍
对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的存储器结构、存储单元组织方式等内容。要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写,并对其读写速度进行了评估。下面先来讲解SD卡的读写时序。
覆写保护开关
在SD卡的右面通常有一个开关,即是覆写保护开关,当覆写保护开关拨下时,SD卡将受到覆写保护,资料只能阅读。当覆写保护开关在上面位置,便可以覆写资料。由于这保护开关是选择性的,有些品牌的SD卡没有此保护掣。
驱动模式
SD卡有两种驱动模式:SPI模式与SDIO模式。它们所使用的接口信号是不同的。在SPI模式下,只会用到SD卡的4根信号线,即CS、DI、SCLK与DO(分别是SD卡的片选、数据输入、时钟与数据输出)。
传输模式
SD卡共支持三种传输模式:SPI模式(独立序列输入和序列输出),1位SD模式(独立指令和数据通道,独有的传输格式), 4位SD模式(使用额外的针脚以及某些重新设置的针脚。支持四位宽的并行传输)。
(1) SD卡的引脚定义:及内部结构
SD卡引脚功能详述:
虽然标准SD卡是九脚,但原理图是SD卡座不是SD卡!!,所以原理图中一般都是11脚或更多。
一般10脚是检测卡是否插入,11脚是卡写保护的检测,再有其它引脚就是用于固定卡座的脚了,其实简单应用这两个脚都可以不要管的,这就是为什么SD卡原理图中的引脚版本不同引脚数目也不同了。
SDIO连接模式
SPI连接模式
注:S:电源供给 I:输入 O:采用推拉驱动的输出
PP:采用推拉驱动的输入输出SD卡支持两种总线方式:SD方式与SPI方式。其中SD方式采用6线制,使用CLK、CMD、DAT0~DAT3进行数据通信。而SPI方式采用4线制,使用CS、CLK、DataIn、DataOut进行数据通信。SD方式时的数据传输速度与SPI方式要快,采用单片机对SD卡进行读写时一般都采用SPI模式。采用不同的初始化方式可以使SD卡工作于SD方式或SPI方式。这里只对其SPI方式进行介绍。
(2) SPI方式驱动SD卡的方法
SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。从应用的角度来看,采用SPI接口的好处在于,很多单片机内部自带SPI控制器,不光给开发上带来方便,同时也见降低了开发成本。然而,它也有不好的地方,如失去了SD卡的性能优势,要解决这一问题,就要用SD方式,因为它提供更大的总线数据带宽。SPI接口的选用是在上电初始时向其写入第一个命令时进行的。以下介绍SD卡的驱动方法,只实现简单的扇区读写。
1) 命令与数据传输
1. 命令传输
SD卡自身有完备的命令系统,以实现各项操作。命令格式如下:命令的传输过程采用发送应答机制,过程如下:
每一个命令都有自己命令应答格式。在SPI模式中定义了三种应答格式,如下表所示:
写命令的例程:
//-----------------------------------------------------------------------------------------------
向SD卡中写入命令,并返回回应的第二个字节
//-----------------------------------------------------------------------------------------------
unsigned char Write_Command_SD(unsigned char *CMD)
{undefined
unsigned char tmp;
unsigned char retry=0;
unsigned char i;//禁止SD卡片选
SPI_CS=1;
//发送8个时钟信号
Write_Byte_SD(0xFF);
//使能SD卡片选
SPI_CS=0;//向SD卡发送6字节命令
for (i=0;i<0x06;i++)
{undefined
Write_Byte_SD(*CMD++);
}
//获得16位的回应
Read_Byte_SD(); //read the first byte,ignore it.
do
{ //读取后8位
tmp = Read_Byte_SD();
retry++;
}
while((tmp==0xff)&&(retry<100));
return(tmp);
}2) 初始化
SD卡的初始化是非常重要的,只有进行了正确的初始化,才能进行后面的各项操作。在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。在初始化成功后,应尽量提高SPI的速率。在刚开始要先发送至少74个时钟信号,这是必须的。在很多读者的实验中,很多是因为疏忽了这一点,而使初始化不成功。随后就是写入两个命令CMD0与CMD1,使SD卡进入SPI模式
初始化时序图:初始化例程:
//--------------------------------------------------------------------------
初始化SD卡到SPI模式
//--------------------------------------------------------------------------
unsigned char SD_Init()
{
unsigned char retry,temp;
unsigned char i;
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
SD_Port_Init(); //初始化驱动端口
Init_Flag=1; //将初始化标志置1for (i=0;i<0x0f;i++)
{undefined
Write_Byte_SD(0xff); //发送至少74个时钟信号
}
//向SD卡发送CMD0
retry=0;
do
{ //为了能够成功写入CMD0,在这里写200次
temp=Write_Command_SD(CMD);
retry++;
if(retry==200)
{ //超过200次
return(INIT_CMD0_ERROR);//CMD0 Error!
}
}
while(temp!=1); //回应01h,停止写入
//发送CMD1到SD卡
CMD[0] = 0x41; //CMD1
CMD[5] = 0xFF;
retry=0;
do
{ //为了能成功写入CMD1,写100次
temp=Write_Command_SD(CMD);
retry++;
if(retry==100)
{ //超过100次
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp!=0);//回应00h停止写入
Init_Flag=0; //初始化完毕,初始化标志清零
SPI_CS=1; //片选无效
return(0); //初始化成功
}
3) 读取CID
CID寄存器存储了SD卡的标识码。每一个卡都有唯一的标识码。
CID寄存器长度为128位。它的寄存器结构如下:
它的读取时序如下:
与此时序相对应的程序如下:
//------------------------------------------------------------------------------------
读取SD卡的CID寄存器 16字节 成功返回0
//-------------------------------------------------------------------------------------
unsigned char Read_CID_SD(unsigned char *Buffer)
{undefined
//读取CID寄存器的命令
unsigned char CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
unsigned char temp;
temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}4)读取CSD
CSD(Card-Specific Data)寄存器提供了读写SD卡的一些信息。其中的一些单元可以由用户重新编程。具体的CSD结构如下:读取CSD 的时序:
相应的程序例程如下:
//-----------------------------------------------------------------------------------------
读SD卡的CSD寄存器 共16字节 返回0说明读取成功
//-----------------------------------------------------------------------------------------
unsigned char Read_CSD_SD(unsigned char *Buffer)
{
//读取CSD寄存器的命令
unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
unsigned char temp;
temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}4)
读取SD卡信息
综合上面对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。如下:
//-----------------------------------------------------------------------------------------------
//返回
// SD卡的容量,单位为M
// sector count and multiplier MB are in
u08 == C_SIZE / (2^(9-C_SIZE_MULT))
// SD卡的名称
//-----------------------------------------------------------------------------------------------
void SD_get_volume_info()
{
unsigned char i;
unsigned char c_temp[5];
VOLUME_INFO_TYPE SD_volume_Info,*vinf;
vinf=&SD_volume_Info; //Init the pointoer;
/读取CSD寄存器
Read_CSD_SD(sectorBuffer.dat);
//获取总扇区数
vinf->sector_count = sectorBuffer.dat[6] & 0x03;
vinf->sector_count <<= 8;
vinf->sector_count += sectorBuffer.dat[7];
vinf->sector_count <<= 2;
vinf->sector_count += (sectorBuffer.dat[8] & 0xc0) >> 6;
// 获取multiplier
vinf->sector_multiply = sectorBuffer.dat[9] & 0x03;
vinf->sector_multiply <<= 1;
vinf->sector_multiply += (sectorBuffer.dat[10] & 0x80) >> 7;
//获取SD卡的容量
vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
// get the name of the card
Read_CID_SD(sectorBuffer.dat);
vinf->name[0] = sectorBuffer.dat[3];
vinf->name[1] = sectorBuffer.dat[4];
vinf->name[2] = sectorBuffer.dat[5];
vinf->name[3] = sectorBuffer.dat[6];
vinf->name[4] = sectorBuffer.dat[7];
vinf->name[5] = 0x00; //end flag
}
以上程序将信息装载到一个结构体中,这个结构体的定义如下:
typedef struct SD_VOLUME_INFO
{ //SD/SD Card info
unsigned int size_MB;
unsigned char sector_multiply;
unsigned int sector_count;
unsigned char name[6];
} VOLUME_INFO_TYPE;TF卡介绍
Micro SD Card,原名Trans-flashCard(TF卡),2004年正式更名为MicroSD Card,由SanDisk(闪迪)公司发明。MicroSD卡是一种极细小的快闪存储器卡,其格式源自SanDisk创造,原本这种记忆卡称为T-Flash,及后改称为TransFlash;而重新命名为MicroSD的原因是因为被SD协会(SDA) 采立。
它的体积为15mm x 11mm x1mm,差不多相等于手指甲的大小,是现时最细小的记忆卡。它也能通过SD转接卡来接驳于SD卡插槽中使用。现时MicroSD卡提供128MB、256MB、512MB、1G、2G、4G、8G、16G、32G、64G、128G的容量(MWC2014 世界移动通信大会期间,SanDisk(闪迪)打破了储存卡最高64GB容量的传统,正式发布了一款容量高达128GB的Micro SD XC 储存卡。
MicroSD的体积更小且可以转换SD卡使用,TF卡的电路和引脚和SD卡是一样的。
TF卡的PCB封装
从下图可以看出,靠近圆圈处的那个引脚没有和TF相连。
所以做TF封装和电路,9脚悬空
-
基于ARM裸机的知识点总结(10)------- SD卡启动详解
2020-04-04 17:31:02内存和外存的区别:一般是把这种RAM(random access memory,随机访问存储器,特点是任意字节读写,掉电丢失)叫内存,把ROM(read only memory,只读存储器,类似于Flash SD卡之类的,用来存储东西,掉电不丢失,不能...一,各种存储设备的差异
内存和外存的区别:一般是把这种RAM(random access memory,随机访问存储器,特点是任意字节读写,掉电丢失)叫内存,把ROM(read only memory,只读存储器,类似于Flash SD卡之类的,用来存储东西,掉电不丢失,不能随机地址访问,只能以块为单位来访问)叫外存。
1.主流的外存设备的发展
产品名称 存储技术 优点 缺点 软盘、硬盘、光盘、CD、磁带 存储原理大部分为磁存储 技术成熟、价格便宜 读写速度慢、可靠性差 纯粹的Flash:NandFlash、NorFlash 闪存技术,是利用电学原理来存储1和0 闪存设备没有物理运动(硬盘中的磁头),所以读写速度可以很快,且无物理损耗 1、读写接口时序比较复杂。2、内部无坏块处理机制,需要SoC自己来管理Flash的坏块;3、各家厂家的Flash接口不一致,甚至同一个厂家的不同型号、系列的Flash接口都不一致,这就造成产品升级时很麻烦。 SD卡、MMC卡、MicroSD、TF卡 这些卡其实内部就是Flash存储颗粒,比直接的Nand芯片多了统一的外部封装和接口。 卡都有统一的标准,譬如SD卡都是遵照SD规范来发布的。这些规范规定了SD卡的读写速度、读写接口时序、读写命令集、卡大小尺寸、引脚个数及定义。这样做的好处就是不同厂家的SD卡可以通用。 外部扩展卡时间长了卡槽可能会接触不良导致不可靠。 iNand、MoviNand、eSSD 这些东西的本质还是NandFlash内部由Nand的存储颗粒构成,再集成了块设备管理单元,综合了SD卡为代表的各种卡的优势和原始的NandFlash芯片的优势。 1、向SD卡学习,有统一的接口标准(包括引脚定义、物理封装、接口时序)。2、向原始的Nand学习,以芯片的方式来发布而不是以卡的方式;3、内部内置了Flash管理模块,提供了诸如坏块管理等功能,让Nand的管理容易了起来。 /# 2.SD卡的特点和背景知识
产品 两者的区别 SD卡和MMC卡的关系 (1)MMC标准比SD标准早,SD标准兼容MMC标准。(2)MMC卡可以被SD读卡器读写,而SD卡不可以被MMC读卡器读写。 SD卡和Nand、Nor等Flash芯片差异 (1)SD卡/MMC卡等卡类有统一的接口标准,而Nand芯片没有统一的标准(各家产品会有差异) SD卡与MicroSD的区别 (1)体积大小区别而已,传输与原理完全相同。 SD卡与TF卡的区别 (1)外观上,SD卡大而TF卡小;用途上,SD卡用于数码相机等而TF卡广泛用于手机、GPS等;(2)时间上,SD卡1999年推出,TF卡于2004年推出;SD卡由日本松下、东芝与美国SanDisk共同推出,而TF卡由Motorola与SanDisk共同推出。(3)SD卡有写保护而TF卡没有,TF卡可以通过卡套转成SD卡使用。 二,SD卡的编程接口
SD卡的编程接口
1.SD卡的物理接口
(1)SD卡由9个针脚与外界进行物理连接,这9个脚中有2个地,1个电源,6个信号线。2.SD协议与SPI协议
(1)SD卡与SRAM/DDR/SROM之类的东西的不同:SRAM/DDR/SROM之类的存储芯片是总线式的,只要连接上初始化好之后就可以由SoC直接以地址方式来访问;但是SD卡不能直接通过接口给地址来访问,它的访问需要按照一定的接口协议(时序)来访问。
(2)SD卡虽然只有一种物理接口,但是却支持两种读写协议:SD协议和SPI协议。3.SPI协议特点(低速、接口操作时序简单、适合单片机)
(1)SPI协议是单片机中广泛使用的一种通信协议,并不是为SD卡专门发明的。
(2)SPI协议相对SD协议来说速度比较低。
(3)SD卡支持SPI协议,就是为了单片机方便使用。SD协议特点(高速、接口时序复杂,适合有SDIO接口的SoC)
(1)SD协议是专门用来和SD卡通信的。
(2)SD协议要求SoC中有SD控制器,运行在高速率下,要求SoC的主频不能太低。4.S5PV210的SD/MMC控制器
(1)SD卡内部除了存储单元Flash外,还有SD卡管理模块,我们SoC和SD卡通信时,通过9针引脚以SD协议/SPI协议向SD卡管理模块发送命令、时钟、数据等信息,然后从SD卡返回信息给SoC来交互。工作时每一个任务(譬如初始化SD卡、譬如读一个块、譬如写、譬如擦除····)都需要一定的时序来完成(所谓时序就是先向SD卡发送xx命令,SD卡回xx消息,然后再向SD卡发送xx命令····)
(2)s5pv210的SD卡检测流程图和时钟使能流程图如下:
三,S5PV210的SD卡启动详解
0.首先要知道几种内存和外存的特点
内存 特点 SRAM 静态内存 特点就是容量小、价格高,优点是不需要软件初始化直接上电就能用 DRAM 动态内存 特点就是容量大、价格低,缺点就是上电后不能直接使用,需要软件初始化后才可以使用。 外存 特点 NorFlash 特点是容量小,价格高,优点是可以和CPU直接总线式相连,CPU上电后可以直接读取,所以一般用作启动介质 NandFlash (跟硬盘一样):特点是容量大,价格低,缺点是不能总线式访问,也就是说不能上电CPU直接读取,需要CPU先运行一些初始化软件,然后通过时序接口读写。 1.SoC为何要支持SD卡启动
(1)一个普遍性的原则就是:SoC支持的启动方式越多,将来使用时就越方便,用户的可选择性就越大,SoC的适用面就越广。
(2)SD卡有一些好处:譬如可以在不借用专用烧录工具(类似Jlink)的情况下对SD卡进行刷机,然后刷机后的SD卡插入卡槽,SoC既可启动;譬如可以用SD卡启动进行量产刷机(量产卡)。像我们X210开发板,板子贴片好的时候,内部iNand是空的,此时直接启动无启动;板子出厂前官方刷机时是把事先做好的量产卡插入SD卡卡槽,然后打到iNand方式启动;因为此时iNand是空的所以第一启动失败,会转而第二启动,就从外部SD2通道的SD卡启动了。启动后会执行刷机操作对iNand进行刷机,刷机完成后自动重启(这回重启时iNand中已经有image了,所以可以启动了)。刷机完成后SD量产卡拔掉,烧机48小时,无死机即可装箱待发货。2.SD卡启动的难点在哪里(SRAM、DDR、SDCard)
(1)SRAM、DDR都是总线式访问的,SRAM不需初始化既可直接使用而DDR需要初始化后才能使用,但是总之CPU可以直接和SRAM/DRAM打交道;而SD卡需要时序访问,CPU不能直接和SD卡打交道;NorFlash读取时可以总线式访问,所以Norflash启动非常简单,可以直接启动,但是SD/NandFlash不行。(2)以前只有Norflash可以作为启动介质,台式机笔记本的BIOS就是Norflash做的。后来三星在2440中使用了SteppingStone的技术,让Nandflash也可以作为启动介质。SteppingStone(翻译为启动基石)技术就是在SoC内部内置4KB的SRAM,然后开机时SoC根据OMpin判断用户设置的启动方式,如果是NandFlash启动,则SoC的启动部分的硬件直接从外部NandFlash中读取开头的4KB到内部SRAM作为启动内容。
(3)启动基石技术进一步发展,在6410芯片中得到完善,在210芯片时已经完全成熟。210中有96KB的SRAM,并且有一段iROM代码作为BL0,BL0再去启动BL1(210中的BL0做的事情在2440中也有,只不过那时候是硬件自动完成的,而且体系没有210中这么详细)。
3.S5PV210的启动过程回顾
210内置了一块96KB大小的SRAM(叫iRAM),同时还有一块内置的64KB大小的NorFlash(叫iROM)。
210的启动过程大致是:
第一步:CPU上电后先从内部IROM中读取预先设置的代码(BL0),执行。这一段IROM代码首先做了一些基本的初始化(CPU时钟、关看门狗···)(这一段IROM代码是三星出厂前设置的,三星也不知道我们板子上将来接的是什么样的DRAM,因此这一段IROM是不能负责初始化外接的DRAM的,因此这一段代码只能初始化SoC内部的东西);然后这一段代码会判断我们选择的启动模式(我们通过硬件跳线可以更改板子的启动模式),然后从相应的外部存储器去读取第一部分启动代码(BL1,大小为16KB)到内部SRAM。
第二步:从IRAM去运行刚上一步读取来的BL1(16KB),然后执行。BL1负责初始化NandFlash,然后将BL2读取到IRAM(剩余的80KB)然后运行
第三步:从IRAM运行BL2,BL2初始化DRAM,然后将OS读取到DRAM中,然后启动OS,启动过程结束。流程图:
4.SD卡启动流程(bin文件小于16KB时和大于16KB时)
(1)启动的第一种情况是整个镜像大小小于16KB。这时候相当于我的整个镜像作为BL1被steppingstone直接硬件加载执行了而已。
(2)启动的第二种情况就是整个镜像大小大于16KB。(只要大于16KB,哪怕是17KB,或者是700MB都是一样的)这时候就要把整个镜像分为2部分:第一部分16KB大小,第二部分是剩下的大小。然后第一部分作为BL1启动,负责去初始化DRAM并且将第二部分加载到DRAM中去执行(uboot就是这样做的)。5.SoC支持SD卡启动的秘密(iROM代码)
(1)三星系列SoC支持SD卡/NandFlash启动,主要是依靠SteppingStone技术,具体在S5PV210中支持steppingstone技术的是内部iROM代码。问题:iROM究竟是怎样读取SD卡/NandFlash的?
三星在iROM中事先内置了一些代码去初始化外部SD卡/NandFlash,并且内置了读取各种SD卡/NandFlash的代码在iROM中。BL0执行时就是通过调用这些device copy function来读取外部SD卡/NandFlash中的BL1的。
(2)实际编程中我们只需要用到的block device copy function6.用函数指针方式调用device copy function
(1)第一种方法:宏定义方式来调用。好处是简单方便,坏处是编译器不能帮我们做参数的静态类型检查。// 第一种方法:宏定义 #define CopySDMMCtoMem(z,a,b,c,e) (((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
(2)第二种方法:用函数指针方式来调用。
typedef unsigned int bool; // 第二种方法:用函数指针方式调用 typedef bool(*pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int*, bool); // 实际使用时 pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98; p1(x, x, x, x, x); // 第一种调用方法 (*p1)(x, x, x, x, x); // 第二种调用方法 *p1(x, x, x, x, x); // 错误,因为p1先和()结合,而不是先和*结合。
7.扇区和块的概念
(1)早期的块设备就是软盘硬盘这类磁存储设备,这种设备的存储单元不是以字节为单位,而是以扇区为单位。磁存储设备读写的最小单元就是扇区,不能只读取或写部分扇区。这个限制是磁存储设备本身物理方面的原因造成的,也成为了我们编程时必须遵守的规律。
(2)一个扇区有好多个字节(一般是512个字节即512B)。早期的磁盘扇区是512字节,实际上后来的磁盘扇区可以做的比较大(譬如1024字节,譬如2048字节,譬如4096字节),但是因为原来最早是512字节,很多的软件(包括操作系统和文件系统)已经默认了512这个数字,因此后来的硬件虽然物理上可能支持更大的扇区,但是实际上一般还是兼容512字节扇区这种操作方法。
(3)一个扇区可以看成是一个块block(块的概念就是:不是一个字节,是多个字节组成一个共同的操作单元块),所以就把这一类的设备称为块设备。常见的块设备有:磁存储设备硬盘、软盘、DVD和Flash设备(U盘、SSD、SD卡、NandFlash、Norflash、eMMC、iNand)
(4)linux里有个mtd驱动,就是用来管理这类块设备的。
(5)磁盘和Flash以块为单位来读写,就决定了我们启动时device copy function只能以整块为单位来读取SD卡。五,S5PV210的SD卡启动实战
任务:大于16KB的bin文件使用SD卡启动
(1)总体思路:将我们的代码分为2部分:第一部分BL1小于等于16KB,第二部分为任意大小,iROM代码执行完成后从SD卡启动会自动读取BL1到SRAM中执行;BL1执行时负责初始化DDR,然后手动将BL2从SD卡copy到DDR中正确位置,然后BL1远跳转到BL2中执行BL2.程序怎么安排?
1.先处理BL1
细节1:BL1在SD卡中必须从Block1开始(Block0不能用,这个是三星官方规定的),长度为16KB内,我们就定为16KB(也就是32个block);BL1理论上可以从33扇区开始,但是实际上为了安全都会留一些空扇区作为隔离,譬如可以从45扇区开始,长度由自己定(实际根据自己的BL2大小来分配长度,我们实验时BL2非常小,因此我们定义BL2长度为16KB,也就是32扇区)。==
细节2:DDR初始化好之后,整个DDR都可以使用了,这时在其中选择一段长度足够BL2的DDR空间即可。我们选0x23E00000(因为我们BL1中只初始化了DDR1,地址空间范围是0x20000000~0x2FFFFFFF)。
**细节3:**程序整个分为2个文件夹BL1和BL2,各自管理各自的项目。该目录下的Makefile是总Makefile,write2sd是烧录脚本。
总Makefile:
烧录脚本:
进入BL1文件夹:
**细节4:**BL1中要完成:关看门狗、设置栈、开iCache、初始化DDR、从SD卡复制BL2到DDR中特定位置,跳转执行BL2.
start.s
从SD卡中复制内容到DDR并且实现跳转:
BL2远跳转
(1)因为我们BL1和BL2其实是2个独立的程序,链接时也是独立分开链接的,所以不能像以前一样使用ldr pc, =main这种方式来通过链接地址实现元跳转到BL2.
(2)我们的解决方案是使用地址进行强制跳转。因为我们知道BL2在内存地址0x23E00000处,所以直接去执行这个地址即可。
sd_relocate.c
2.再处理BL2
接下来进入BL2文件夹:==
start.S.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了 _start: ldr pc, =main // ldr指令实现长跳转 // 汇编最后的这个死循环不能丢 b .
led.c:单纯用来测试SD卡启动的
#define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 #define rGPJ0CON *((volatile unsigned int *)GPJ0CON) #define rGPJ0DAT *((volatile unsigned int *)GPJ0DAT) void delay(void); void led1(void) { rGPJ0CON = 0x11111111; rGPJ0DAT = ((0<<3) | (1<<4) | (1<<5)); } void led2(void) { rGPJ0CON = 0x11111111; rGPJ0DAT = ((0<<3) | (0<<4) | (1<<5)); } void led3(void) { rGPJ0CON = 0x11111111; rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); } // 该函数要实现led闪烁效果 void main(void) { // led初始化,也就是把GPJ0CON中设置为输出模式 //volatile unsigned int *p = (unsigned int *)GPJ0CON; //volatile unsigned int *p1 = (unsigned int *)GPJ0DAT; rGPJ0CON = 0x11111111; while (1) { // led亮 rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); // 延时 delay(); // led灭 rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); // 延时 delay(); } } void delay(void) { volatile unsigned int i = 900000; // volatile 让编译器不要优化,这样才能真正的减 while (i--); // 才能消耗时间,实现delay }
子makefile和链接脚本的细节
3.在Linux下烧录启动实验及总结
1.插入SD卡->在VMware上边的栏目中点击虚拟机->可移动设备->找到你的SD卡点击连接
命令行输入ls /dev/sd,出现下图中就是SD卡在Linux中识别成功。*
进去目录make编译之后,./writesd执行烧录脚本即可,烧录完成之后,插入开发板,led灯亮的节奏为12313闪烁,实验就是成功的。
2.代码分为2部分启动(上一节讲的)的缺陷
(1)代码分为2部分,这种技术叫分散加载。这种分散加载的方法可以解决问题,但是比较麻烦。
(2)分散加载的缺陷:第一,代码完全分2部分,完全独立,代码编写和组织上麻烦;第二,无法让工程项目兼容SD卡启动和Nand启动、NorFlash启动等各种启动方式。3.uboot中的做法
(1)第二种思路:程序代码仍然包括BL1和BL2两部分,但是组织形式上不分为2部分而是作为一个整体来组织。它的实现方式是:iROM启动然后从SD卡的扇区1开始读取16KB的BL1然后去执行BL1,BL1负责初始化DDR,然后从SD卡中读取整个程序(BL1+BL2)到DDR中,然后从DDR中执行(利用ldr pc, =main这种方式以远跳转从SRAM中运行的BL1跳转到DDR中运行的BL2)。4.再来分析uboot的SD卡启动细节
(1)uboot编译好之后有200多KB,超出了16KB。uboot的组织方式就是前面16KB为BL1,剩下的部分为BL2.
(2)uboot在烧录到SD卡的时候,先截取uboot.bin的前16KB(实际脚本截取的是8KB)烧录到SD卡的block1~bolck32;然后将整个uboot烧录到SD卡的某个扇区中(譬如49扇区)
(3)实际uboot从SD卡启动时是这样的:iROM先执行,根据OMpin判断出启动设备是SD卡,然后从S卡的block1开始读取16KB(8KB)到SRAM中执行BL1,BL1执行时负责初始化DDR,并且从SD卡的49扇区开始复制整个uboot到DDR中指定位置(0x23E00000)去备用;然后BL1继续执行直到ldr pc, =main时BL1跳转到DDR上的BL2中接着执行uboot的第二阶段。总结:uboot中的这种启动方式比上节讲的分散加载的好处在于:能够兼容各种启动方式。
-
micro SD(TF)卡详解
2016-09-18 19:37:51为了满足数码产品不断缩小存储卡体积的要求,SD卡逐渐演变出了Mini SD,Micro SD两种规格。 SD卡背面共有9个引脚,包含4根数据线,支持1bit/4bit两种数据传输宽度,时钟最高频率为25MHZ,故理论最 -
用Altium Designer绘制stm32最小系统的电路原理图并完成STM32+SD卡 的系统原理图设计
2021-12-21 10:18:46目录一、安装Altium Designe18二、用AD18绘制stm32最小系统的电路原理图1、新建工程2、添加原理图3、下载并添加元件库4、绘制芯片模块原理图4.1 常见的工具栏介绍4.2 延长管脚4.3 放置网络编号4.4 放置电源和地4.5 ... -
STM32 HAL库 实现基于SPI模式的SD卡、TF卡FATS文件系统+模拟U盘的应用笔记
2021-08-19 15:50:18很多单片机不带SDIO接口,所以在使用SD卡时必须使用SPI模式进行读写。 想做一个基于SPI的SD卡文件系统... 1.SD卡和MicroSD卡(TF卡)的区别 由下图可以很容易的看出TF卡只是比SD卡少了一个3脚Vss脚,其它的管脚顺序 -
1015-MicroSD/SD卡接口电平3.3V/1.8V 区别,走线
2019-10-15 10:59:52SD总线电路图连接方式如图12-5所示。 如果DAT3引脚作为卡检测工作,需要将RDAT下拉至地。一旦有卡插入,SD卡内部通过50KΩ把DATA3信号拉高至高电平,主机通过检测DAT3线的电平判断SD卡的插拔状况。 4,SD标准简介 SD... -
使用STM32在SPI模式下读写SD卡
2021-12-22 17:18:57使用STM32在SPI模式下读写SD卡 -
sd卡tf卡进入spi模式
2017-09-22 14:18:53现在我们手机的内存卡多为Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常见。自己曾经也想写写SD卡的读取程序,但又不想特地再去买个SD卡,这时想起手机内存卡不是和SD卡很像吗?在网上查了以后发现SD卡和Micro SD卡... -
【雕爷学编程】Arduino动手做(52)---MicroSD卡读写模块
2019-12-30 16:03:2437款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和模块,依照实践(动手试试)出真知的理念,以学习和...实验五十二:SPI接口Micro SD... -
Micro SD 卡(TF卡) spi 模式实现方法
2014-10-07 17:57:52现在我们手机的内存卡多为Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常见。自己曾经也想写写SD卡的读取程序,但又不想特地再去买个SD卡,这时想起手机内存卡不是和SD卡很像吗?在网上查了以后发现SD卡和Micro SD卡... -
【嵌入式20】STM32F103完成对SD卡的数据读取详细操作
2021-12-20 08:19:34本文主要利用STM32F103完成对SD卡的数据读取,介绍该实验的详细操作 -
Altium Designer绘制stm32+SD卡原理图
2021-12-20 17:01:12此次绘制的SD卡为 micro SD卡模块 SPI接口 Mirco SD 卡模块的接口如下图所示: 控制接口:共 6 个引脚(GND、VCC、MISO、MOSI、SCK、CS),GND 为地,VCC 为供 电电源,MISO、MOSI、SCK 为 SPI 总线,CS 为片选... -
STM32的FATFS模式读取SD卡数据
2021-12-21 21:01:22配置一个GPIO管脚用与连接SD卡,这里配置的是PA4,将其配置为Output模式,然后命名为SD_CS 配置USART串口 用于串口输出显示 配置FATFS 配置时钟 修改堆栈大小 配置完毕后生成工程即可 2.文件移植 打 -
Arduino UNO 读取SD卡的信息
2021-11-24 11:56:06Arduino UNO 读取SD卡的信息 ...电平转换电路:往Micro SD卡方向的信号转换成3.3V,MicroSD卡往控制接口方向的MISO信号也转换成了3.3V,一般AVR单片机系统都能读取该信号; Micro SD卡座:是自弹 -
用STM32F103完成对SD卡的数据读取(fat文件模式)
2021-12-23 21:31:08文章目录一、主要内容二、SD卡协议三、实验代码四、结果实现1)电路连接2)结果展示五、总结六、参考内容 一、主要内容 掌握SD卡协议原理,用STM32F103完成对SD卡的数据读取(fat文件模式)。 实验器材: stm32... -
【正点原子FPGA连载】第四十七章SD卡读BMP图片LCD显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1
2021-11-25 10:53:461)实验平台:正点原子新起点V2开发板 ...3)对正点原子FPGA感兴趣的同学可以加群讨论:994244016 4)关注正点原子公众号,获取最新资料更新 ...在“SD卡读写测试实验”中,我们成功地在开发板上实现了对SD卡的读写测 -
STM32完成SD卡的数据写入
2021-12-24 20:03:49本次实验使用STM32F103C86芯片完成对SD卡的数据写入(FAT32文件模式) 文章目录一、SD卡模块简介二、创建工程三、总结四、参考资料 一、SD卡模块简介 根绝百度百科上的解释:SD卡_百度百科 (baidu.com) SD存储卡是... -
高手在民间:SD卡坏了进行封装PCB跳线 修复数据
2020-08-25 12:15:00现在很多现代的NAND闪存设备都采用了一种新型的架构,将接口、控制器和存储芯片集成到一个普通的陶瓷层中。我们称之为一体结构封装。直到最近,所有的存储卡,如SD、索尼的MemoryStic... -
基础——ROM, RAM, FLASH, SSD, DDR3/4, eMMC, UFS, SD卡, TF卡,相互关系
2019-10-30 14:18:19ROM, RAM, FLASH闪存, SSD, DDR3/4, eMMC, UFS, SD卡, TF卡, 这几个名词在手机和电脑等数码产品的参数中经常出现,单独看还明白是什么,放在一块,他们的主要用途和区别有时候会比较混乱,但知道他们都是存储器,放... -
STM32CubeMX实战教程(八)——SD卡初始化
2021-02-01 23:57:23SD卡读写前言材料SD卡 前言 其实STM32CubeMX这款软件本身只是一个工具,它可以让我们更方便地去开发STM32,让我们更少地去关注硬件底层的关联,但这并不代表着底层硬件就不再重要了。一个优秀的嵌入式工程师往往不... -
单片机SD 卡读写
2015-07-20 17:30:001.迄今为止看到的最详细的关于SD卡SPI mode的分析和代码 ... 2.转载... 现在我们手机的内存卡多为Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常见。自己曾经也想写写SD卡的读取程序,但又不... -
S5PV210体系结构与接口09:SD卡启动详解
2021-04-04 19:11:07MicroSD卡(TF卡) 1.2.1 代际关系 1.2.2 技术共性 1.3 iNand & MoviNand 1.4 SD协议简介 1.4.1 物理接口与协议 1.4.2 速度等级 1.4.3 容量等级 2. x210的SD卡启动 2.1 拨码与启动 2.1.1 拨码开关...