打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
一个比较高效的SPI方式SD卡的驱动
一个比较高效的SPI方式SD卡的驱动 发布时间:2009-03-07 19:22:49
技术类别:接口电路
流传的用SPI驱动SD卡的程序基本都是针对没有FIFO的SPI接口的,这样做程序比较通用;但是如果处理器的SPI接口有FIFO的话,那么FIFO的性能就浪费了。其实把程序稍加改动,就可以大幅度提高SD卡的读取速度,具体程序如下:
/******************************************************/
/*          SD Card driver using SSP for LPC2148      */
/*                   by 314forever                    */
/*                 spi_mmc.c  2009.1                  */
/******************************************************/
#ifndef __SPI_MMC_H__
#define __SPI_MMC_H__
#define SPI_SEL        16
#define SET_MMC_CS FIO0SET = (1 << SPI_SEL);
#define CLR_MMC_CS FIO0CLR = (1 << SPI_SEL);
#define MMC_CMD_SIZE   6        // the SPI data is 8 bit long, the MMC use 48 bits, 6 bytes
#define MMC_DATA_SIZE  512      // data of one sector in byte
#define MAX_TIMEOUT    0xFF     // retry times
#define GO_IDLE_STATE           0x00
#define SEND_CSD                0x09
#define SEND_CID                0x0A
#define READ_SINGLE_BLOCK       0x11
#define WRITE_SINGLE_BLOCK      0x18
#define SEND_OP_COND            0x29
#define APP_CMD                 0x37
#define CRC_ON_OFF              0x3B
void spiSend(BYTE *buffer, DWORD length);
void spiReceive(BYTE *buffer, DWORD length);
BYTE spiReceiveByte(void);
BYTE mmcInit(void);
BOOL mmcReadSector(DWORD sector, BYTE *buffer, DWORD *SectorInCache);
BOOL mmcWriteSector(DWORD sector, BYTE *buffer);
#endif
/******************************************************/
/*          SD Card driver using SSP for LPC2148      */
/*                   by 314forever                    */
/*                 spi_mmc.c  2009.1                  */
/******************************************************/
#include <LPC214X.H>
#include "..\type.h"
#include "spi_mmc.h"
#define sspLowSpeed()   SSPCPSR = 0x80;
#define sspHighSpeed()  SSPCPSR = 0x08;
void sspSend(BYTE *buffer, DWORD length){
BYTE dummy;
while(SSPSR & 0x04)dummy = SSPDR;    // clean FIFO
SSPDR = *buffer;                     // first byte to send
buffer ++;
length --;
while(length){
SSPDR = *buffer;                 // keep FIFO not empty nor not full
buffer ++;
length --;
while(!(SSPSR & 0x04));
dummy = SSPDR;
}
while(!(SSPSR & 0x04));
dummy = SSPDR;
}
void sspReceive(BYTE *buffer, DWORD length){
BYTE dummy;
while(SSPSR & 0x04)dummy = SSPDR;    // clean FIFO
SSPDR = 0xFF;
length --;
while(length){
SSPDR = 0xFF;                    // keep FIFO not empty nor not full
while(!(SSPSR & 0x04));
*buffer = SSPDR;
buffer ++;
length --;
}
while(!(SSPSR & 0x04));              // last byte to receive
*buffer = SSPDR;
}
BYTE sspReceiveByte(void){
SSPDR = 0xFF;
while(SSPSR & 0x10);
return SSPDR;
}
void sspSendByte(BYTE data){
BYTE dummy;
SSPDR = data;
while(SSPSR & 0x10);
dummy = SSPDR;
}
BYTE mmcSendCommand(BYTE command, DWORD argument){
BYTE R1;
BYTE retry ;
BYTE MMCCmd[MMC_CMD_SIZE + 1];
MMCCmd[0]= command | 0x40;
MMCCmd[1]= argument >> 24;
MMCCmd[2]= argument >> 16;
MMCCmd[3]= argument >> 8;
MMCCmd[4]= argument;
if(!command)MMCCmd[5]= 0x95;
else MMCCmd[5]= 0xFF;
MMCCmd[6]= 0xFF;
sspSend(MMCCmd, MMC_CMD_SIZE + 1);
retry = MAX_TIMEOUT;
do{
R1 = sspReceiveByte();
if(!(retry --))break;
}while(R1 == 0xFF);
sspReceiveByte();
return R1;
}
BYTE mmcInit(void){
BYTE i;
BYTE R1;
BYTE retry;
WORD dummy;
PINSEL1 |= 0x000000A8;      // enable SCK(P0.17), MISO(P0.18), MOSI(P0.19)
FIO0DIR |= 1 << SPI_SEL;    // use P0.16 as SSEL of SSP port
FIO0SET = 1 << SPI_SEL;
SSPCR0 = 0x0007;            // 8bit, SPI format, CPOL = 0, CPHA = 0, and SCR is 0
sspLowSpeed();
SSPCR1 = 0x02;              // master mode, SSP enabled, normal operational mode
while(SSPSR & 0x04)dummy = SSPDR; // clear the RxFIFO
retry = MAX_TIMEOUT;
do{
SET_MMC_CS;
for(i = 0; i < 10; i ++)sspReceiveByte();
CLR_MMC_CS;
R1 = mmcSendCommand(GO_IDLE_STATE, 0);  // CMD0
if(!(retry --)){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
}while(R1 != 0x01);
retry = MAX_TIMEOUT;
do{
if(!(retry --)){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
R1 = mmcSendCommand(APP_CMD, 0);  // CMD55
if(R1 != 0x01)continue;
R1 = mmcSendCommand(SEND_OP_COND, 0);  // CMD41
}while(R1 != 0x00);
retry = MAX_TIMEOUT;
do{
R1 = mmcSendCommand(1, 0);  // send active command
if(!(retry --)){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
}while(R1);
sspHighSpeed();
mmcSendCommand(CRC_ON_OFF, 0);  // disable CRC
mmcSendCommand(16, 512);  // set sector size to 512
SET_MMC_CS;
return 0;
}
BOOL mmcReadSector(DWORD sector, BYTE *buffer, DWORD *SectorInCache){
BYTE R1;
BYTE retry = MAX_TIMEOUT;
if(*SectorInCache == sector)return 0;
else *SectorInCache = sector;
CLR_MMC_CS;
R1 = mmcSendCommand(READ_SINGLE_BLOCK, sector << 9);  // read command
if(R1 != 0x00){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
while(sspReceiveByte() != 0xFE){  // wait to start recieve data
if(!(retry --)){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
}
sspReceive(buffer, 512);
sspReceiveByte();  // dummy CRC
sspReceiveByte();
SET_MMC_CS;
sspReceiveByte();  // extra 8 CLK
return 0;
}
BOOL mmcWriteSector(DWORD sector, BYTE *buffer){
BYTE R1;
WORD retry = 0xFFFF;
CLR_MMC_CS;
R1 = mmcSendCommand(WRITE_SINGLE_BLOCK, sector << 9);  // write command
if(R1 != 0x00){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
sspReceiveByte();
sspReceiveByte();
sspSendByte(0xFE);               // start transmit
sspSend(buffer, MMC_DATA_SIZE);  // 512 bytes
sspReceiveByte();                // dummy CRC
sspReceiveByte();
R1 = sspReceiveByte();
if((R1 & 0x1F) != 0x05){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
while(!sspReceiveByte()){        // wait until write finish
if(!(retry --)){
SET_MMC_CS;
sspReceiveByte();
return 1;
}
}
SET_MMC_CS;
sspReceiveByte();
return 0;
}
与通用的程序相比就是在连续发送和连续接收的地方作了一些简单处理。改动不大,但是提升的效率却很惊人,读取速度提高了能有50%左右。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SD卡初始化
从一张示波器截图谈FIFO
深入理解SD卡基础原理以及内部结构的总结
基于单片机的SD卡设计
[笔记].菜农M0助学板之读SD卡块内容小练(库操作方式)
MicroPython之 炫彩跑马灯(TPYBoard V10X系列教程28)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服