SD卡初始化以及命令详解

2023-11-19

SD卡是嵌入式设备中很常用的一种存储设备,体积小,容量大,通讯简单,电路简单所以受到很多设备厂商的欢迎,主要用来记录设备运行过程中的各种信息,以及程序的各种配置信息,很是方便,有这样几点是需要知道的

SD 卡是基于 flash 的存储卡。

SD 卡和 MMC 卡的区别在于初始化过程不同。SD卡并不是我们通常意义上的手机扩展卡,那种卡叫做TF卡,但是通讯以及驱动模式是类似的.

SD 卡的通信协议包括 SD 和 SPI 两类,SD卡上电之后默认处于SD状态。

SD 卡使用卡内智能控制模块进行 FLASH 操作控制,包括协议、安全算法、

数据存取、ECC 算法、缺陷处理和分析、电源管理、时钟管理。这些都不需要用户关系,这是SD卡厂商做的事情

驱动SD卡主要要实现读扇区,写扇区,初始化,获取SD卡相关配置信息这几个就可以了,

另外.SD卡本身只是一种数据介质,它不含有文件系统,文件系统是一种文件的组织格式,是独立于存储介质的一种规范

标准SD卡引脚序列

SD卡引脚功能表

TF卡引脚排序

TF卡引脚功能表

由此可见,TF卡比SD卡少了一个VSS引脚,也就是少了一个供电引脚

另外电路设计时若SD卡使用SPI模式,那么不用的几根数据线应加上上拉电阻,否者会因为这几根数据线的电流震荡引起电流损耗,造成电路上的不稳定

SD卡电路SPI驱动模式

 

SD卡内部有五个我们可以读取的寄存器,分别如下

 

要读取这些信息就需要与卡通讯,SD通讯是用命令+数据的形式进行的,命令格式如下

也就是说,一次SD卡命令发送一共要发送6个字节,对于SPI通讯而言,就是SPI总线上传送六个字节

字节 1 的最高 2 位固定为 01,低 6 位为命令号(比如 CMD16,

为 10000 即 16 进制的 0X10,完整的 CMD16,第一个字节为 01010000,即 0X10+0X40)。

字节 2~5 为命令参数,有些命令是没有参数的。对于没有参数的命令默认发送0即可

字节 6 的高七位为 CRC 值,最低位恒定为 1,crc计算遵循以下规律

GX为生成多项式,具体计算方法请查看CRC计算相关,不过有一点好处就是,在SPI驱动模式下,不需要CRC校验(默认SD卡在SPI模式下不开启CRC校验,在SD模式下默认开始CRC校验),所以我们只需要对CMD0进行CRC就可以了,后面的CRC都可以不管(因为在CMD0之前是SD模式,所以第一个命令需要,切换之后就不用了),而CMD0的CRC为0x95(加上了之后的一位1)

注:SPI模式下打开crc校验需要用到CMD59的保留命令,请查阅相关资料

SD卡的命令表如下所示(以下仅写出SPI模式的CMD)

CMD0 复位SD卡, 重置所有卡到 Idle状态,参数为0

CMD1 设置SD卡到ACTIVATE模式,也就是推出IDLE模式

CMD8 发送接口状态命令

CMD9 读取CSD寄存器

CMD10 读取CID寄存器

CMD12 在多块读取的时候请求停止读取

CMD13读取SD卡状态寄存器

CMD16 设置单个扇区的大小一般都设置为512字节一个扇区

CMD17 读取扇区命令

CMD18 读取多个扇区知道发送停止命令

CMD24 写扇区命令

CMD25 写多个扇区命令

CMD27 编辑CSD位

CMD28设置地址组保护位。写保护由卡配置数据的WP_GRP_SIZE 指定

CMD29清除保护位

CMD30 要求卡发送写保护状态,参数中有要查询的地址

CMD32 设置要擦除的第一个写数据块地址

CMD33 设置要擦除的最后一个写数据块地址

CMD38 擦除所有选中的块

 

CMD42 设置SD卡的解锁或者上锁

CMD55 告诉SD卡下一个命令式卡应用命令,不是标准命令

CMD56 应用相关的数据块读写命令

CMD58 读取OCR信息

CMD59 设置crc校验的使能与关闭(前面说到过)

ACMD13 发送SD卡状态

ACMD18保留作为 SD 安全应用(也就是这命令没用)

ACMD22发送写数据块的数目。响应为 32 位+CRC

ACMD23设置写前预擦除的数据块数目(用来加速多数据块写操作)。“1”=默认(一个块)(1)

不管是否使用 ACMD23,在多数据块写操作中都需要 STOP_TRAN(CMD12)命令

ACMD25 26 38 保留作为安全应用

ACMD41要求访问的卡发送它的操作条件寄存器(OCR)内容

ACMD42连接[1]/断开[0]卡上CD/DAT3(pin 1]的 50K 欧姆上拉电阻。上拉电阻可用来检测卡

ACMD43-49保留作为安全应用

ACMD51读取 SD 配置寄存器 SCR

 

ACMD命令,全称应该是application CMD,所以使用ACMD都需要在发送CMD55之后

发出命令后会收到相应的响应, 所有响应通过 CMD 线传输,响应以 MSB 开始,不同类型的响应长度根据类型不同而不同。

响应以起始位开始(通常为“0”),接着这是传输方向的位(卡为 0)。除了 R3 外其他

响应都有 CRC。每个响应都以结束位(通常为“1”)结束。,SD卡响应格式有多种

1.       R1响应

2.       R1b响应

多了一个忙数据

3.       R2响应

4.       R3响应(针对于read ocr的响应 CMD58)

5.       响应R4和R5都是正对于SD mode的响应

6.       针对CMD8命令的响应R7

 

 

SD卡的初始化以及识别过程(为了方便起见,我们只检测响应的R1状态)

1.  初始化与 SD 卡连接的硬件条件(MCU 的 SPI 配置,IO 口配置);

2.  上电延时(>74 个 CLK)(为了让卡正常启动)

3.  复位卡(CMD0),进入 IDLE 状态,检测R1的最低位,是否为闲置状态

4.  发送 CMD8,检查是否支持 2.0 协议,因为这个命令是在2.0的协议里面才添加的

5.  根据不同协议检查 SD 卡(命令包括:CMD55、CMD41、CMD58 和 CMD1 等);

6.  取消片选,发多 8 个 CLK,结束初始化

具体请查看下图

以下是网络上找到的一份经我修改之后的SD卡驱动,不完全符合SD卡标准驱动,但是我用着一直还蛮正常,大家有兴趣可以看看改改

 

Spisd.c

#include "spisd.h"

//预定义SD卡类型
u8  SD_Type=0;//SD卡的类型 

//这部分应根据具体的连线来修改!
#define	SD_CS  PAout(4) //SD卡片选引脚

//data:要写入的数据
//返回值:读到的数据
static u8 SdSpiReadWriteByte(u8 data)
{
    return Spi1ReadWriteByte(data);
}

//SD卡初始化的时候,需要低速
static void SdSpiSpeedLow(void)
{
    Spi1SetSpeed(SPI_SPEED_256);//设置到低速模式  用于初始化,最高spi速度为400k	
}

//SD卡正常工作的时候,可以高速了
static void SdSpiSpeedHigh(void)
{
    Spi1SetSpeed(SPI_SPEED_4);//设置到高速模式	初始化完成之后进行,最高可到25M,不过一般不用
}


static void SdIOInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA, ENABLE );	
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化A4
	
	SD_CS = 1;
	Spi1Init();//初始化SPI接口
	SdSpiSpeedLow();//初始化设置为低速
}

//等待卡准备好
//返回值:0,准备好了;其他,错误代码
static u8 SdWaitReady(void)
{
    u32 t=0;
    do
    {
        if(SdSpiReadWriteByte(0XFF)==0XFF)return 0;//OK
        t++;		  	
    }while(t<0XFFFFFF);//等待 
    return 1;
}

//取消选择,释放SPI总线
void SD_DisSelect(void)
{
    SD_CS=1;
    SdSpiReadWriteByte(0xff);//提供额外的8个时钟
}

//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SdSelect(void)
{
    SD_CS=0;
    if(SdWaitReady()==0)return 0;//等待成功
    SD_DisSelect();
    return 1;//等待失败
}

//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败    期待得到的回应值
u8 SdGetResponse(u8 Response)
{
    u16 Count=0xFFF;//等待次数	   						  
    while ((SdSpiReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应  	  
    if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败   
    else return MSD_RESPONSE_NO_ERROR;//正确回应
}

//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;
//0XFE数据起始令牌	
u8 SdRecvData(u8*buf,u16 len)
{			  	  
    if(SdGetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
    while(len--)//开始接收数据
    {
        *buf=SdSpiReadWriteByte(0xFF);
        buf++;
    }
    //下面是2个伪CRC(dummy CRC)
    SdSpiReadWriteByte(0xFF);
    SdSpiReadWriteByte(0xFF);									  					    
    return 0;//读取成功
}

//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;	
u8 SdSendBlock(u8*buf,u8 cmd)
{	
    u16 t;		  	  
    if(SdWaitReady())return 1;//等待准备失效
    SdSpiReadWriteByte(cmd);
    if(cmd!=0XFD)//不是结束指令
    {
        for(t=0;t<512;t++)SdSpiReadWriteByte(buf[t]);//提高速度,减少函数传参时间
        SdSpiReadWriteByte(0xFF);//忽略crc
        SdSpiReadWriteByte(0xFF);
        t=SdSpiReadWriteByte(0xFF);//接收响应
        if((t&0x1F)!=0x05)return 2;//响应错误									  					    
    }						 									  					    
    return 0;//写入成功
}


//向SD卡发送一个命令
//输入: u8 cmd   命令 
//      u32 arg  命令参数
//      u8 crc   crc校验值	   
//返回值:SD卡返回的响应															  
u8 SdSendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1;	
    u8 Retry=0; 
    SD_DisSelect();//取消上次片选
    if(SdSelect())return 0XFF;//片选失效 
    //发送
    SdSpiReadWriteByte(cmd | 0x40);//分别写入命令
    SdSpiReadWriteByte(arg >> 24);
    SdSpiReadWriteByte(arg >> 16);
    SdSpiReadWriteByte(arg >> 8);
    SdSpiReadWriteByte(arg);	  
    SdSpiReadWriteByte(crc); 
    if(cmd==CMD12)SdSpiReadWriteByte(0xff);//Skip a stuff byte when stop reading
    //等待响应,或超时退出
    Retry=0X1F;
    do
    {
        r1=SdSpiReadWriteByte(0xFF);
    }while((r1&0X80) && Retry--);	 
    //返回状态值
    return r1;
}	

//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)	  
//返回值:0:NO_ERR
//		 1:错误														   
u8 SdGetCID(u8 *cid_data)
{
    u8 r1;	   
    //发CMD10命令,读CID
    r1=SdSendCmd(CMD10,0,0x01);
    if(r1==0x00)
    {
        r1=SdRecvData(cid_data,16);//接收16个字节的数据	 
    }
    SD_DisSelect();//取消片选
    if(r1)return 1;
    else return 0;
}	

//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)	    
//返回值:0:NO_ERR
//		 1:错误														   
u8 SdGetCSD(u8 *csd_data)
{
    u8 r1;	 
    r1=SdSendCmd(CMD9,0,0x01);//发CMD9命令,读CSD
    if(r1==0)
    {
    	r1=SdRecvData(csd_data, 16);//接收16个字节的数据 
    }
    SD_DisSelect();//取消片选
    if(r1)return 1;
    else return 0;
}

//获取SD卡的总扇区数(扇区数)   
//返回值:0: 取容量出错 
//其他:SD卡的容量(扇区数/512字节)
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.														  
u32 SdGetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity;  
    u8 n;
    u16 csize;  					    
    //取CSD信息,如果期间出错,返回0
    if(SdGetCSD(csd)!=0) return 0;	    
    //如果为SDHC卡,按照下面方式计算
    if((csd[0]&0xC0)==0x40)	 //V2.00的卡
    {	
        csize = csd[9] + ((u16)csd[8] << 8) + 1;
        Capacity = (u32)csize << 10;//得到扇区数	 		   
    }else//V1.XX的卡
    {	
        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
        csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
        Capacity= (u32)csize << (n - 9);//得到扇区数   
    }
    return Capacity;
}


//初始化SD卡
//返回值:0,正常.
//其他,不正常.
u8 SdInitialize(void)
{
    u8 r1;      // 存放SD卡的返回值
    u16 retry;  // 用来进行超时计数
    u8 buf[4];  
    u16 i;
    
    SdIOInit();		//初始化IO 
    for(i=0;i<10;i++)SdSpiReadWriteByte(0XFF);//发送最少74个脉冲  ,这里发送了80个脉冲
    retry=20;
    do
    {
        r1=SdSendCmd(CMD0,0,0x95);//进入IDLE状态
    }while((r1!=0X01) && retry--);
    SD_Type=0;//默认无卡
    if(r1==0X01)
    {
        if(SdSendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
        {
            for(i=0;i<4;i++)buf[i]=SdSpiReadWriteByte(0XFF);	//Get trailing return value of R7 resp
            if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
            {
                retry=0XFFFE;
                do
                {
                    SdSendCmd(CMD55,0,0X01);	//发送CMD55
                    r1=SdSendCmd(CMD41,0x40000000,0X01);//发送CMD41
                }while(r1&&retry--);
                if(retry&&SdSendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
                {
                    for(i=0;i<4;i++)buf[i]=SdSpiReadWriteByte(0XFF);//得到OCR值
                    if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
                    else SD_Type=SD_TYPE_V2;   
                }
            }
        }else//SD V1.x/ MMC	V3
        {
            SdSendCmd(CMD55,0,0X01);		//发送CMD55
            r1=SdSendCmd(CMD41,0,0X01);	//发送CMD41
            if(r1<=1)
            {		
                SD_Type=SD_TYPE_V1;
                retry=0XFFFE;
                do //等待退出IDLE模式
                {
                    SdSendCmd(CMD55,0,0X01);	//发送CMD55
                    r1=SdSendCmd(CMD41,0,0X01);//发送CMD41
                }while(r1&&retry--);
            }else
            {
                SD_Type=SD_TYPE_MMC;//MMC V3
                retry=0XFFFE;
                do //等待退出IDLE模式
                {											    
                    r1=SdSendCmd(CMD1,0,0X01);//发送CMD1
                }while(r1&&retry--);  
            }
            if(retry==0||SdSendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
        }
    }
    SD_DisSelect();//取消片选
    SdSpiSpeedHigh();//高速
    if(SD_Type)return 0;
    else if(r1)return r1; 	   
    return 0xaa;//其他错误
}



//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SdReadDisk(u8*buf,u32 sector,u8 cnt)
{
    u8 r1;
    if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
    if(cnt==1)
    {
        r1=SdSendCmd(CMD17,sector,0X01);//读命令
        if(r1==0)//指令发送成功
        {
            r1=SdRecvData(buf,512);//接收512个字节	   
        }
    }else
    {
        r1=SdSendCmd(CMD18,sector,0X01);//连续读命令
        do
        {
            r1=SdRecvData(buf,512);//接收512个字节	 
            buf+=512;  
        }while(--cnt && r1==0); 	
        SdSendCmd(CMD12,0,0X01);	//发送停止命令
    }   
    SD_DisSelect();//取消片选
    return r1;//
}

//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SdWriteDisk(u8*buf,u32 sector,u8 cnt)
{
    u8 r1;
    if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
    if(cnt==1)
    {
        r1=SdSendCmd(CMD24,sector,0X01);//读命令
        if(r1==0)//指令发送成功
        {
            r1=SdSendBlock(buf,0xFE);//写512个字节	   
        }
    }else
    {
        if(SD_Type!=SD_TYPE_MMC)
        {
            SdSendCmd(CMD55,0,0X01);	
            SdSendCmd(CMD23,cnt,0X01);//发送指令	
        }
        r1=SdSendCmd(CMD25,sector,0X01);//连续读命令
        if(r1==0)
        {
            do
            {
                r1=SdSendBlock(buf,0xFC);//接收512个字节	 
                buf+=512;  
            }while(--cnt && r1==0);
            r1=SdSendBlock(0,0xFD);//接收512个字节 
        }
    }   
    SD_DisSelect();//取消片选
    return r1;//
}	

Spisd.h

#ifndef __SPISD_H_
#define __SPISD_H_

#include "spi.h"
#include "delay.h"
#include "common.h"
#include "ioremap.h"

// SD卡类型定义  
#define SD_TYPE_ERR     0X00
#define SD_TYPE_MMC     0X01
#define SD_TYPE_V1      0X02
#define SD_TYPE_V2      0X04
#define SD_TYPE_V2HC    0X06	

// SD卡指令表  	   
#define CMD0    0       //卡复位
#define CMD1    1
#define CMD8    8       //命令8 ,SEND_IF_COND
#define CMD9    9       //命令9 ,读CSD数据
#define CMD10   10      //命令10,读CID数据
#define CMD12   12      //命令12,停止数据传输
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
#define CMD17   17      //命令17,读sector
#define CMD18   18      //命令18,读Multi sector
#define CMD23   23      //命令23,设置多sector写入前预先擦除N个block
#define CMD24   24      //命令24,写sector
#define CMD25   25      //命令25,写Multi sector
#define CMD41   41      //命令41,应返回0x00
#define CMD55   55      //命令55,应返回0x01
#define CMD58   58      //命令58,读OCR信息
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00

// SD卡中的响应有许多种,R1为标准响应,最为常用。与R1响应相似的还有R1b、R2和R3。
// R1响应在除SEND_STATUS外其它命令后发送,也是最高位先发送,共1个字节。最高位为0。响应说明如下:
// 0x01:空闲状态
// 0x02:擦除错误
// 0x04:命令错误
// 0x08:CRC通信错误
// 0x10:擦除次序错误
// 0x20:地址错误
// 0x40:参数错误

#define MSD_RESPONSE_NO_ERROR      0x00    //无错误
#define MSD_IN_IDLE_STATE          0x01    //空闲状态
#define MSD_ERASE_RESET            0x02    //擦除错误
#define MSD_ILLEGAL_COMMAND        0x04    //命令错误
#define MSD_COM_CRC_ERROR          0x08    //CRC通信错误
#define MSD_ERASE_SEQUENCE_ERROR   0x10    //擦除次序错误
#define MSD_ADDRESS_ERROR          0x20    //地址错误
#define MSD_PARAMETER_ERROR        0x40    //参数错误
#define MSD_RESPONSE_FAILURE       0xFF    //这次命令根本是失败的,没有任何回应

u8 SdInitialize(void);

u8 SdGetCID(u8 *cid_data);

u8 SdGetCSD(u8 *csd_data);

u32 SdGetSectorCount(void);

u8 SdReadDisk(u8*buf,u32 sector,u8 cnt);

u8 SdWriteDisk(u8*buf,u32 sector,u8 cnt);


#endif

https://www.cnblogs.com/dengxiaojun/p/4279439.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SD卡初始化以及命令详解 的相关文章

  • 芯片的SD/MMC控制器以及SD卡介绍

    1 MMC SD卡 eMMC介绍 1 1 三者关联 1 最早出现的是MMC卡 卡片式结构 按照MMC协议设计 相较于NandFlash芯片来说 MMC卡有2个优势 第一是卡片化 便于拆装 第二是统一了协议接口 兼容性好 2 后来出现SD卡
  • SPI协议读写SD卡介绍

    前言 在前面的文章中 我们主要介绍了如何利用SDIO协议对SD卡进行读写操作的流程及注意事项 虽然SDIO协议读写SD卡的效率很高 但是 操作却比较麻烦 另外 还需要使用的芯片具有SDIO外设 这对于不具备SDIO外设的芯片而言 绝对是一个
  • 基于SD卡的FatFs文件系统(FatFs移植到STM32)

    平台 STM32ZET6 核心板 ST LINK V2 SD卡 USB串口线 一 移植 工程介绍 主要文件在USER组中 bsp sdio sdcard c bsp sdio sdcard h和main c 另外FatFs是用来后面移植文件
  • FATFS文件系统详解

    FATFS文件系统详解 文章目录 FATFS文件系统详解 1 简介 2 基础概念 3 FAT文件系统组成介绍 4 FAT文件系统分析 4 1 采用FAT格式格式化SD nand sd卡 4 2 引导扇区分析 4 3 分区偏移及大小计算 4
  • FATFS 0.13 f_mount(&fs,““,1)挂载失败的原因

    这两天学着用了一下FATS文件系统 虽然工作中没用到 但是对个人的经验积累还是有用的 看了一下 代码并不多 但是精简啊 指针跳来跳去的一不小心就晕了 所以也遇到了不少问题啊 这里就讲一下我遇到的第一步就懵逼的问题 那就是 FRESULT f
  • STM32的简单的SD卡读写

    导读 SD卡一般支持两种读写模式 SPI和SDIO模式 SD卡的引脚排序如下图所示 SPI模式下有几个重要的操作命令 分别是 SD卡R1回应的格式如下SPI模式下的典型初始化过程如下 1 初始化硬件配置 SPI配置 IO配置等 SD卡一般支
  • S3C2440读写sd卡的一些总结

    整理硬盘的时候发现这个文档 以前写2440操作sd卡程序的时候总结的 1 我的2440 sdi对sd卡发送ACMD41时总是反馈crc fail 但是可以得到正确的response sd卡可以正常使用 2 sd卡可以没有mbr 在物理的 0
  • SD卡SPI模式 读写block

    声明 第一次写教程 如若有错误 请指出更正 看了很多网上的教程 还是觉得很多教程中 写多个块的时候有些问题 因此经过3天的奋斗 写出自己的教程 本教程中 没有挂载文件系统 单纯读写Block 会破坏分区和数据 下节再 装上文件系统Fatfs
  • STM32+FATFS文件系统连续在同一个txt文件里写入内容

    移植好fatfs文件系统之后 我们经常要在一个txt文件下写入数据 但是这些数据可能需要多次写入 那怎么办呢 通过这几天的学习 有以下函数可以帮助我们进行多次写入数据 1 打开文件 f open filescr2 0 201711022 t
  • SD卡/TF卡简记

    文章目录 MicroSD卡与SD卡关系与区别 对比NM卡 XQD卡 CFexpress卡 SD规格标识 FAQ 拍摄1080p或2k视频需要什么速度的sd卡 拍摄4k视频需要什么速度的sd卡 拍摄8k视频需要什么速度的sd卡 MicroSD
  • STM32 SPI方式读写SD卡

    前段时间在51上模拟SPI实现了对SD卡的读取 效果还算不错 最近将其移植到STM32上 不过使用硬件SPI和使用软件SPI还是有差别的 代码如下 void User SPIInit void GPIO InitTypeDef GPIO I
  • fatfs移植和使用(在SPI_FLASH上建立文件系统)

    文件系统对于嵌入式系统的重要性是不言而喻的 有了文件系统管理数据和外设变得方便许多 同时简化了应用的开发 今天我们来以在SPI FLASH上建立文件系统为例 看看FATFS文件系统怎么移植和使用 需要准备的材料有 1 FATFS文件系统源码
  • MMC、SD、TF、SDIO、SDMMC简介

    MMC 概念 MMC的全称是 MultiMediaCard 所以也通常被叫做 多媒体卡 是一种小巧大容量的快闪存储卡 特别应用于移动电话和数字影像及其他移动终端中 外形及接口定义 如上图所示 MMC存贮卡只有7pin 可以支持MMC和SPI
  • 发布一个在读写sd卡时,此时sd卡拔出造成死机的处理方法

    发布一个在读写sd卡时 此时sd卡拔出造成死机的处理方法 同时也在此记录一下 以备后用及有需要人们参考 stm32f4xx hal sd c 红色的代码是增加上去的 函数名称 static HAL SD ErrorTypedef SD Cm
  • STM32F407移植FATFS文件系统(版本 R0.09b)支持长文件名和中文名称

    FatFs文件系统 默认是不支持长文件名和中文名称的 要想支持长文件名和中文名称 需要打开ffconf h文件进行配置 一 支持长文件名 FatFs文件系统 默认是不支持长文件名的 要想支持长文件名 需要打开ffconf h文件进行配置 找
  • SD卡、TF卡读写速率测试

    请注意 可以在未经过博主同意下转载 但必须注明出处 谢谢 1 运行HDBENCH软件 点击确定 2 弹出如下图所示界面 配置选项并测试 选择待测TF卡 Removable可移动存储设备 图示所插入的TF卡是 I 盘 请根据实际情况选择 选择
  • SD卡 FATFS CSV 文件中的 逗号和换行

    RFC 4180 Common Format and MIME Type for Comma Separated Values CSV Files 要点有 1 CSV的换行符号要使用CRLF 即 回车符 换行符 的形式 2 文字可以使用双引
  • FATFS实现数据追加功能(原文不覆盖)

    在对FATFS的应用中我们经常需要把采集的数据存入的文件中 用作保存 也许我们的系统是一个长期的运行过程 但是我们的数据可能不是持续采集的 所以我们这样写代码 注册一个工作区域 f mount 0 fs 打开创建一个新文件 res f op
  • SD卡初始化以及命令详解

    SD卡是嵌入式设备中很常用的一种存储设备 体积小 容量大 通讯简单 电路简单所以受到很多设备厂商的欢迎 主要用来记录设备运行过程中的各种信息 以及程序的各种配置信息 很是方便 有这样几点是需要知道的 SD 卡是基于 flash 的存储卡 S
  • 【正点原子探索者STM32F407开发板例程连载+教学】第30章 SPI通信实验

    第三十章 SPI 实验 mw shl code c true 1 硬件平台 正点原子探索者STM32F407开发板 2 软件平台 MDK5 1 3 固件库版本 V1 4 0 mw shl code 本章我们将向大家介绍STM32F4的SPI

随机推荐

  • Java算法题:两数之和

    LeetCode原题 给你一个下标从 1 开始的整数数组 numbers 该数组已按 非递减顺序排列 请你从数组中找出满足相加之和等于目标数 target 的两个数 示例 1 输入 numbers 2 7 11 15 target 9 输出
  • STM32F103VG使用RTT实现发送DMX512调光数据

    DMX512调光协议和DALI一样属于数字调光协议 一个完整的DMX512数据包格式 1break 1mab 1startcode 512个调光数据 DMX512发送是基于485串口的基础上实现的特殊的数据协议 使用RTT需要把串口打开并且
  • 大话数据结构:线性表(顺序存储结构)

    线性表 零个或多个数据元素的有限序列 直接前驱元素 直接后继元素 线性表的长度 线性表元素的个数n 线性表的抽象数据类型 ADT线性表 list Data 线性表的数据对象集合为 a1 a2 an 每个元素的类型均为Datatype 其中
  • 微软服务器的主要功能,数据库服务器主要功能

    数据库服务器主要功能 内容精选 换一换 HANA全称High performanceAnalyticAppliance是由SAP开发的基于内存的面向行 列存储的关系型数据库管理系统 其作为数据库服务器的主要功能是根据应用程序的要求存储和检索
  • jdk17下载

    官网下载 https download oracle com java 17 latest jdk 17 windows x64 bin zip
  • 也想做一个绝地求生版的汽车控制移动,进来瞧瞧?(干货满满)

    控制车子移动 效果图附上 1 首先4个车轮复制一遍为车轮2备用 2 给车轮2全部添加wheel collider 只剩下车轮碰撞器和transform组件 3 给原版4个车轮添加脚本wheel 变量共有 面板赋值 依次添加车轮2里面的车轮c
  • c#图解教程和c#高级编程电子书链接

    链接 https pan baidu com s 1y TM08JvyBh8kQ0v7uT5hg 提取码 b0cq
  • Python的多维空数组赋值

    Python里面的list tuple默认都是一维的 创建二维数组或者多维数组也是比较简单 可以这样 list1 1 2 list1 append 3 4 可以这样 list2 1 2 3 4 还可以这样 list3 1 2 list3 i
  • android界面监控,防劫持

    1 首先要对自己应用的activity建立一个白名单 2 权限
  • http协议从客户端提交数据给服务器并返回数据

    老罗视频学习 本例从客户端提交数据给服务器 服务器接收到数据之后 看是否匹配 匹配返回字符串 login is success 失败返回 login is error 一 客户端 初始化url地址 private static String
  • Git如何比较不同分支的差异

    前两天 良许在做集成的时候碰到了一件闹心事 事情是这样的 良许的一位同事不小心把一个错误的 dev 分支 merge 到了 master 分支上 导致了良许编译不通过 于是 我们需要将版本回退到 merge 之前的状态 如果是下面这个状态
  • 电子设计竞赛(三)-SPWM与PID

    1 SPWM波调制技术 逆变电路的控制方式主要是采用SPWM 正弦脉宽调制技术 IR2104控制开关管的通断来实现正弦调制 SPWM的基本思路是将一个正弦波按等宽间距分成N等份 对于每一个波形以一个等面积的脉冲来对应 使脉冲的中点与相应正弦
  • python3 hashlib库sha256、pbkdf2_hmac、blake2b基本用法

    hashlib sha256 import hashlib x hashlib sha256 x update b asd print x 1 x hexdigest x hashlib sha256 x update asd encode
  • 数据下载网站整理

    数据十分重要 如何找到理想的数据显得更重要了 这里记录自己经过网上查询到的数据 进行整理 如果侵权 请联系我删除 再次感谢网友大佬们提供的资料 1 中国气象站点数据 下载地址 https www resdc cn data aspx DAT
  • 递归算法中的时间复杂度分析

    对于一种算法的时间复杂度分析还是特别重要的 在一些非递归算法中 我们仅仅看运算次数最多的那一行代码可能执行多少次就可以 实际就是看在循环中变量的变化 但是对于递归算法中该怎么分析呢 下面介绍几种递归函数中的算法时间复杂度分析的方法 0 递推
  • 使用paramiko跨服务器传输文件/文件夹

    一些概念 SSH Secure Shell 安全外壳协议 是建立在应用层基础上的安全协议 专为远程登录和其他网络服务提供安全性的协议 SFTP SSH 文件传输协议 Secret File Transfer Protocol SFTP 安全
  • window.location.href的用法

    window location href的用法 一 前言 二 常见用例 一 前言 window location href 是一个用于获取当前页面 URL 或让浏览器跳转到新 URL 的重要方法 是 window location 对象的属
  • 【gis系列】等高线创建dem,以及高程分析,坡度分析,坡向分析

    绝对原创 首先 我们要整理一份cad的文件格式 这里我不说那么多 就是在某某地图下载后 方法很多 可以通过qgis globalmapper来操作数据 以及一些普通的地图软件直接生成 这里呢 然后进入cad 把里面的高程标注信息给删除掉 图
  • 机器学习资源大全

    C 计算机视觉 CCV 基于C语言 提供缓存 核心的机器视觉库 新颖的机器视觉库 OpenCV 它提供C C Python Java 以及 MATLAB接口 并支持Windows Linux Android and Mac OS操作系统 通
  • SD卡初始化以及命令详解

    SD卡是嵌入式设备中很常用的一种存储设备 体积小 容量大 通讯简单 电路简单所以受到很多设备厂商的欢迎 主要用来记录设备运行过程中的各种信息 以及程序的各种配置信息 很是方便 有这样几点是需要知道的 SD 卡是基于 flash 的存储卡 S