#include "sys.h"
#include "mmc_sd.h"
#include "spi.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////
//±¾³ÌÐòÖ»¹©Ñ§Ï°Ê¹Óã¬Î´¾­×÷ÕßÐí¿É£¬²»µÃÓÃÓÚÆäËüÈκÎÓÃ;
//ALIENTEK MiniSTM32¿ª·¢°å
//SD¿¨ Çý¶¯´úÂë
//ÕýµãÔ­×Ó@ALIENTEK
//¼¼ÊõÂÛ̳:
www.openedv.com
//ÐÞ¸ÄÈÕÆÚ:2014/3/13
//°æ±¾£ºV1.0
//°æȨËùÓУ¬µÁ°æ±Ø¾¿¡£
//Copyright(C) ¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾ 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
u8 SD_Type=0;//SD¿¨µÄÀàÐÍ
////////////////////////////////////ÒÆÖ²ÐÞ¸ÄÇø///////////////////////////////////
//ÒÆֲʱºòµÄ½Ó¿Ú
//data:ҪдÈëµÄÊý¾Ý
//·µ»ØÖµ:¶Áµ½µÄÊý¾Ý
u8 SD_SPI_ReadWriteByte(u8 data)
{
return SPI2_ReadWriteByte(data);
}
//SD¿¨³õʼ»¯µÄʱºò,ÐèÒªµÍËÙ
void SD_SPI_SpeedLow(void)
{
SPI2_SetSpeed(SPI_BaudRatePrescaler_256);//ÉèÖõ½µÍËÙģʽ
}
//SD¿¨Õý³£¹¤×÷µÄʱºò,¿ÉÒÔ¸ßËÙÁË
void SD_SPI_SpeedHigh(void)
{
SPI2_SetSpeed(SPI_BaudRatePrescaler_2);//ÉèÖõ½¸ßËÙģʽ
}
//SPIÓ²¼þ²ã³õʼ»¯
void SD_SPI_Init(void)
{
//ÉèÖÃÓ²¼þÉÏÓëSD¿¨Ïà¹ØÁªµÄ¿ØÖÆÒý½ÅÊä³ö
//½ûÖ¹ÆäËûÍâÉè(NRF/W25Q64)¶ÔSD¿¨²úÉúÓ°Ïì
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE); //ʹÄÜ

B¶Ë¿ÚʱÖÓ
//ÉèÖÃÓ²¼þÉÏÓëSD¿¨Ïà¹ØÁªµÄ¿ØÖÆÒý½ÅÊä³ö
//±ÜÃâNRF24L01/W25Q32µÈµÄÓ°Ïì
//͉˕

B12ºÍ

G7À­¸ß,ÊÇΪÁË·ÀÖ¹Ó°ÏìFLASHµÄÉÕд.
//ÒòΪËûÃǹ²ÓÃÒ»¸öSPI¿Ú.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PB12 ÍÆÍì
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12); //PB12ÉÏÀ­
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PD2 ÍÆÍì
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PG7 ÍÆÍì
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_7);
SPI2_Init();
SD_CS=1;
}
///////////////////////////////////////////////////////////////////////////////////
//È¡ÏûÑ¡Ôñ,ÊÍ·ÅSPI×ÜÏß
void SD_DisSelect(void)
{
SD_CS=1;
SD_SPI_ReadWriteByte(0xff);//Ìṩ¶îÍâµÄ8¸öʱÖÓ
}
//Ñ¡Ôñsd¿¨,²¢Çҵȴý¿¨×¼±¸OK
//·µ»ØÖµ:0,³É¹¦;1,ʧ°Ü;
u8 SD_Select(void)
{
SD_CS=0;
if(SD_WaitReady()==0)return 0;//µÈ´ý³É¹¦
SD_DisSelect();
return 1;//µÈ´ýʧ°Ü
}
//µÈ´ý¿¨×¼±¸ºÃ
//·µ»ØÖµ:0,×¼±¸ºÃÁË;ÆäËû,´íÎó´úÂë
u8 SD_WaitReady(void)
{
u32 t=0;
do
{
if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
t++;
}while(t<0XFFFFFF);//µÈ´ý
return 1;
}
//µÈ´ýSD¿¨»ØÓ¦
//Response:ÒªµÃµ½µÄ»ØÓ¦Öµ
//·µ»ØÖµ:0,³É¹¦µÃµ½Á˸ûØÓ¦Öµ
// ÆäËû,µÃµ½»ØӦֵʧ°Ü
u8 SD_GetResponse(u8 Response)
{
u16 Count=0xFFFF;//µÈ´ý´ÎÊý
while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//µÈ´ýµÃµ½×¼È·µÄ»ØÓ¦
if (Count==0)return MSD_RESPONSE_FAILURE;//µÃµ½»ØӦʧ°Ü
else return MSD_RESPONSE_NO_ERROR;//ÕýÈ·»ØÓ¦
}
//´Ósd¿¨¶ÁÈ¡Ò»¸öÊý¾Ý°üµÄÄÚÈÝ
//buf:Êý¾Ý»º´æÇø
//len:Òª¶ÁÈ¡µÄÊý¾Ý³¤¶È.
//·µ»ØÖµ:0,³É¹¦;ÆäËû,ʧ°Ü;
u8 SD_RecvData(u8*buf,u16 len)
{
if(SD_GetResponse(0xFE))return 1;//µÈ´ýSD¿¨·¢»ØÊý¾ÝÆðʼÁîÅÆ0xFE
while(len--)//¿ªÊ¼½ÓÊÕÊý¾Ý
{
*buf=SPI2_ReadWriteByte(0xFF);
buf++;
}
//ÏÂÃæÊÇ2¸öαCRC£¨dummy CRC£©
SD_SPI_ReadWriteByte(0xFF);
SD_SPI_ReadWriteByte(0xFF);
return 0;//¶ÁÈ¡³É¹¦
}
//Ïòsd¿¨Ð´ÈëÒ»¸öÊý¾Ý°üµÄÄÚÈÝ 512×Ö½Ú
//buf:Êý¾Ý»º´æÇø
//cmd:Ö¸Áî
//·µ»ØÖµ:0,³É¹¦;ÆäËû,ʧ°Ü;
u8 SD_SendBlock(u8*buf,u8 cmd)
{
u16 t;
if(SD_WaitReady())return 1;//µÈ´ý×¼±¸Ê§Ð§
SD_SPI_ReadWriteByte(cmd);
if(cmd!=0XFD)//²»ÊǽáÊøÖ¸Áî
{
for(t=0;t<512;t++)SPI2_ReadWriteByte(buf[t]);//Ìá¸ßËÙ¶È,¼õÉÙº¯Êý´«²Îʱ¼ä
SD_SPI_ReadWriteByte(0xFF);//ºöÂÔcrc
SD_SPI_ReadWriteByte(0xFF);
t=SD_SPI_ReadWriteByte(0xFF);//½ÓÊÕÏìÓ¦
if((t&0x1F)!=0x05)return 2;//ÏìÓ¦´íÎó
}
return 0;//дÈë³É¹¦
}
//ÏòSD¿¨·¢ËÍÒ»¸öÃüÁî
//ÊäÈë: u8 cmd ÃüÁî
// u32 arg ÃüÁî²ÎÊý
// u8 crc crcУÑéÖµ
//·µ»ØÖµ:SD¿¨·µ»ØµÄÏìÓ¦
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
u8 r1;
u8 Retry=0;
SD_DisSelect();//È¡ÏûÉÏ´ÎƬѡ
if(SD_Select())return 0XFF;//ƬѡʧЧ
//·¢ËÍ
SD_SPI_ReadWriteByte(cmd | 0x40);//·Ö±ðдÈëÃüÁî
SD_SPI_ReadWriteByte(arg >> 24);
SD_SPI_ReadWriteByte(arg >> 16);
SD_SPI_ReadWriteByte(arg >> 8);
SD_SPI_ReadWriteByte(arg);
SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
//µÈ´ýÏìÓ¦£¬»ò³¬Ê±Í˳ö
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);
//·µ»Ø״ֵ̬
return r1;
}
//»ñÈ¡SD¿¨µÄCIDÐÅÏ¢£¬°üÀ¨ÖÆÔìÉÌÐÅÏ¢
//ÊäÈë: u8 *cid_data(´æ·ÅCIDµÄÄڴ棬ÖÁÉÙ16Byte£©
//·µ»ØÖµ:0£ºNO_ERR
// 1£º´íÎó
u8 SD_GetCID(u8 *cid_data)
{
u8 r1;
//·¢CMD10ÃüÁ¶ÁCID
r1=SD_SendCmd(CMD10,0,0x01);
if(r1==0x00)
{
r1=SD_RecvData(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 SD_GetCSD(u8 *csd_data)
{
u8 r1;
r1=SD_SendCmd(CMD9,0,0x01);//·¢CMD9ÃüÁ¶ÁCSD
if(r1==0)
{
r1=SD_RecvData(csd_data, 16);//½ÓÊÕ16¸ö×Ö½ÚµÄÊý¾Ý
}
SD_DisSelect();//È¡ÏûƬѡ
if(r1)return 1;
else return 0;
}
//»ñÈ¡SD¿¨µÄ×ÜÉÈÇøÊý£¨ÉÈÇøÊý£©
//·µ»ØÖµ:0£º È¡ÈÝÁ¿³ö´í
// ÆäËû:SD¿¨µÄÈÝÁ¿(ÉÈÇøÊý/512×Ö½Ú)
//ÿÉÈÇøµÄ×Ö½ÚÊý±ØΪ512£¬ÒòΪÈç¹û²»ÊÇ512£¬Ôò³õʼ»¯²»ÄÜͨ¹ý.
u32 SD_GetSectorCount(void)
{
u8 csd[16];
u32 Capacity;
u8 n;
u16 csize;
//È¡CSDÐÅÏ¢£¬Èç¹ûÆÚ¼ä³ö´í£¬·µ»Ø0
if(SD_GetCSD(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¿¨
u8 SD_Initialize(void)
{
u8 r1; // ´æ·ÅSD¿¨µÄ·µ»ØÖµ
u16 retry; // ÓÃÀ´½øÐг¬Ê±¼ÆÊý
u8 buf[4];
u16 i;
SD_SPI_Init(); //³õʼ»¯IO
SD_SPI_SpeedLow(); //ÉèÖõ½µÍËÙģʽ
for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//·¢ËÍ×îÉÙ74¸öÂö³å
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);//½øÈëIDLE״̬
}while((r1!=0X01) && retry--);
SD_Type=0;//ĬÈÏÎÞ¿¨
if(r1==0X01)
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
{
for(i=0;i<4;i++)buf
=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
if(buf[2]==0X01&&buf[3]==0XAA)//¿¨ÊÇ·ñÖ§³Ö2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X01); //·¢ËÍCMD55
r1=SD_SendCmd(CMD41,0x40000000,0X01);//·¢ËÍCMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//¼ø±ðSD2.0¿¨°æ±¾¿ªÊ¼
{
for(i=0;i<4;i++)buf=SD_SPI_ReadWriteByte(0XFF);//µÃµ½OCRÖµ
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //¼ì²éCCS
else SD_Type=SD_TYPE_V2;
}
}
}else//SD V1.x/ MMC V3
{
SD_SendCmd(CMD55,0,0X01); //·¢ËÍCMD55
r1=SD_SendCmd(CMD41,0,0X01); //·¢ËÍCMD41
if(r1<=1)
{
SD_Type=SD_TYPE_V1;
retry=0XFFFE;
do //µÈ´ýÍ˳öIDLEģʽ
{
SD_SendCmd(CMD55,0,0X01); //·¢ËÍCMD55
r1=SD_SendCmd(CMD41,0,0X01);//·¢ËÍCMD41
}while(r1&&retry--);
}else
{
SD_Type=SD_TYPE_MMC;//MMC V3
retry=0XFFFE;
do //µÈ´ýÍ˳öIDLEģʽ
{
r1=SD_SendCmd(CMD1,0,0X01);//·¢ËÍCMD1
}while(r1&&retry--);
}
if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//´íÎóµÄ¿¨
}
}
SD_DisSelect();//È¡ÏûƬѡ
SD_SPI_SpeedHigh();//¸ßËÙ
if(SD_Type)return 0;
else if(r1)return r1;
return 0xaa;//ÆäËû´íÎó
}
//¶ÁSD¿¨
//buf:Êý¾Ý»º´æÇø
//sector:ÉÈÇø
//cnt:ÉÈÇøÊý
//·µ»ØÖµ:0,ok;ÆäËû,ʧ°Ü.
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//ת»»Îª×Ö½ÚµØÖ·
if(cnt==1)
{
r1=SD_SendCmd(CMD17,sector,0X01);//¶ÁÃüÁî
if(r1==0)//Ö¸Áî·¢Ëͳɹ¦
{
r1=SD_RecvData(buf,512);//½ÓÊÕ512¸ö×Ö½Ú
}
}else
{
r1=SD_SendCmd(CMD18,sector,0X01);//Á¬Ðø¶ÁÃüÁî
do
{
r1=SD_RecvData(buf,512);//½ÓÊÕ512¸ö×Ö½Ú
buf+=512;
}while(--cnt && r1==0);
SD_SendCmd(CMD12,0,0X01); //·¢ËÍÍ£Ö¹ÃüÁî
}
SD_DisSelect();//È¡ÏûƬѡ
return r1;//
}
//дSD¿¨
//buf:Êý¾Ý»º´æÇø
//sector:ÆðʼÉÈÇø
//cnt:ÉÈÇøÊý
//·µ»ØÖµ:0,ok;ÆäËû,ʧ°Ü.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//ת»»Îª×Ö½ÚµØÖ·
if(cnt==1)
{
r1=SD_SendCmd(CMD24,sector,0X01);//¶ÁÃüÁî
if(r1==0)//Ö¸Áî·¢Ëͳɹ¦
{
r1=SD_SendBlock(buf,0xFE);//д512¸ö×Ö½Ú
}
}else
{
if(SD_Type!=SD_TYPE_MMC)
{
SD_SendCmd(CMD55,0,0X01);
SD_SendCmd(CMD23,cnt,0X01);//·¢ËÍÖ¸Áî
}
r1=SD_SendCmd(CMD25,sector,0X01);//Á¬Ðø¶ÁÃüÁî
if(r1==0)
{
do
{
r1=SD_SendBlock(buf,0xFC);//½ÓÊÕ512¸ö×Ö½Ú
buf+=512;
}while(--cnt && r1==0);
r1=SD_SendBlock(0,0xFD);//½ÓÊÕ512¸ö×Ö½Ú
}
}
SD_DisSelect();//È¡ÏûƬѡ
return r1;//
}
用这个程序能实现写文件到SD卡么,FATFS文件程序有,我就是不知道SD卡程序还要不要加其他程序,还是只要这个程序就可实现把数据保存到SD卡
一周热门 更多>