搜档网
当前位置:搜档网 › STM32读写SD卡要点

STM32读写SD卡要点

STM32读写SD卡要点
STM32读写SD卡要点

3.20SD卡实验

很多单片机系统都需要大容量存储设备,以存储数据。目前常用的有U盘,FLASH芯片,SD卡等。他们各有优点,综合比较,最适合单片机系统的莫过于SD卡了,它不仅容量可以做到很大(32Gb以上),而且支持SPI接口,方便移动,有几种体积的尺寸可供选择(标准的SD 卡尺寸,以及TF卡尺寸),能满足不同应用的要求。只需要4个IO口,就可以外扩一个最大达32GB以上的外部存储器,容量选择尺度很大,更换也很方便,而且方便移动,编程也比较简单,是单片机大容量外部存储器的首选。

ALIENTKE MiniSTM3开发板就带有SD卡接口,利用STM32自带的SPI接口,最大通信速度可达18Mbps,每秒可传输数据2M字节以上,对于一般应用足够了。本节将向大家介绍,如何在ALIENTEK MiniSTM32开发板上读取SD卡。本节分为如下几个部分:

3.20.1 SD卡简介

3.20.2 硬件设计

3.20.3 软件设计

3.20.4 下载与测试

3.20.1 SD卡简介

SD卡(Secure Digital Memory Card)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。

SD卡一般支持2种操作模式:

1,SD卡模式;

2,SPI模式;

主机可以选择以上任意一种模式同SD卡通信,SD卡模式允许4线的高速数据传输。SPI模式允许简单的通过SPI接口来和SD卡通信,这种模式同SD卡模式相比就是丧失了速度。

SD卡的引脚排序如下图所示:

图3.20.1.1 SD卡引脚排序图

SD卡引脚功能描述如下表所示:

表3.20.1.1 SD卡引脚功能表

SD卡只能使用3.3V的IO电平,所以,MCU一定要能够支持3.3V的IO端口输出。

注意:在SPI模式下,CS/MOSI/MISO/CLK都需要加10~100K左右的上拉电阻。

SD卡要进入SPI模式很简单,就是在SD卡收到复位命令(CMD0)时,CS为有效电平(低电平)则SPI模式被启用。不过在发送CMD0之前,要发送>74个时钟,这是因为SD卡内部有个供电电压上升时间,大概为64个CLK,剩下的10个CLK用于SD卡同步,之后才能开始CMD0的操作,在卡初始化的时候,CLK时钟最大不能超过400Khz!。

ALENTEK MiniSTM32开发板使用的是SPI模式来读写SD卡,下面我们就重点介绍一下SD卡在SPI模式下的相关操作。

首先介绍SPI模式下几个重要的操作命令,如下表所示:

表3.20.1.2 SPI模式下SD卡部分操作指令

其中R1的回应格式如下表所示:

表3.20.1.3 SD卡R1回应格式

接着我们看看SD卡的初始化,SD卡的典型初始化过程如下:

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

2、上电延时(>74个CLK);

3、复位卡(CMD0);

4、激活卡,内部初始化并获取卡类型(CMD1(用于MMC卡)、CMD5

5、CMD41);

5.、查询OCR,获取供电状况(CMD58);

6、是否使用CRC(CMD59);

7、设置读写块数据长度(CMD16);

8、读取CSD,获取存储卡的其他信息(CMD9);

9、发送8CLK后,禁止片选;

这样我们就完成了对SD卡的初始化,这里面我们一般设置读写块数据长度为512个字节,并禁止使用CRC。在完成了初始化之后,就可以开始读写数据了。

SD卡读取数据,这里通过CMD17来实现,具体过程如下:

1、发送CMD17;

2、接收卡响应R1;

3、接收数据起始令牌0XFE;

4、接收数据;

5、接收2个字节的CRC,如果没有开启CRC,这两个字节在读取后可以丢掉。

6、8CLK之后禁止片选;

以上就是一个典型的读取SD卡数据过程,SD卡的写于读数据差不多,写数据通过CMD24来实现,具体过程如下:

1、发送CMD24;

2、接收卡响应R1;

3、发送写数据起始令牌0XFE;

4、发送数据;

5、发送2字节的伪CRC;

6、8CLK之后禁止片选;

以上就是一个典型的写SD卡过程。关于SD卡的介绍,我们就介绍到这里,更详细的

介绍请参考SD卡的参考资料。

3.20.2 硬件设计

本节实验功能简介:开机的时候先初始化SD卡,如果SD卡初始化完成,则读取扇区

0的数据,然后通过串口打印到电脑上。如果没初始化通过,则在LCD上提示初始化失败。同样用DS0来指示程序正在运行。

所要用到的硬件资源如下:

1)STM32F103RBT6。

2)DS0(外部LED0)。

3)串口1。

4)TFTLCD液晶模块。

5)SD卡。

前面四部分,在之前的实例已经介绍过了,这里我们介绍一下SD卡在开发板上的连接方式,SD卡与MCU的连接原理图如下:

图3.20.2.1 SD卡与STM32连接电路图

3.20.3 软件设计

打开上一节的工程,首先在HARDW ARE文件夹下新建一个SD的文件夹。然后新建一个MMC_SD.C和MMC_SD.H的文件保存在SD文件夹下,并将这个文件夹加入头文件包含路径。

打开MMC_SD.C文件,输入如下代码:

#include "sys.h"

#include "mmc_sd.h"

#include "spi.h"

#include "usart.h"

#include "delay.h"

u8SD_Type=0;//SD卡的类型

//Mini STM32开发板

//SD卡驱动

//正点原子@ALIENTEK

//2010/5/13

//增加了一些延时,实测可以支持TF卡(1G/2G),金士顿2G,4G 16G SD卡

//2010/6/24

//加入了u8 SD_GetResponse(u8 Response)函数

//修改了u8 SD_WaitDataReady(void)函数

//增加了USB读卡器支持的u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);

//和u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite);两个函数

//等待SD卡回应

//Response:要得到的回应值

//返回值:0,成功得到了该回应值

//其他,得到回应值失败

u8 SD_GetResponse(u8 Response)

{

u16 Count=0xFFF;//等待次数

while ((SPIx_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应

if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败

else return MSD_RESPONSE_NO_ERROR;//正确回应

}

//等待SD卡写入完成

//返回值:0,成功;

//其他,错误代码;

u8 SD_WaitDataReady(void)

{

u8 r1=MSD_DATA_OTHER_ERROR;

}

u32 retry; retry=0; do {

r1=SPIx_ReadWriteByte(0xFF)&0X1F;//读到回应 if(retry==0xfffe)return 1; retry++; switch (r1) {

case MSD_DATA_OK://数据接收正确了

r1=MSD_DATA_OK; break;

case MSD_DATA_CRC_ERROR: //CRC

校验错误

return MSD_DATA_CRC_ERROR;

case MSD_DATA_WRITE_ERROR://数据写入错误 return MSD_DATA_WRITE_ERROR; default://未知错误

r1=MSD_DATA_OTHER_ERROR; break;

}

}while(r1==MSD_DATA_OTHER_ERROR); //数据错误时一直等待 retry=0;

while(SPIx_ReadWriteByte(0XFF)==0)//读到数据为

0,则数据还未写完成

{

retry++;

//delay_us(10);//SD

卡写等待需要较长的时间 if(retry>=0XFFFFFFFE)return 0XFF;//等待失败了

};

return 0;//成功了 //向

SD

卡发送一个命令 //输入: u8 cmd 命令

//

u32 arg 命令参数

//

u8 crc crc

校验值 //返回值:SD

卡返回的响应

u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc) {

u8 r1; u8 Retry=0; SD_CS=1;

SPIx_ReadWriteByte(0xff);//高速写命令延时 SPIx_ReadWriteByte(0xff); SPIx_ReadWriteByte(0xff);

} //片选端置低,选中

SD

卡 SD_CS=0;

//发送

SPIx_ReadWriteByte(cmd | 0x40);//分别写入命令 SPIx_ReadWriteByte(arg >> 24); SPIx_ReadWriteByte(arg >> 16); SPIx_ReadWriteByte(arg >> 8); SPIx_ReadWriteByte(arg); SPIx_ReadWriteByte(crc); //等待响应,或超时退出

while((r1=SPIx_ReadWriteByte(0xFF))==0xFF) {

Retry++;

if(Retry>200)break; }

//关闭片选 SD_CS=1;

//在总线上额外增加

8

个时钟,让

SD

卡完成剩下的工作

SPIx_ReadWriteByte(0xFF); //返回状态值 return r1;

//向

SD

卡发送一个命令(结束是不失能片选,还有后续数据传来) //输入:u8 cmd 命令

//

u32 arg 命令参数 // u8 crc crc

校验值

//返回值:SD

卡返回的响应

u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc) {

u8 Retry=0; u8 r1;

SPIx_ReadWriteByte(0xff);//高速写命令延时 SPIx_ReadWriteByte(0xff); SD_CS=0;//片选端置低,选中

SD

卡 //发送

SPIx_ReadWriteByte(cmd | 0x40); //分别写入命令 SPIx_ReadWriteByte(arg >> 24); SPIx_ReadWriteByte(arg >> 16); SPIx_ReadWriteByte(arg >> 8); SPIx_ReadWriteByte(arg); SPIx_ReadWriteByte(crc);

}

//等待响应,或超时退出

while((r1=SPIx_ReadWriteByte(0xFF))==0xFF) {

Retry++;

if(Retry>200)break; }

//返回响应值 return r1; //把

SD

卡设置到挂起模式

//返回值:0,成功设置 //

1,设置失败

u8 SD_Idle_Sta(void) {

u16 i;

u8 retry;

for(i=0;i<0xf00;i++);//纯延时,等待

SD

卡上电完成

//先产生>74

个脉冲,让 SD

卡自己初始化完成

for(i=0;i<10;i++)SPIx_ReadWriteByte(0xFF);

//-----------------SD

卡复位到 idle

开始-----------------

//循环连续发送

CMD0,直到

SD

卡返回

0x01,进入

IDLE

状态 //超时则直接退出

retry = 0; do {

//发送

CMD0,让

SD

卡进入

IDLE

状态 i = SD_SendCommand(CMD0, 0, 0x95);

retry++;

}while((i!=0x01)&&(retry<200));

//跳出循环后,检查原因:初始化成功?or 重试超时? if(retry==200)return 1; //失败 return 0;//成功 }

//初始化

SD

//如果成功返回,则会自动设置

SPI

速度为

18Mhz

//返回值:0:NO_ERR //

1:TIME_OUT

//

99:NO_CARD

u8 SD_Init(void) {

u8 r1;

// 存放

SD

卡的返回值 u16 retry; // 用来进行超时计数

u8 buff[6];

//设置硬件上与SD卡相关联的控制引脚输出

//避免NRF24L01/W25X16等的影响

RCC->APB2ENR|=1<<2;//PORTA时钟使能

GPIOA->CRL&=0XFFF000FF;

GPIOA->CRL|=0X00033300;//PA2.3.4 推挽

GPIOA->ODR|=0X7<<2;//PA2.3.4上拉

SPIx_Init();

SPIx_SetSpeed(SPI_SPEED_256);//设置到低速模式

SD_CS=1;

if(SD_Idle_Sta()) return 1;//超时返回1 设置到idle 模式失败

//-----------------SD卡复位到idle结束-----------------

//获取卡片的SD版本信息

SD_CS=0;

r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);

//如果卡片版本信息是v1.0版本的,即r1=0x05,则进行以下初始化

if(r1 == 0x05)

{

//设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC

SD_Type = SD_TYPE_V1;

//如果是V1.0卡,CMD8指令后没有后续数据

//片选置高,结束本次命令

SD_CS=1;

//多发8个CLK,让SD结束后续操作

SPIx_ReadWriteByte(0xFF);

//-----------------SD卡、MMC卡初始化开始-----------------

//发卡初始化指令CMD55+ACMD41

// 如果有应答,说明是SD卡,且初始化完成

// 没有回应,说明是MMC卡,额外进行相应初始化

retry = 0;

do

{

//先发CMD55,应返回0x01;否则出错

r1 = SD_SendCommand(CMD55, 0, 0);

if(r1 == 0XFF)return r1;//只要不是0xff,就接着发送

//得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次

r1 = SD_SendCommand(ACMD41, 0, 0);

retry++;

}while((r1!=0x00) && (retry<400));

// 判断是超时还是得到正确回应

// 若有回应:是SD卡;没有回应:是MMC卡

//----------MMC卡额外初始化操作开始------------

if(retry==400)

{

}

retry = 0;

//发送

MMC

卡初始化命令(没有测试)

do {

r1 = SD_SendCommand(1,0,0); retry++;

}while((r1!=0x00)&& (retry<400));

if(retry==400)return 1; //MMC

卡初始化超时 //写入卡类型

SD_Type = SD_TYPE_MMC; //----------MMC

卡额外初始化操作结束------------

//设置

SPI

为高速模式

SPIx_SetSpeed(SPI_SPEED_4);

SPIx_ReadWriteByte(0xFF); //禁止

CRC

校验

r1 = SD_SendCommand(CMD59, 0, 0x95); if(r1 != 0x00)return r1; //命令错误,返回

r1 //设置

Sector Size

r1 = SD_SendCommand(CMD16, 512, 0x95); if(r1 != 0x00)return r1;//命令错误,返回

r1

//-----------------SD

卡、MMC

卡初始化结束-----------------

}//SD

卡为 V1.0

版本的初始化结束

//下面是

V2.0

卡的初始化

//其中需要读取

OCR

数据,判断是

SD2.0

还是

SD2.0HC

else if(r1 == 0x01) {

//V2.0

的卡,CMD8

命令后会传回

4

字节的数据,要跳过再结束本命令

buff[0] = SPIx_ReadWriteByte(0xFF); //should be 0x00 buff[1] = SPIx_ReadWriteByte(0xFF); //should be 0x00 buff[2] = SPIx_ReadWriteByte(0xFF); //should be 0x01 buff[3] = SPIx_ReadWriteByte(0xFF); //should be 0xAA SD_CS=1;

SPIx_ReadWriteByte(0xFF);//the next 8 clocks //判断该卡是否支持

2.7V-

3.6V

的电压范围

//if(buff[2]==0x01 && buff[3]==0xAA) //不判断,让其支持的卡更多 {

retry = 0;

//发卡初始化指令

CMD55+ACMD41

do {

r1 = SD_SendCommand(CMD55, 0, 0);

if(r1!=0x01)return r1;

r1 = SD_SendCommand(ACMD41, 0x40000000, 0);

if(retry>200)return r1;//超时则返回r1状态

}while(r1!=0);

//初始化指令发送完成,接下来获取OCR信息

//-----------鉴别SD2.0卡版本开始-----------

r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);

if(r1!=0x00)

{

SD_CS=1;//释放SD片选信号

return r1;//如果命令没有返回正确应答,直接退出,返回应答

} }

}//读OCR指令发出后,紧接着是4字节的OCR信息

buff[0] = SPIx_ReadWriteByte(0xFF);

buff[1] = SPIx_ReadWriteByte(0xFF);

buff[2] = SPIx_ReadWriteByte(0xFF);

buff[3] = SPIx_ReadWriteByte(0xFF);

//OCR接收完成,片选置高

SD_CS=1;

SPIx_ReadWriteByte(0xFF);

//检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC //如果CCS=1:SDHC CCS=0:SD2.0

if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC;//检查CCS

else SD_Type = SD_TYPE_V2;

//-----------鉴别SD2.0卡版本结束-----------

//设置SPI为高速模式

SPIx_SetSpeed(SPI_SPEED_4);

}

return r1;

//从SD卡中读回指定长度的数据,放置在给定位置

//输入: u8 *data(存放读回数据的内存>len)

//u16 len(数据长度)

//u8 release(传输完成后是否释放总线CS置高 0:不释放 1:释放)//返回值:0:NO_ERR

//other:错误信息

u8 SD_ReceiveData(u8 *data, u16 len, u8 release)

{

// 启动一次传输

} SD_CS=0;

if(SD_GetResponse(0xFE))//等待

SD

卡发回数据起始令牌

0xFE

{

SD_CS=1; return 1;

}

while(len--)//开始接收数据 {

*data=SPIx_ReadWriteByte(0xFF); data++;

}

//下面是

2

个伪

CRC (dummy CRC )

SPIx_ReadWriteByte(0xFF);

SPIx_ReadWriteByte(0xFF);

if(release==RELEASE)//按需释放总线,将

CS

置高

{

SD_CS=1;//传输结束 SPIx_ReadWriteByte(0xFF); }

return 0;

//获取

SD

卡的

CID

信息,包括制造商信息

//输入: u8 *cid_data(存放

CID

的内存,至少

16Byte ) //返回值:0:NO_ERR

// 1:TIME_OUT

//

other :错误信息

u8 SD_GetCID(u8 *cid_data) {

u8 r1;

//发

CMD10

命令,读

CID

r1 = SD_SendCommand(CMD10,0,0xFF);

if(r1 != 0x00)return r1; //没返回正确应答,则退出,报错 SD_ReceiveData(cid_data,16,RELEASE);//接收 16

个字节的数据

return 0; }

//获取

SD

卡的

CSD

信息,包括容量和速度信息

//输入:u8 *cid_data(存放

CID

的内存,至少

16Byte )

//返回值:0:NO_ERR // 1:TIME_OUT //

other :错误信息

u8 SD_GetCSD(u8 *csd_data)

{

u8 r1;

r1=SD_SendCommand(CMD9,0,0xFF);//发CMD9命令,读CSD

if(r1)return r1;//没返回正确应答,则退出,报错

SD_ReceiveData(csd_data, 16, RELEASE);//接收16个字节的数据return 0;

}

//获取SD卡的容量(字节)

//返回值:0:取容量出错

//其他:SD卡的容量(字节)

u32 SD_GetCapacity(void)

{

u8 csd[16];

u32 Capacity;

u8 r1;

u16 i;

u16 temp;

//取CSD信息,如果期间出错,返回0

if(SD_GetCSD(csd)!=0) return 0;

//如果为SDHC卡,按照下面方式计算

if((csd[0]&0xC0)==0x40)

{

Capacity=((u32)csd[8])<<8;

Capacity+=(u32)csd[9]+1;

Capacity = (Capacity)*1024;//得到扇区数

Capacity*=512;//得到字节数

}

else

{

i = csd[6]&0x03;

i<<=8;

i += csd[7];

i<<=2;

i += ((csd[8]&0xc0)>>6);

//C_SIZE_MULT

r1 = csd[9]&0x03;

r1<<=1;

r1 += ((csd[10]&0x80)>>7);

r1+=2;//BLOCKNR

temp = 1;

while(r1)

{

}

temp*=2; r1--;

}

Capacity = ((u32)(i+1))*((u32)temp); // READ_BL_LEN i = csd[5]&0x0f; //BLOCK_LEN temp = 1; while(i) {

temp*=2; i--;

}

//The final result

Capacity *= (u32)temp;//字节为单位 } return (u32)Capacity;

//读

SD

卡的一个

block

//输入:u32 sector 取地址(sector

值,非物理地址)

//

u8 *buffer 数据存储地址(大小至少

512byte )

//返回值:0: 成功 //

other :失败

u8 SD_ReadSingleBlock(u32 sector, u8 *buffer) {

u8 r1;

//设置为高速模式

SPIx_SetSpeed(SPI_SPEED_4);

//如果不是

SDHC ,给定的是

sector

地址,将其转换成 byte

地址

if(SD_Type!=SD_TYPE_V2HC) {

sector = sector<<9;

}

r1 = SD_SendCommand(CMD17, sector, 0);//读命令 if(r1 != 0x00)return r1;

r1 = SD_ReceiveData(buffer, 512, RELEASE); if(r1 != 0)return r1; //读数据出错!

else return 0;

}

/////////////////下面

2

个函数为

USB

读写所需要的/////////////////////////

//定义SD卡的块大小

#define BLOCK_SIZE 512

//写入MSD/SD数据

//pBuffer:数据存放区

//ReadAddr:写入的首地址

//NumByteToRead:要写入的字节数

//返回值:0,写入完成

//其他,写入失败

u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite) {

u32 i,NbrOfBlock = 0, Offset = 0;

u32 sector;

u8 r1;

NbrOfBlock = NumByteToWrite / BLOCK_SIZE;//得到要写入的块的数目SD_CS=0;

while (NbrOfBlock--)//写入一个扇区

{

sector=WriteAddr+Offset;

if(SD_Type==SD_TYPE_V2HC)sector>>=9;//执行与普通操作相反的操作

} r1=SD_SendCommand_NoDeassert(CMD24,sector,0xff);//写命令if(r1)

{

SD_CS=1;

return 1;//应答不正确,直接返回

}

SPIx_ReadWriteByte(0xFE);//放起始令牌0xFE

//放一个sector的数据

for(i=0;i<512;i++)SPIx_ReadWriteByte(*pBuffer++);

//发2个Byte的dummy CRC

SPIx_ReadWriteByte(0xff);

SPIx_ReadWriteByte(0xff);

if(SD_WaitDataReady())//等待SD卡数据写入完成

{

SD_CS=1;

return 2;

}

Offset += 512;

//写入完成,片选置1

SD_CS=1;

SPIx_ReadWriteByte(0xff); return 0;

}

//读取MSD/SD数据

//pBuffer:数据存放区

//ReadAddr:读取的首地址

//NumByteToRead:要读出的字节数

//返回值:0,读出完成

//其他,读出失败

u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead)

{

u32 NbrOfBlock=0,Offset=0;

u32 sector=0;

u8 r1=0;

NbrOfBlock=NumByteToRead/BLOCK_SIZE;

SD_CS=0;

while (NbrOfBlock --)

{

sector=ReadAddr+Offset;

if(SD_Type==SD_TYPE_V2HC)sector>>=9;//执行与普通操作相反的操作

r1=SD_SendCommand_NoDeassert(CMD17,sector,0xff);//读命令

} if(r1)//命令发送错误

{

SD_CS=1;

return r1;

}

r1=SD_ReceiveData(pBuffer,512,RELEASE); if(r1)//读数错误

{

SD_CS=1;

return r1;

}

pBuffer+=512;

Offset+=512;

} SD_CS=1;

SPIx_ReadWriteByte(0xff); return 0;

////////////////////////////////////////////////////////////////////////// //写入SD卡的一个block(未实际测试过)

//输入:u32 sector 扇区地址(sector值,非物理地址)

//u8 *buffer 数据存储地址(大小至少512byte)

//返回值:0:成功

//other:失败

u8 SD_WriteSingleBlock(u32 sector, const u8 *data)

{

u8 r1;

u16 i;

u16 retry;

//设置为高速模式

//SPIx_SetSpeed(SPI_SPEED_HIGH);

//如果不是SDHC,给定的是sector地址,将其转换成byte地址if(SD_Type!=SD_TYPE_V2HC)

{

sector = sector<<9;

}

r1 = SD_SendCommand(CMD24, sector, 0x00);

if(r1 != 0x00)

{

return r1;//应答不正确,直接返回

}

//开始准备数据传输

SD_CS=0;

//先放3个空数据,等待SD卡准备好

SPIx_ReadWriteByte(0xff);

SPIx_ReadWriteByte(0xff);

SPIx_ReadWriteByte(0xff);

//放起始令牌0xFE

SPIx_ReadWriteByte(0xFE);

//放一个sector的数据

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

{

SPIx_ReadWriteByte(*data++);

}

//发2个Byte的dummy CRC

SPIx_ReadWriteByte(0xff);

SPIx_ReadWriteByte(0xff);

//等待SD卡应答

r1 = SPIx_ReadWriteByte(0xff);

if((r1&0x1F)!=0x05)

{

SD_CS=1;

return r1;

}

//等待操作完成

retry = 0;

while(!SPIx_ReadWriteByte(0xff))

{

retry++;

if(retry>0xfffe)//如果长时间写入没有完成,报错退出

{

SD_CS=1;

return 1;//写入超时返回1

}

}

//写入完成,片选置1

SD_CS=1;

SPIx_ReadWriteByte(0xff);

return 0;

}

//读SD卡的多个block(实际测试过)

//输入:u32 sector 扇区地址(sector值,非物理地址)

//u8 *buffer 数据存储地址(大小至少512byte)

//u8 count 连续读count个block

//返回值:0:成功

//other:失败

u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)

{

u8 r1;

//SPIx_SetSpeed(SPI_SPEED_HIGH);//设置为高速模式

//如果不是SDHC,将sector地址转成byte地址

if(SD_Type!=SD_TYPE_V2HC)sector = sector<<9;

//SD_WaitDataReady();

//发读多块命令

r1 = SD_SendCommand(CMD18, sector, 0);//读命令

if(r1 != 0x00)return r1;

do//开始接收数据

{

if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)break;

}

buffer += 512; } while(--count);

//全部传输完毕,发送停止命令 SD_SendCommand(CMD12, 0, 0); //释放总线

SD_CS=1;

SPIx_ReadWriteByte(0xFF);

if(count != 0)return count;

//如果没有传完,返回剩余个数

else return 0; //写入

SD

卡的

N

block(未实际测试过)

//输入:u32 sector 扇区地址(sector

值,非物理地址)

//

u8 *buffer 数据存储地址(大小至少

512byte )

//

u8 count 写入的 block

数目 //返回值:0: 成功

//

other :失败

u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count) {

u8 r1;

u16 i;

//SPIx_SetSpeed(SPI_SPEED_HIGH);//设置为高速模式

if(SD_Type != SD_TYPE_V2HC)sector = sector<<9;//如果不是 sector

地址,将其转换成

byte

地址

SDHC ,给定的是

if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count, 0x00);//

如果目标卡不是

MMC

卡,启用

ACMD23

指令使能预擦除

r1 = SD_SendCommand(CMD25, sector, 0x00);//发多块写入指令

if(r1 != 0x00)return r1; //应答不正确,直接返回

SD_CS=0;//开始准备数据传输

SPIx_ReadWriteByte(0xff);//先放

3

个空数据,等待

SD

卡准备好

SPIx_ReadWriteByte(0xff);

//--------下面是

N

个 sector

写入的循环部分

do {

//放起始令牌

0xFC 表明是多块写入

SPIx_ReadWriteByte(0xFC); //放一个

sector

的数据

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

SPIx_ReadWriteByte(*data++); }

//发

2

Byte

dummy CRC SPIx_ReadWriteByte(0xff);

SPIx_ReadWriteByte(0xff);

}

//等待SD卡应答

r1 = SPIx_ReadWriteByte(0xff);

if((r1&0x1F)!=0x05)

{

SD_CS=1;//如果应答为报错,则带错误代码直接退出

return r1;

}

//等待SD卡写入完成

if(SD_WaitDataReady()==1)

{

SD_CS=1;//等待SD卡写入完成超时,直接退出报错

return 1;

}

}while(--count);//本sector数据传输完成

//发结束传输令牌0xFD

r1 = SPIx_ReadWriteByte(0xFD);

if(r1==0x00)

{

count =0xfe;

}

if(SD_WaitDataReady()) //等待准备好

{

SD_CS=1;

return 1;

}

//写入完成,片选置1

SD_CS=1;

SPIx_ReadWriteByte(0xff);

return count;//返回count值,如果写完则count=0,否则count=1

//在指定扇区,从offset开始读出bytes个字节

//输入:u32 sector 扇区地址(sector值,非物理地址)

//u8 *buf数据存储地址(大小<=512byte)

//u16 offset在扇区里面的偏移量

//u16 bytes要读出的字节数

//返回值:0:成功

//other:失败

u8 SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes)

{

寄存器和存储器的区别

https://www.sodocs.net/doc/266314019.html,/p-20032411.html

寄存器和存储器的区别

如果仅是讨论CPU的范畴 寄存器在cpu的内部,容量小,速度快 存储器一般都在cpu外部,容量大,速度慢 回答者:athlongyj - 高级经理六级6-1 08:52 从根本上讲,寄存器与RAM的物理结构不一样。 一般寄存器是指由基本的RS触发器结构衍生出来的D触发, 就是一些与非门构成的结构,这个在数电里面大家都看过; 而RAM则有自己的工艺,一般1Bit由六MOS管构成。所以, 这两者的物理结构不一样也导致了两者的性能不同。寄存器 访问速度快,但是所占面积大。而RAM相反,所占面积小, 功率低,可以做成大容量存储器,但访问速度相对慢一点。 1、 寄存器存在于CPU中,速度很快,数目有限; 存储器就是内存,速度稍慢,但数量很大; 计算机做运算时,必须将数据读入寄存器才能运算。 2、 存储器包括寄存器, 存储器有ROM和RAM 寄存器只是用来暂时存储,是临时分配出来的,断电,后,里面的内容就没了`````

寄存器跟存储器有什么区别? 一般数据在内存里面,要处理(或运算)的时候, 独到寄存器里面。 然后CPU到寄存器里面拿值,拿到运算核内部, 算好了在送到寄存器里面 再到内存 寄存器跟存储器有什么区别? 寄存器跟存储器有什么区别? 寄存器上:“一个操作码+一个操作数”等于一条微指令吗?一条微指令是完成一条机器指令的一个步骤对吗?cpu是直接跟寄存器打交道的对吗?也就是说寄存器是运算器、控制器的组成部分对不? 设计一条指令就是说把几条微指令组合起来对吗? 刚开始学硬件相关知识,学的晕头转向的!! 存储器与寄存器区别 2009-06-09 12:27 寄存器是CPU内部存储单元,数量有限,一般在128bit内,但是速度快,CPU访问几乎没有任何延迟。分为通用寄存器和特殊功能寄存器。 通常说的存储器是独立于cpu之外的,比如内存,硬盘,光盘等。 所有数据必须从存储器传入寄存器后,cpu才能使用。

单片机读写SD卡API模式读写

单片机读写SD卡最简单最基本的程序 处理器:s3c44b0 (arm7) SD卡与处理器的引脚连接:MISO -->SIORxD MOSI -->SIOTxD CLK -->SCLK CS -->PE5 四个文件::用户API函数,移植时不需修改 :中间层函数,移植时不需修改 :硬件层函数,移植时需修改 :一些功能的宏定义,移植时需修改 第一次读写SD卡时,需调用SD_Init(void),然后就可以条用Read_Single_Block或者Write_Single_Block进行读写操作 注意:进行写操作时,最好不要写前700个扇区,应为这些扇区都是FAT文件系统的重要扇区,一旦误写则可能会导致SD无法被电脑识别,需格式化。 /******************************************************* 文件名: 作用:用户API函数,包括四个函数, 读取一块扇区(512字节)U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf) 写一个扇区(512字节)U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf) 获取SD卡基本信息,即读CSD寄存器信息(16字节):void SD_info() SD卡初始化:U8 SD_Init(void) ********************************************************/

/******************************************** 功能:读取一个block 输入:blk_addr为第几个block,rx_buf为数据缓存区首地址输出:返回NO_ERR则成功,其它则读取失败 ********************************************/ U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf) { U16 rsp = 1; U8 i = 0; SD_sel(); //使能SD卡 while(rsp && (i < 100)) { write_cmd(CMD17, blk_addr << 9); //写命令CMD17 rsp = Get_rsp(R1); //获取答应 send_clk(); } if(i > 99) //如果命令超时,则执行超时处理 {

STM32读写SD卡要点

3.20SD卡实验 很多单片机系统都需要大容量存储设备,以存储数据。目前常用的有U盘,FLASH芯片,SD卡等。他们各有优点,综合比较,最适合单片机系统的莫过于SD卡了,它不仅容量可以做到很大(32Gb以上),而且支持SPI接口,方便移动,有几种体积的尺寸可供选择(标准的SD 卡尺寸,以及TF卡尺寸),能满足不同应用的要求。只需要4个IO口,就可以外扩一个最大达32GB以上的外部存储器,容量选择尺度很大,更换也很方便,而且方便移动,编程也比较简单,是单片机大容量外部存储器的首选。 ALIENTKE MiniSTM3开发板就带有SD卡接口,利用STM32自带的SPI接口,最大通信速度可达18Mbps,每秒可传输数据2M字节以上,对于一般应用足够了。本节将向大家介绍,如何在ALIENTEK MiniSTM32开发板上读取SD卡。本节分为如下几个部分: 3.20.1 SD卡简介 3.20.2 硬件设计 3.20.3 软件设计 3.20.4 下载与测试

3.20.1 SD卡简介 SD卡(Secure Digital Memory Card)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。 SD卡一般支持2种操作模式: 1,SD卡模式; 2,SPI模式; 主机可以选择以上任意一种模式同SD卡通信,SD卡模式允许4线的高速数据传输。SPI模式允许简单的通过SPI接口来和SD卡通信,这种模式同SD卡模式相比就是丧失了速度。 SD卡的引脚排序如下图所示: 图3.20.1.1 SD卡引脚排序图 SD卡引脚功能描述如下表所示: 表3.20.1.1 SD卡引脚功能表 SD卡只能使用3.3V的IO电平,所以,MCU一定要能够支持3.3V的IO端口输出。 注意:在SPI模式下,CS/MOSI/MISO/CLK都需要加10~100K左右的上拉电阻。 SD卡要进入SPI模式很简单,就是在SD卡收到复位命令(CMD0)时,CS为有效电平(低电平)则SPI模式被启用。不过在发送CMD0之前,要发送>74个时钟,这是因为SD卡内部有个供电电压上升时间,大概为64个CLK,剩下的10个CLK用于SD卡同步,之后才能开始CMD0的操作,在卡初始化的时候,CLK时钟最大不能超过400Khz!。 ALENTEK MiniSTM32开发板使用的是SPI模式来读写SD卡,下面我们就重点介绍一下SD卡在SPI模式下的相关操作。 首先介绍SPI模式下几个重要的操作命令,如下表所示:

SD卡初始化及读写流程

SD卡初始化及读写流程 默认分类2010-03-03 21:03:00 阅读264 评论0 字号:大中小 SD卡调试关键点: 1. 上电时要延时足够长的时间给SD卡一个准备过程,在我的程 序里是5秒,根据不同的卡设置不同的延时时间。SD卡初始化第一步在发送CMD命令之前,在片选有效的情况下首先要发送至少74个时钟,否则将有可能出现SD卡不能初始化的问题。 2. SD卡发送复位命令CMD0后,要发送版本查询命令CMD8, 返回状态一般分两种,若返回0x01表示此SD卡接受CMD8,也就是说此SD卡支持版本2;若返回0x05则表示此SD卡支持版本1。因为不同版本的SD卡操作要求有不一样的地方,所以务必查询SD卡的版本号,否则也会出现SD卡无法正常工作的问题。 3. 理论上要求发送CMD58获得SD卡电压参数,但实际过程中 由于事先都知道了SD卡的工作电压,因此可省略这一步简化程序。协议书上也建议尽量不要用这个命令。 4. SD卡读写超时时间要按照协议说明书书上的给定值(读超时: 100ms;写超时:250ms),这个值要在程序中准确计算出来,否

则将会出现不能正常读写数据的问题。我自己定义了一个计算公 式:超时时间=(8/clk)*arg。 5. 2GB以内的SD卡(标准卡)和2GB以上的SD卡(大容量卡)在 地址访问形式上不同,这一点尤其要注意,否则将会出现无法读写数据的问题。如标准卡在读写操作时,对读或写命令令牌当中的地址域符初值0x10,表示对第16个字节以后的地址单元进行操作(前提是此SD卡支持偏移读写操作),而对大容量卡读或写命令令牌当中的地址域符初值0x10时,则表示对第16块进行读写操作,而且大容量卡只支持块读写操作,块大小固定为512字节, 对其进行字节操作将会出错。 6. 对某一块要进行写操作时最好先执行擦出命令,这样写入的速 度就能大大提高。进行擦除操作时不管是标准卡还是大容量卡都按块操作执行,也就是一次擦除至少512字节。 7. 对标准卡进行字节操作时,起始和终止必须在一个物理扇区 内,否则将不能进行读写操作。实际操作过程中建议用块操作以提高效率。不管是标准卡还是大容量卡一个读写命令只能对一个块进行操作,不允许跨物理层地址操作。

sd卡读写程序(SDcardreadandwriteprogram)

sd 卡读写程序( SD card read and write program ) SD card read and write program Objective: To study the SD card / / operation Design / software 1, using SPI communication / / SD card 2, go to SD / / in order to 0-255 a total of 256 data, and then read back LCD1602 display / / hardware requirements: S11 ON / / dial switch Jumper J18 / / all connected #include //dsPIC30F6014 standard header file _FOSC( CSW_FSCM_O&F FX T_PLL4); //4 doubler crystal oscillator, Failsafe clock closed _FWDT (WDT_OFF); / / close the watchdog timer _FBORPO(RP BOR_OFF& MCLR_EN);/ / reset prohibited MCLRr eset enable. _FGS (CODE_PROT_OFF); / / code protection against #define CS PORTGbits.RG9 / / SD card selection pin definition #define RSL https://www.sodocs.net/doc/266314019.html,TB4 / / definition LCDc ontrol bits (note here can only register with LATB, you cannot directly use the

寄存器概念整理

寄存器、RAM、ROM、Flash相关概念区别整理 寄存器 寄存器是中央处理器内的组成部份。它跟CPU有关。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。 存储器 存储器范围最大,它几乎涵盖了所有关于存储的范畴。你所说的寄存器,内存,都是存储器里面的一种。凡是有存储能力的硬件,都可以称之为存储器,这是自然,硬盘更加明显了,它归入外存储器行列,由此可见——。 内存 内存既专业名上的内存储器,它不是个什么神秘的东西,它也只是存储器中的沧海一粟,它包涵的范围也很大,一般分为只读存储器和随即存储器,以及最强悍的高速缓冲存储器(CACHE),只读存储器应用广泛,它通常是一块在硬件上集成的可读芯片,作用是识别与控制硬件,它的特点是只可读取,不能写入。随机存储器的特点是可读可写,断电后一切数据都消失,我们所说的内存条就是指它了。 CACHE 高速缓冲存储器(Cache)其原始意义是指存取速度比一般随机存取记忆体(RAM)来得快的一种RAM,一般而言它不像系统主记忆体那样使用DRAM技术,而使用昂贵但较快速的SRAM技术,也有快取记忆体的名称。 CACHE是在CPU中速度非常块,而容量却很小的一种存储器,它是计算机存储器中最强悍的存储器。由于技术限制,容量很难提升,一般都不过兆。 ROM、RAM的区别: ROM(只读存储器或者固化存储器) RAM(随机存取存储器) ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。 RAM有两大类,一种称为静态RAM(Static RAM/SRAM),当数据被存入其中后不会消失。SRAM速度非常快,是目前读写最快的存储设备了。当这个SRAM 单元被赋予0 或者1 的状态之后,它会保持这个状态直到下次被赋予新的状态或者断电之后才会更改或者消失。但是存储1bit 的信息需要4-6 只晶体管。因此它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲。另一种称为动态RAM(Dynamic

SD卡读写操作

SD卡操作 一、概述 1、简介 SD卡是基于flash的存储卡。 SD卡和MMC卡的区别在于初始化过程不同。 SD卡的通信协议包括SD和SPI两类。 SD卡使用卡内智能控制模块进行FLASH操作控制,包括协议、安全算法、数据存取、ECC算法、缺陷处理和分析、电源管理、时钟管理。

2、功能介绍 2.1 特点 1)主机无关的FLASH内存擦除和编程 读或写数据,主机只要发送一个带地址的命令,然后等待命令完成,主机无需关心具体操作的完成。当采用新型的FLASH时,主机代码无需更新。 2)缺陷管理 3)错误恢复 4)电源管理 Flash每个扇区有大约10万次的写寿命,读没有限制。 擦除操作可以加速写操作,因为在写之前会进行擦除。 3 SD总线模式 3.1 Negotiating Operation Conditions 当主机定义了SD卡不支持的电压范围时,SD卡将处于非活动状态,将忽略所有的总线传输。要退出非活动状态唯一的方法就是重新上电。 3.2 SD卡获取和识别 SD卡总线采用的是单主多从结构,总线上所有卡共用时钟和电源线。主机依次分别访问每个卡,每个卡的CID寄存器中已预编程了一个唯一的卡标识号,用来区分不同的卡。 主机通过READ_CID命令读取CID寄存器。CID寄存器在SD卡生产过程中的测试和格式化时被编程,主机只能读取该号。 DAT3线上内置的上拉电阻用来侦测卡。在数据传输时电阻断开(使用ACMD42)。

3.3 卡状态 卡状态分别存放在下面两个区域: 卡状态(Card Status),存放在一个32位状态寄存器,在卡响应主机命令时作为数据传送给主机。 SD状态(SD_Status),当主机使用SD_STATUS(ACMD13)命令时,512位以一个数据块的方式发送给主机。SD_STATUS还包括了和BUS_WIDTH、安全相关位和扩展位等的扩展状态位。 3.4 内存组织 数据读写的基本单元是一个字节,可以按要求组织成不同的块。

单片机读写SD卡教程

郑重声明:本实验并不是对所有SD卡都能成功运行第一步:打开winhex软件,用读卡器读SD卡,在winhex中查看SD卡

点击查找(ctrl+F) 输入FAT(找到DBR处)

发现DBR起始于0x11200扇区地址,它必是512整数倍,因为一个扇区含512BYTE,所以在程序中读一个扇区时一定要是512整数倍,否则会出错。11200地址对应的值是0xEB,本程序读一下这个地址的值看看是否正确。注意有的winhex编址是十进制 看看程序吧 #include #define uchar unsigned char #define uint unsigned int //============================================================= //定义SD卡需要的4根信号线 sbit SD_CLK = P1^1; sbit SD_DI = P1^2; sbit SD_DO = P1^0; sbit SD_CS = P1^3; sbit Beep=P2^0;//用来调程序标志 //=========================================================== //=========================================================== //定义512字节缓冲区,,89C52直接定义成unsigned char DATA[80];,太大了RAM不够unsigned char xdata DATA[512]; void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--); for(y=110;y>0;y--); }

基于Atmega128单片机SD卡读写程序(免费分享)

基于Atmega128单片机SD卡读写程序实物图对照 接线图

以下是一个简单的测试SD卡读写的程序,程序是基于Atmega128单片机编写的,对于Atmega的其他单片机仅需要做管脚改动就可以使用,其他单片机更改要更大。 sd.h //********************************************************** ******** //SPI各线所占用的端口 #define SD_SS PB6 #define SD_SCK PB1 #define SD_MOSI PB2 #define SD_MISO PB3 //********************************************************** ******** #define SD_DDR DDRB #define SD_PORT PORTB #define SD_PIN PINB #define SD_SS_H SD_PORT |= (1<#define SDSS_L SD_PORT &= ~(1<#define SD_SCK_H SD_PORT |= (1<#define SD_SCK_L SD_PORT &= ~(1<#define SD_MOSI_H SD_PORT |= (1<#define SD_MOSI_L SD_PORT

&= ~(1< #define SD_MISO_IN (SD_PIN&(1

通用寄存器存储器实验

计算机组成原理 实验报告 学号: 姓名: 提交日期: 成绩: 东北大学秦皇岛分校 实验三通用寄存器存储器实验 1、实验目的与要求 实验目的: 熟悉通用寄存器的数据通路; 掌握通用寄存器的构成和运用; 熟悉和了解存储器组织与总线组成的数据通路

实验要求: 在掌握了AX、BX运算寄存器的读写操作后,继续完成CX、DX通用寄存器的数据写入与读出; 按照实验步骤完成实验项目,掌握存储部件在原理计算机中的运用。 2、实验原理 通用寄存器: 通用寄存器数据通路如下图所示。由四片8位字长的74LS574组成CX、DX通用寄存器组。途中X1 X2 X0定义为输出选通使能,SI、XP控制位为源选通选择。RXW为寄存器数据写入使能,Q2 Q1 Q0及OP、DI为目的寄存器选择。T4信号为寄存器、对战数据写入脉冲,上升沿有效。准双向I/O 输入输出端口用于置数操作,经2片74LS245三态门与数据总线相连。 存储器: 存储器是计算机的存储部件,用于存放程序和数据。存储器是计算机信息存储的核心,是计算机必不可少的部件之一,计算机就是按存放在存储器中的程序自动有序不间断地进行工作。 本系统从提高存储器存储信息效率的角度设计数据通路,按现代计算机中最为典型的分段存储理念把存储器组织划分为程序段、数据段等,由此派生了数据总线(DBus)、指令总线(IBus)、微总线(μBus)等与现代计算机设计规范相吻合的实验环境。 实验所用的存储器电路原理如图3-1所示,该存储器组织由二片6116构成具有奇偶概念的十六位信息存储体系,该存储体系AddBus由IP指针和AR指针分时提供,E/M控位为“1”时选通IP,反之选通AR。该存储体系可随机定义总线宽度,动态变更总线结构,把我们的教学实验提高到能与现代计算机设计规范相匹配与接轨的层面。

计算机组成原理存储器读写实验报告

《计算机组成原理》实验报告 实验名称:存储器读写实验班级: 学号:姓名: 一、实验目的 1、掌握存储器的工作特征 2、熟悉静态存储器的操作过程,验证存储器的读取方法 二、实验设备 1、YY—Z02计算机组成原理实验仪一台。 2、排线若干。 3、PC微机一台。 三、实验原理 1.存储器是计算机的主要部件,用来保存程序和数据。从工作方式上分类, 其可分为易失性和非易失性存储器,易失性存储器中的数据在关电后将 不复存在,非易失性存储器中的数据在关电后不会丢失。易失性存储器 又可分为动态存储器和静态存储器,动态存储器保存信息的时间只有 2ms,工作时需要不断更新,既不断刷新数据;静态存储器只要不断电, 信息是不会丢失的。 2.静态存储器芯片6116的逻辑功能: 3.存储器实验单元电路:

存储器实验单元电路控制信号逻辑功能表: 4.存储器实验电路: 存储器读写实验需三部分电路共同完成:存储器单元、地址寄存器单元和输入、输出单元。存储器单元以6116芯片为中心构成,地址寄存器单元主要由一片74LS273组成,控制信号B-AR的作用是把总线上的数据送人地址寄存器,向存储器单元电路提供地址信息,输入、输出单元作用与以前相同。

四、实验结果记录 (1)连线准备 1.连接输入、输出实验的全部连线。 2.按实验逻辑原理图连接M-W、M-R两根信号低电平有效信号线。 3.连接A7—A0 8根地址线。 4.连接B-AR正脉冲有效信号线。 (2)记录结果(包含采集结果前的动作) 地址写入数据读出数据结果说明 01H0010000000100000数据的写入与读取02H0001001100010011数据的写入与读取03H0010011000100110数据的写入与读取04H数据的写入与读取05H0000010100000101数据的写入与读取25H不写存储器一个随机地址 36H0010000100100001数据的写入与读取 0A0H写总线悬空时的数 据总线悬空时表示的数据是FFH,即写入的数据是,所以读出结果为 五、实验总结与心得体会

读写SD卡的设计及其程序硬件

前言 长期以来,以Flash Memory为存储体的SD卡因具备体积小、功耗低、可擦写以及非易失性等特点而被广泛应用于消费类电子产品中。特别是近年来,随着价格不断下降且存储容量不断提高,它的应用范围日益增广。当数据采集系统需要长时间地采集、记录海量数据时,选择SD卡作为存储媒质是开发者们一个很好的选择。在电能监测以及无功补偿系统中,要连续记录大量的电压、电流、有功功率、无功功率以及时间等参数,当单片机采集到这些数据时可以利用SD作为存储媒质。本文主要介绍了SD卡在电能监测及无功补偿数据采集系统中的应用方案。 设计方案 应用AT89C52读写SD卡有两点需要注意。首先,需要寻找一个实现AT89C52单片机与SD卡通讯的解决方案;其次,SD卡所能接受的逻辑电平与AT89C52提供的逻辑电平不匹配,需要解决电平匹配问题。 通讯模式 SD卡有两个可选的通讯协议:SD模式和SPI模式。SD模式是SD卡标准的读写方式,但是在选用SD模式时,往往需要选择带有SD卡控制器接口的MCU,或者必须加入额外的SD 卡控制单元以支持SD卡的读写。然而,AT89C52单片机没有集成SD卡控制器接口,若选用SD模式通讯就无形中增加了产品的硬件成本。在SD卡数据读写时间要求不是很严格的情况下,选用SPI模式可以说是一种最佳的解决方案。因为在SPI模式下,通过四条线就可以完成所有的数据交换,并且目前市场上很多MCU都集成有现成的SPI接口电路,采用SPI模式对SD卡进行读写操作可大大简化硬件电路的设计。 虽然AT89C52不带SD卡硬件控制器,也没有现成的SPI接口模块,但是可以用软件模拟出SPI总线时序。本文用SPI总线模式读写SD卡。 电平匹配 SD卡的逻辑电平相当于3.3V TTL电平标准,而控制芯片AT89C52的逻辑电平为5V CMOS 电平标准。因此,它们之间不能直接相连,否则会有烧毁SD卡的可能。出于对安全工作的考虑,有必要解决电平匹配问题。 要解决这一问题,最根本的就是解决逻辑器件接口的电平兼容问题,原则主要有两条:一为输出电平器件输出高电平的最小电压值,应该大于接收电平器件识别为高电平的最低电压值;另一条为输出电平器件输出低电平的最大电压值,应该小于接收电平器件识别为低电平的最高电压值。 一般来说,通用的电平转换方案是采用类似SN74ALVC4245的专用电平转换芯片,这类芯片不仅可以用作升压和降压,而且允许两边电源不同步。但是,这个方案代价相对昂贵,而且一般的专用电平转换芯片都是同时转换8路、16路或者更多路数的电平,相对本系统仅仅需要转换3路来说是一种资源的浪费。

计算机组成原理实验五-存储器读写实验

实验五 存储器读写实验 一、 实验目的 1. 掌握存储器的工作特性。 2. 数学静态存储器的操作过程,验证存储器的读写方法。 二、 实验原理 存储器是计算机的主要部件,用来保存程序和数据。从工作方式上分类,存储器可分成易失性和非易失性存储器,易失性存储器中的数据在关电后将不复存在,非易失性储器又可分为动态存储器和静态存储器,动态存储器保存信息的时间只有2ms ,工作时需要不断更新,既不断刷新数据;静态存储器只要不断电,信息是不会丢失的。为简单起见,计算机组成实验用的是容量为2K 的镜头存储器6116。 1. 静态存储器芯片6116的逻辑功能 6116是一种数据宽度为8位(8个二进制位),容量为2048字节的态存储器芯片,封在24引脚的封装中,封装型式如图2-7所示。6116芯片有8根双向三态数据线D7-D0,所谓三态是指输入状态、输出状态和高阻状态,高阻状态数据线处于一种特殊的“断开”状态;11根地址线A10-A0, 指示芯片内部2048个存储单元号;3根控制线CS ???片选控制信号,低电平时,芯片可进行读写操作,高电平时,芯片保存信息不能进行读写;WE ???为写入控制信号,低电平时,把数据线上的信息存入地址线A10-A0指示的存储 单元中;OE ???为输出使能控制信号,低电平时,把地址线A10-A0指示的存储单元中的数据读出送到数据线上。芯片控制信号逻辑功能见表2-9。 图2-7 存储器部件电路图 2. 存储器实验单元电力路 因为在计算机组成原理实验中仅用了256个存储单元,所以6116芯片 的三根地址线A11-A8接地也没有多片联用问题,片选信号CS ???接地使芯片总是处于被选中状态。芯片的,WE.和OE ???信号分别连接实验台的存储器写信号M ?W ???????和存储器读写信号M ?R ???????,存储器实验单元逻辑电路如图2-7所示。这

SD卡读写的方式(用SD模式)

大家读写SD卡怎么不用SD模式方式读取,是SPI方式读取简单? 下面贴一段代码,是在FPGA上程序,只能用SD模式进行读,没有文件系统,没有用AVR硬件实现,电路图: 电路说明,SD_DAT3一直给高电平 程序: #ifndef __SD_Card_H__ #define __SD_Card_H__ #define High 1 #define Low 0 //------------------------------------------------------------------------- // SD Card Set I/O Direction #define SD_CMD_IN DDRX.1 = Low #define SD_CMD_OUT DDRX.1 = High #define SD_DAT_IN DDRX.2 = Low #define SD_DAT_OUT DDRX.2 = High #define SD_CLK_OUT DDRX.3 = High #define SD_DAT3_OUT DDRX.0 = High // SD Card Output High/Low #define SD_CMD_LOW PORTX.1 = Low

#define SD_CMD_HIGH PORTX.1 = High #define SD_DAT_LOW PORTX.2 = Low #define SD_DAT_HIGH PORTX.2 = High #define SD_CLK_LOW PORTX.3 = Low #define SD_CLK_HIGH PORTX.3 = High #define SD_DAT3_HIGH PORTX.0 = High // SD Card Input Read #define SD_TEST_CMD PINX.1 #define SD_TEST_DAT PINX.2 //------------------------------------------------------------------------- #define BYTE unsigned char #define UINT16 unsigned int #define UINT32 unsigned long //------------------------------------------------------------------------- void Ncr(void); void Ncc(void); BYTE response_R(BYTE); BYTE send_cmd(BYTE *); BYTE SD_read_lba(BYTE *,UINT32,UINT32); BYTE SD_card_init(void); //------------------------------------------------------------------------- BYTE read_status; BYTE response_buffer[20]; BYTE RCA[2]; BYTE cmd_buffer[5]; const BYTE cmd0[5] = {0x40,0x00,0x00,0x00,0x00}; const BYTE cmd55[5] = {0x77,0x00,0x00,0x00,0x00}; const BYTE cmd2[5] = {0x42,0x00,0x00,0x00,0x00}; const BYTE cmd3[5] = {0x43,0x00,0x00,0x00,0x00}; const BYTE cmd7[5] = {0x47,0x00,0x00,0x00,0x00}; const BYTE cmd9[5] = {0x49,0x00,0x00,0x00,0x00}; const BYTE cmd16[5] = {0x50,0x00,0x00,0x02,0x00}; const BYTE cmd17[5] = {0x51,0x00,0x00,0x00,0x00}; const BYTE acmd6[5] = {0x46,0x00,0x00,0x00,0x02}; const BYTE acmd41[5] = {0x69,0x0f,0xf0,0x00,0x00}; const BYTE acmd51[5] = {0x73,0x00,0x00,0x00,0x00}; //------------------------------------------------------------------------- void Ncr(void) { SD_CMD_IN; SD_CLK_LOW; SD_CLK_HIGH; SD_CLK_LOW; SD_CLK_HIGH;

计算机组成原理实验五存储器读写实验

实验五存储器读写实验 一、实验目的 1.掌握存储器的工作特性。 2.数学静态存储器的操作过程,验证存储器的读写方法。 二、实验原理 存储器是计算机的主要部件,用来保存程序和数据。从工作方式上分类,存储器可分成易失性和非易失性存储器,易失性存储器中的数据在关电后将不复存在,非易失性储器又可分为动态存储器和静态存储器,动态存储器保存信息的时间只有2ms,工作时需要不断更新,既不断刷新数据;静态存储器只要不断电,信息是不会丢失的。 为简单起见,计算机组成实验用的是容量为2K的镜头存储器6116。 1.静态存储器芯片6116的逻辑功能 6116是一种数据宽度为8位(8个二进制位),容量为2048字节的态存储器芯片,封在24引脚的封装中,封装型式如图2-7 所示。6116芯片有8根双向三态数据线D7-D0,所谓三态是指输 入状态、输出状态和高阻状态,高阻状态数据线处于一种特殊的 “断开”状态;11根地址线A10-A0,指示芯片内部2048个存储 单元号;3根控制线CS???片选控制信号,低电平时,芯片可进行读 写操作,高电平时,芯片保存信息不能进行读写;WE???为写入控制 信号,低电平时,把数据线上的信息存入地址线A10-A0指示的存 储单元中;OE???为输出使能控制信号,低电平时,把地址线A10-A0 指示的存储单元中的数据读出送到数据线上。芯片控制信号逻辑 功能见表2-9。 表2-9 6116芯片控制信号逻辑功能表 图2-7 存储器部件电路图 2.存储器实验单元电力路

因为在计算机组成原理实验中仅用了256个存储单元,所以6116芯片的三根地址线A11-A8接地也没有多片联用问题,片选 信号CS ???接地使芯片总是处于被选中状态。芯片的,WE.和OE ???信号分别连接实验台的存储器写信号M ?W ???????和存储器读写信号M ?R ???????,存储 器实验单元逻辑电路如图2-7所示。这种简化了控制过程的实验电路可方便实验进行,存储器实验单元电路控制信号逻辑功能见 3. 存储器实验电路 存储器读/写实验需呀三部分电路共同完成:存储器单元(MEM UNIT )、地址寄存器单元(ADDRESS UNIT )和输入、输出单元(INPUT/OUTPUT UNIT )。存储器单元以6116总线上的数据送入地址寄存器,向存储器单元电路提供地址信息,输入、输出单元作用与以前相同。存储器实验的逻辑原理如图2-8所示。 图2-8 存储器实验电路逻辑图 三、 实验过程 1. 连线 (1) 连接实验一(输入、输出实验)的全部连线。 (2) 按实验逻辑原理图连接M ?W ???????、M ?R ???????两根信号低电平有效信号 线。 (3) 连接A7-A0 8根地址线。 (4) 连接B-AR 正脉冲有效信号线。 2. 顺序写入存储单元实验操作过程 (1) 把B-AR 控制开关拨到0(因此信号是正脉冲有效),把其他控 制开关全部拨到1,使全部控制信号都处于无效状态。 (2) 在输入数据开关上拨一个地址数据(如00000001,即16进制 01H ),拨下,IOR.开关,把地址数据送总线。 (3) 拨动一下B-AR 开关,实现“0-1-0”,产生一个正脉冲,把地 址数据送地址寄存器(AR )保存。 (4) IO ?R ?????????控制开关,把实验数据送到总线。 (5) 拨动M ?W ???????控制开关,即实现“0-1-0”,产生一个负脉冲,把 实验数据存入存储器的01H 号单元。

单片机存储器和寄存器

单片机的存储器、寄存器 单片机的存储器有程序存储器ROM与数据存储器RAM两种。这两种存储器在使用上是严格区分的,不得混用。程序存储器存放程序指令,以及常数,表格等;而数据存储器则存放缓冲数据。 MCS-51单片机存储器的结构共有3部分:一是程序存储器二是内部数据存储器三是外部数据存储器MCS-51单片机的存储器可分为5类:程序存储器、内部数据存储器、特殊功能寄存器、位地址空间、外部数据存储器 程序存储器 程序是控制计算机动作的一系列命令,单片机只认识由“0”和“1”代码构成的机器指令。如前述用助记符编写的命令MOV A,#20H,换成机器认识的代码74H、20H:(写成二进制就是01110100B和00100000B)。在单片机处理问题之前必须事先将编好的程序、表格、常数汇编成机器代码后存入单片机的存储器中,该存储器称为程序存储器。程序存储器可以放在片内或片外,亦可片内片外同时设置。由于PC程序计数器为16位,使得程序存储器可用16位二进制地址,因此,内外存储器的地址最大可从0000H到FFFFH。8051内部有4k字节的ROM,就占用了由0000H~0FFFH的最低4k个字节,这时片外扩充的程序存储器地址编号应由1000H开始,如果将8051当做8031使用,不想利用片内4kROM,全用片外存储器,则地址编号仍可由0000H开始。不过,这时应使8051的第{31}脚(即EA脚)保持低电平。当EA为高电平时,用户在0000H至0FFFH范围内使用内部ROM,大于0FFFH后,单片机CPU自动访问外部程序存储器。 数据存储器 单片机的数据存储器由读写存储器RAM组成。其最大容量可扩展到64k,用于存储实时输入的数据。8051内部有256个单元的内部数据存储器,其中00H~7FH为内部随机存储器RAM,80H~FFH为专用寄存器区。实际使用时应首先充分利用内部存储器,从使用角度讲,搞清内部数据存储器的结构和地址分配是十分重要的。因为将来在学习指令系统和程序设计时会经常用到它们。8051内部数据存储器地址由00H至FFH共有256个字节的地址空间,该空间被分为两部分,其中内部数据RAM的地址为00H~7FH(即0~127)。而用做特殊功能寄存器的地址为80H~FFH。在此256个字节中,还开辟有一个所谓“位地址”区,该区域内不但可按字节寻址,还可按“位(bit)”寻址。对于那些需要进行位操作的数据,可以存放到这个区域。从00H到1FH安排了四组工作寄存器,每组占用8个RAM 字节,记为R0~R7。究竟选用那一组寄存器,由前述标志寄存器中的RS1和RS0来选用。在这两位上放入不同的二进制数,即可选用不同的寄存器组。 特殊功能寄存器 特殊功能寄存器(SFR)的地址范围为80H~FFH。在MCS-51中,除程序计数器PC和四个工作寄存器区外,其余21个特殊功能寄存器都在这SFR块中。其中5个是双字节寄存器,它们共占用了26个字节。各特殊功能寄存器的符号和地址见附表2。其中带*号的可位寻址。特殊功能寄存器反映了8051的状态,实际上是8051的状态字及控制字寄存器。用于CPU PSW便是典型一例。这些特殊功能寄存器大体上分为两类,一类与芯片的引脚有关,另一类作片内功能的控制用。与芯片引脚有关的特殊功能寄存器是P0~P3,它们实际上是4个八位锁存器(每个I/O口一个),每个锁存器附加有相应的输出驱动器和输入缓冲器就构成了一个并行口。MCS-51共有P0~P3四个这样的并行口,可提供32 根I/O线,每根线都是双向的,并且大都有第二功能。其余用于芯片控制的寄存器中,累加

实验三:存储器读写实验

计算机组成原理实验报告 Computer Organization Lab Reports ______________________________________________________________________________ 班级: __________ 姓名:___________ 学号:__________ 实验日期:_____________ 学院: _____________________________ 专业:__________________________________ 实验顺序:_______ 原创:___________ 实验名称:______________________________ 实验分数:_______ 考评日期:________ 指导教师:张旭 ______________________________________________________________________________ 一、实验目的 熟悉和了解存储器逻辑结构与总线组成的数据通路及其基本的工作原理。 理解AR地址寄存器与PC地址寄存器的各自的作用。 二、实验要求 按照实验步骤完成实验项目,掌握存储部件在原理计算机中的运用。 三、实验原理 存储器是计算机的存储部件,用于存放程序和数据。存储器是计算机信息存储的核心, 是计算机必不可少的部件之一,计算机就是按存放在存储器中的程序自动有序不间断地进行 工作。 本系统从提高存储器存储信息效率的角度设计数据通路,按现代计算机中最为典型的分 段存储理念把存储器组织划分为程序段、数据段等,由此派生了数据总线(DBus)、指令总 线(IBus)、微总线(μBus)等与现代计算机设计规范相吻合的实验环境。 实验所用的存储器电路原理如图3-1所示,该存储器组织由二片6116构成具有奇偶概 念的十六位信息存储体系,该存储体系AddBus由IP指针和AR指针分时提供,E/M控位 为“1”时选通IP,反之选通AR。该存储体系可随机定义总线宽度,动态变更总线结构, 把我们的教学实验提高到能与现代计算机设计规范相匹配与接轨的层面。 图3-1 存储器数据通路

相关主题