摘要:在單片機(jī)開(kāi)發(fā)板上或者是核心板上通常會(huì)看到除了MCU之外的的芯片—EEPROM和FLASH,一般是AT24CXX、W25QXX這兩顆芯片。但在利用單片機(jī)做一些項(xiàng)目的時(shí)候,比如做一個(gè)小車(chē),驅(qū)動(dòng)一些外設(shè)、顯示一些溫濕度信息等,卻發(fā)現(xiàn)一般沒(méi)有用到這些芯片。
在做一些顯示的時(shí)候卻會(huì)用到。他們與單片機(jī)之間的通信方式就是IIC和SPI通信,在單片機(jī)的開(kāi)發(fā)中用到的非常多。很多小伙伴就會(huì)說(shuō)了,用OLED來(lái)顯示一些數(shù)據(jù),IIC通信直接用別人的代碼,驅(qū)動(dòng)SD卡或者NRF24L01直接拿別人的SPI代碼就可以啊,難道我還自己去寫(xiě)驅(qū)動(dòng)嗎?當(dāng)然需要,學(xué)會(huì)了這些操作,層次就會(huì)提高很多,不信那就接著往下看!
EEPROM AT24C02存儲(chǔ)器學(xué)單片機(jī)的時(shí)候大家可能有一個(gè)問(wèn)題,為啥是IIC讀寫(xiě)EEPROM,而不是讀寫(xiě)其他的東西。為什么大部分的單片機(jī)開(kāi)發(fā)教程都教我利用IIC通信來(lái)讀寫(xiě)EEPROM這顆AT24C02芯片?4針0.96寸OLED也是IIC操作的,為啥他們不叫我如何利用IIC通信來(lái)操作OLED?原因很簡(jiǎn)單,主要是讀寫(xiě)EEPROM你學(xué)完了沒(méi)有成就感,會(huì)讀寫(xiě)EEPROM又怎么樣?歸根到底是沒(méi)有掌握IIC體會(huì)到IIC通信的重要性。
今年疫情很?chē)?yán)重,有一款紅外測(cè)溫芯片mlx90641就是通過(guò)IIC來(lái)讀取溫度的。我想如果教程是IIC讀寫(xiě)紅外測(cè)溫芯片,大家可能會(huì)比較感興趣。言歸正傳,來(lái)說(shuō)一說(shuō)EEPROM。ROM是“Read Only Memory”的縮寫(xiě),意為只能讀的存儲(chǔ)器。由于技術(shù)的發(fā)展,后來(lái)設(shè)計(jì)出了可以方便寫(xiě)入數(shù)據(jù)的 ROM,而這個(gè)“Read Only Memory”的名稱(chēng)被沿用下來(lái)了。EEPROM(Electrically Erasable Programmable ROM)是電可擦除存儲(chǔ)器。EEPROM 可以重復(fù)擦寫(xiě),EEPROM 是一種掉電后數(shù)據(jù)不丟失的存儲(chǔ)器,常用來(lái)存儲(chǔ)一些配置信息,以便系統(tǒng)重新上電的時(shí)候加載之。它的擦除和寫(xiě)入都是直接使用電路控制,不需要再使用外部設(shè)備來(lái)擦寫(xiě)。而且可以按字節(jié)為單位修改數(shù)據(jù),無(wú)需整個(gè)芯片擦除?,F(xiàn)在主要使用的ROM芯片都是EEPROM。24C02是一個(gè)2K Bit的串行EEPROM存儲(chǔ)器(掉電不丟失),內(nèi)部含有256個(gè)字節(jié),在24C02里面有一個(gè)8字節(jié)的頁(yè)寫(xiě)緩沖器。
操作任何的IIC設(shè)備一般都要知道從機(jī)地址,也就是利用單片機(jī)操作讀寫(xiě)的那個(gè)設(shè)備的地址。一般來(lái)說(shuō)對(duì)于IIC設(shè)備地址是7位,其中高 4 位固定為:1010 b,低 3 位則由 A0/A1/A2信號(hào)線的電平?jīng)Q定。所以一個(gè)IIC總線上可以掛載2^3=8個(gè)EEPROM芯片,當(dāng)然一般一個(gè)單片機(jī)只有一塊EEPROM芯片,所以我們直接把這個(gè)A2A1A0接地即可,當(dāng)然接VCC也沒(méi)有問(wèn)題,如果接GND那么地址就是1010000(0X50),如果接VCC那么地址就是1010111(0X57)。
因?yàn)?4C02是一個(gè)2K Bit的串行EEPROM存儲(chǔ)器(掉電不丟失),內(nèi)部含有256個(gè)字節(jié)。也就是說(shuō)有256個(gè)存儲(chǔ)單元,一個(gè)字節(jié)就是一個(gè)存儲(chǔ)單元,因?yàn)槊總€(gè)字節(jié)可以出存256個(gè)數(shù),也就是說(shuō)每個(gè)存儲(chǔ)單元可以存0~255個(gè)數(shù)。我們可以這樣理解,AT24C02是一棟教學(xué)樓,這個(gè)教學(xué)樓有256個(gè)房間(存儲(chǔ)單元),沒(méi)每個(gè)房間可以容納256個(gè)學(xué)生(每個(gè)存儲(chǔ)單元可以存儲(chǔ)0 ~ 255個(gè)數(shù))。
而且這個(gè)芯片在斷電的時(shí)候數(shù)據(jù)不會(huì)丟失,利用掉電不會(huì)丟失以及這款芯片容量不大的特性,可以大致判斷它會(huì)在哪些地方可以用到。比如我們看電視得時(shí)候,正在看CCTV6電影頻道,播放的聲音比較大,那么這時(shí)候正好停電了。那么你下次來(lái)電時(shí)你打開(kāi)電視機(jī),電視機(jī)默認(rèn)肯定是CCTV6電影頻道,播放的聲音也是很大。那么這些“頻道”、“音量”這些數(shù)據(jù)就存在EEPROM里面,至于是不是ATC02就不一定了。
總結(jié):
存儲(chǔ)量少,用起來(lái)方便
可以任意訪問(wèn)地址數(shù)據(jù),每一個(gè)存儲(chǔ)單片可以獨(dú)立訪問(wèn),
寫(xiě)入前是不需要對(duì)寫(xiě)入的單片做獨(dú)立的擦除
這三個(gè)特點(diǎn)對(duì)我們理解存儲(chǔ)器的特性非常重要,因?yàn)榻酉聛?lái)要說(shuō)的FLASH芯片的特性就與它完全相反。
FLASH W25Q128存儲(chǔ)器
FLSAH字面意思就是閃現(xiàn)、一瞬間的意思,所以FLSAH存儲(chǔ)器又稱(chēng)閃存,與 EEPROM都是掉電后數(shù)據(jù)不丟失的存儲(chǔ)器,但FLASH存儲(chǔ)器容量普遍大于 EPROM,現(xiàn)在基本取代了它的地位。生活中常用的 U 盤(pán)、SD卡、SSD 固態(tài)硬盤(pán)以及我們 STM32 芯片內(nèi)部用于存儲(chǔ)程序的設(shè)備,都是 FLASH 類(lèi)型的存儲(chǔ)器。在存儲(chǔ)控制上,最主要的區(qū)別是 FLASH 芯片只能一大片一大片地擦寫(xiě),而 EEPROM可以單個(gè)字節(jié)擦寫(xiě)。
FLASH 芯片的最小擦除單位為扇區(qū)(Sector),而一個(gè)塊(Block)包含 16 個(gè)扇區(qū),4Kbytes為一個(gè)Sector,16個(gè)扇區(qū)為1個(gè)Block。W25Q64 容量為8M字節(jié)(即 64M bit), 分為128塊(Block),每一塊的大小為64K字節(jié),每塊又分為16個(gè)扇區(qū)(Sector),那么每個(gè)扇區(qū)就是4K個(gè)字節(jié)。W25Q128 容量為16M字節(jié)(即 128M bit),分為256塊(Block),每一塊的大小為64K字節(jié),每塊又分為16個(gè)扇區(qū)(Sector),那么每個(gè)扇區(qū)就是4K個(gè)字節(jié)(4096個(gè)字節(jié),也就是4096個(gè)存儲(chǔ)單元)。
W25Qxx的最小擦除單位為一個(gè)扇區(qū),也就是每一次必須擦除4K字節(jié)。所以必須給W25Qxx開(kāi)辟至少4K的緩沖區(qū),這樣對(duì)單片機(jī)的RAM的要求比較高,要求芯片必須有4K以上的RAM才能很好的操作。所有的FLASH我們?cè)趯?xiě)之前都要擦出對(duì)應(yīng)的扇區(qū),擦除后的數(shù)據(jù)是0XFF。我們可以這樣理解。我們要改寫(xiě)FLASH芯片W25Q128的一個(gè)扇區(qū)中某一個(gè)數(shù)據(jù),就必須在STM32芯片的內(nèi)部RAM中開(kāi)辟4K字節(jié)(4096字節(jié))的緩沖區(qū)域。先把FLASH芯片W25Q128的一個(gè)扇區(qū)中數(shù)據(jù)全部讀到STM32芯片的內(nèi)部RAM中開(kāi)辟4K字節(jié)(4096字節(jié))的緩沖區(qū)域中去,把我們要改寫(xiě)的數(shù)據(jù)在緩沖區(qū)域改寫(xiě)好之后,再把FLASH芯片W25Q128的一個(gè)扇區(qū)中的數(shù)據(jù)全部擦除完畢,擦除完成之后再把數(shù)據(jù)寫(xiě)回去。這是寫(xiě)入數(shù)據(jù)的操作,在讀數(shù)據(jù)的時(shí)候不需要以扇區(qū)為單位,想讀哪個(gè)扇區(qū)就讀哪個(gè)扇區(qū)的數(shù)據(jù)。
/************************************************************************* * Function Name : SPI_Flash_Write * Description : 在指定地址開(kāi)始寫(xiě)入指定長(zhǎng)度的數(shù)據(jù),該函數(shù)帶擦除操作! * Input : *pBuffer:要寫(xiě)入數(shù)據(jù)的指針 WriteAddr:開(kāi)始寫(xiě)入的地址(24bit) NumByteToWrite:要寫(xiě)入的字節(jié)數(shù)(最大16 x 1024 x 1024) * Output : None * Return : None
****************************************************************************/ void SPI_Flash_Write(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) { u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0; Addr = WriteAddr % 4096;//mod運(yùn)算求余,若writeAddr是4096整數(shù)倍,運(yùn)算結(jié)果Addr值為0 NumOfPage = NumByteToWrite / 4096;//計(jì)算出要寫(xiě)多少整數(shù)扇區(qū) NumOfSingle = NumByteToWrite % 4096;//mod
運(yùn)算求余,計(jì)算出剩余不滿一扇區(qū)的字節(jié)數(shù) count = 4096 - Addr;//差count個(gè)數(shù)據(jù)值,剛好可以對(duì)齊到扇區(qū)地址 if (Addr == 0)//Addr=0,則WriteAddr剛好按扇區(qū)對(duì)齊或者說(shuō)小于一個(gè)扇區(qū) { //NumByteToWrite 《 4096,寫(xiě)入的字符串大小長(zhǎng)度小于一個(gè)扇區(qū)(4096個(gè)字節(jié))的大小,如22 if (NumOfPage == 0) { SPI_Flash_Write_Page(pBuffer, WriteAddr, NumByteToWrite); } else //NumByteToWrite 》 4096,寫(xiě)入的字符串大小長(zhǎng)度大與一個(gè)扇區(qū)(4096個(gè)字節(jié))的大小,如4098 { //先把整數(shù)扇區(qū)都寫(xiě)了 while (NumOfPage--) { SPI_Flash_Write_Page(pBuffer, WriteAddr, 4096); WriteAddr += 4096; pBuffer += 4096; } //若有多余的不滿一扇區(qū)的數(shù)據(jù),把它寫(xiě)完
SPI_Flash_Write_Page(pBuffer, WriteAddr, NumOfSingle); } } //若地址與 4096 不對(duì)齊 else //Addr不等于0,則要寫(xiě)入的WriteAddr地址與4096不對(duì)齊 { //NumByteToWrite 《 4096 if (NumOfPage == 0)//大小不夠一個(gè)扇區(qū),如22 { //當(dāng)前頁(yè)剩余的count個(gè)位置比NumOfSingle小,一扇區(qū)寫(xiě)不完 if (NumOfSingle 》 count) { temp = NumOfSingle - count; //先寫(xiě)滿當(dāng)前扇區(qū) SPI_Flash_Write_Page(pBuffer, WriteAddr, count); WriteAddr += count; pBuffer += count; //再寫(xiě)剩余的數(shù)據(jù) SPI_Flash_Write_Page(pBuffer, WriteAddr, temp); } else //當(dāng)前扇區(qū)剩余的count個(gè)位置能寫(xiě)完
NumOfSingle個(gè)數(shù)據(jù) { SPI_Flash_Write_Page(pBuffer, WriteAddr, NumByteToWrite); } } else //NumByteToWrite 》 4096 //大小夠一個(gè)扇區(qū),而且還超出一點(diǎn)點(diǎn),如4098 { //地址不對(duì)齊多出的count分開(kāi)處理,不加入這個(gè)運(yùn)算 NumByteToWrite -= count; NumOfPage = NumByteToWrite / 4096; NumOfSingle = NumByteToWrite % 4096; //先寫(xiě)完count個(gè)數(shù)據(jù),為的是讓下一次要寫(xiě)的地址對(duì)齊 SPI_Flash_Write_Page(pBuffer, WriteAddr, count); //接下來(lái)就重復(fù)地址對(duì)齊的情況
*/ WriteAddr += count; pBuffer += count; //把整數(shù)扇區(qū)都寫(xiě)了*/ while (NumOfPage--) { SPI_Flash_Write_Page(pBuffer, WriteAddr, 4096); WriteAddr += 1096; pBuffer += 4096; } //若有多余的不滿一扇區(qū)的數(shù)據(jù),把它寫(xiě)完 if (NumOfSingle != 0) { SPI_Flash_Write_Page(pBuffer, WriteAddr, NumOfSingle); } } } }
總結(jié):
/********************************************************************** * Function Name : SPI_Flash_Read * Description : 在指定地址開(kāi)始讀取指定長(zhǎng)度的數(shù)據(jù) * Input : *pBuffer:存儲(chǔ)讀出數(shù)據(jù)的指針 ReadAddr:開(kāi)始讀取的地址(24bit) NumByteToRead:要讀取的字節(jié)數(shù)(最大 16 x 1024 x 1024) * Output : None * Return : None ************************************************************************/ void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; SPI_FLASH_CS=0; //使能器件
SPI1_ReadWriteByte(CMD_W25X_ReadData); //發(fā)送讀取命令 SPI1_ReadWriteByte((ReadAddr& 0xFF0000)》》16); //發(fā)送扇區(qū)地址的高8bit SPI1_ReadWriteByte((ReadAddr& 0xFF00)》》8); //發(fā)送扇區(qū)地址的中間8bit SPI1_ReadWriteByte( ReadAddr& 0xFF); //發(fā)送扇區(qū)地址的低8bit for(i=0;i《NumByteToRead;i++) { pBuffer[i]=SPI1_ReadWriteByte(0XFF); //循環(huán)讀數(shù) } SPI_FLASH_CS=1; //取消片選 } 總結(jié):
存儲(chǔ)量大
不能任意訪問(wèn)字節(jié)地址數(shù)據(jù),每一個(gè)存儲(chǔ)單片不可以獨(dú)立訪問(wèn),最小讀取單元是一個(gè)扇區(qū)
寫(xiě)入前是必須對(duì)寫(xiě)入的扇區(qū)做獨(dú)立的擦除操作。擦除的目的是使存儲(chǔ)單元的數(shù)據(jù)全為1
SD卡大容量存儲(chǔ)器SD 卡(Secure Digital Memory Card)在我們生活中已經(jīng)非常普遍了,控制器對(duì) SD卡進(jìn)行讀寫(xiě)通信操作一般有兩種通信接口可選,一種是 SPI接口,另外一種是 SDIO 接口。SDIO全稱(chēng)是安全數(shù)字輸入/輸出接口,多媒體卡(MMC)、SD卡、SD I/O 卡(專(zhuān)指使用SDIO 接口的一些輸入輸出設(shè)備)都可使用 SDIO 接口通訊。STM32F10x 系列控制器有一個(gè) SDIO 主機(jī)接口,它支持與上述使用 SDIO 接口的設(shè)備進(jìn)行數(shù)據(jù)傳輸。
STM32F10x 系列控制器只支持 SD 卡規(guī)范版本 2.0,即只支持標(biāo)準(zhǔn)容量SD和高容量 SDHC 標(biāo)準(zhǔn)卡,不支持超大容量 SDXC 標(biāo)準(zhǔn)卡,所以可以支持的最高卡容量是 32GB。SD 卡一般都支持 SDIO 和 SPI 這兩種接口。另外,STM32F42x 系列控制器的 SDIO 是不支持 SPI通信模式的,如果需要用到 SPI通信只能使用 SPI外設(shè)。因?yàn)镾PI通信方式操作SD卡的數(shù)據(jù)線只有一根,而如果用SDIO的通信方式操作SD卡的數(shù)據(jù)線卻又3根。為了節(jié)省資源一般在STM32F10x 系列控制器上用SPI的通信方式,而在引腳資源比較多的F4系列上就用SDIO的通信方式了。
SD容量有8MB、16MB、32MB、64MB、128MB、256MB、512MB、1GB、2GB (磁盤(pán)格式FAT12、FAT16)
SDHC容量有2GB、4GB、8GB、16GB、32GB(磁盤(pán)格式FAT32)
SDXC容量有32GB、48GB、64GB、128GB、256GB(磁盤(pán)格式exFAT)
3.1初始化1、初始化與SD卡連接的硬件條件(MCU的SPI配置,IO口配置);
2、上電延時(shí)(》74 個(gè) CLK);
3、復(fù)位卡(CMD0),進(jìn)入IDLE狀態(tài);
4、發(fā)送CMD8,檢查是否支持2.0協(xié)議;
5、根據(jù)不同協(xié)議檢查SD卡(命令包括:CMD55、CMD41、CMD58 和 CMD1 等);
6、取消片選,發(fā)多 8個(gè)CLK,結(jié)束初始化
/******************************************************************************* * Function Name : SD_Init * Description : 初始化SD卡 * Input : None * Output : None * Return : u8 * 0:NO_ERR * 1:TIME_OUT * 99:NO_CARD *******************************************************************************/ u8 SD_Init(void) { u8 r1; // 存放SD卡的返回值 u16 retry; // 用來(lái)進(jìn)行超時(shí)計(jì)數(shù) u8 buf[4]; u16 i; SD_SPI_Init(); //初始化IO SD_SPI_SpeedLow(); //設(shè)置到低速模式 //先產(chǎn)生至少74個(gè)脈沖,讓SD卡自己初始化完成 for(i=0;i《10;i++) { SD_SPI_WriteByte(0XFF);
////80clks } //-----------------SD卡復(fù)位到idle開(kāi)始----------------- //循環(huán)連續(xù)發(fā)送CMD0,直到SD卡返回0x01,進(jìn)入IDLE狀態(tài) //超時(shí)則直接退出 retry=0; do { r1=SD_SendCmd(CMD0,0,0x95);//進(jìn)入IDLE狀態(tài),作用是讓SD卡進(jìn)入SPI模式。這里的CRC校驗(yàn)位0x95是固定的,不能修改 retry++; }while((r1!=0X01) && (retry《20));//如果 SD 卡有正確的回應(yīng),代碼就繼續(xù)執(zhí)行,如果沒(méi)有回應(yīng)程序就終止執(zhí)行。 //跳出循環(huán)后,檢查原因:初始化成功?or 重試超時(shí)? if(retry==20) return 1; //超時(shí)返回1 SD_Type=0;
//默認(rèn)無(wú)卡 //下面是V2.0卡的初始化 //其中需要讀取OCR數(shù)據(jù),判斷是SD2.0還是SD2.0HC卡 if(r1==0X01) { if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0 { //V2.0的卡,CMD8命令后會(huì)傳回4字節(jié)的數(shù)據(jù),要跳過(guò)再結(jié)束本命令 buf[0]=SD_SPI_ReadByte(); //should be 0x00 buf[1]=SD_SPI_ReadByte(); //should be 0x00 buf[2]=SD_SPI_ReadByte(); //should be 0x01 buf[3]=SD_SPI_ReadByte(); //should be 0xAA if(buf[2]==0X01&&buf[3]==0XAA)//判斷卡是否支持2.7~3.6V的電壓范圍 { retry=0XFFFE; //發(fā)卡初始化指令CMD55+CMD41 do { SD_SendCmd(CMD55,0,0X01); //發(fā)送CMD55 r1=SD_SendCmd(CMD41,0x40000000,0X01);//發(fā)送CMD41 }while(r1&&retry--); //初始化指令發(fā)送完成,接下來(lái)獲取OCR信息
//-----------鑒別SD2.0卡版本開(kāi)始----------- if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鑒別SD2.0卡版本開(kāi)始 { //讀OCR指令發(fā)出后,緊接著是4字節(jié)的OCR信息 buf[0]=SD_SPI_ReadByte(); buf[1]=SD_SPI_ReadByte(); buf[2]=SD_SPI_ReadByte(); buf[3]=SD_SPI_ReadByte(); //檢查接收到的OCR中的bit30位(CCS),確定其為SD2.0還是SDHC //如果CCS=1:為SDV2.0HC的2.0高容量卡 CCS=0:為SDV2.0的2.0版本的標(biāo)準(zhǔn)卡 if(buf[0]&0x40) SD_Type=SD_TYPE_V2HC; //檢查CCS else SD_Type=SD_TYPE_V2; LCD_ShowNum(164,250,SD_Type,5,16);//顯示SD卡容量 //-----------鑒別SD2.0卡版本結(jié)束----------- } } } //如果卡片版本信息是v1.0版本的,即r1=0x05,則進(jìn)行以下初始化
else//SD V1.0/ MMC V3 { //先發(fā)CMD55,應(yīng)返回0x01;否則出錯(cuò) r1 = SD_SendCmd(CMD55,0,0X01); //發(fā)送CMD55 if(r1 != 0x01) return r1; //得到正確響應(yīng)后,發(fā)ACMD41,應(yīng)得到返回值0x00 r1=SD_SendCmd(CMD41,0,0X01); //發(fā)送CMD41 if(r1《=1) { SD_Type=SD_TYPE_V1; retry=0XFFFE; do //等待退出IDLE模式 { SD_SendCmd(CMD55,0,0X01); //發(fā)送CMD55 r1=SD_SendCmd(CMD41,0,0X01);//發(fā)送CMD41 }while(r1&&retry--); }else//MMC卡不支持CMD55+CMD41識(shí)別 { SD_Type=SD_TYPE_MMC;//MMC V3 retry=0XFFFE; do //等待退出IDLE模式 { r1=SD_SendCmd(CMD1,0,0X01);//發(fā)送CMD1,發(fā)送MMC卡初始化命令
}while(r1&&retry--); } if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0) SD_Type=SD_TYPE_ERR;//錯(cuò)誤的卡 } } SD_DisSelect();//取消片選 SD_SPI_SpeedHigh();//高速 if(SD_Type) return 0; else if(r1) return r1; return 0xaa;//其他錯(cuò)誤 }
3.2寫(xiě)數(shù)據(jù)通過(guò) CMD24實(shí)現(xiàn)1、發(fā)送CMD24;
2、接收卡響應(yīng)R1;
3、發(fā)送寫(xiě)數(shù)據(jù)起始令牌 0XFE;
4、發(fā)送數(shù)據(jù);
5、發(fā)送2字節(jié)的偽CRC;
6、禁止片選之后,發(fā)多8個(gè)CLK;
/******************************************************************************* * Function Name : SD_WriteDisk * Description : 向SD卡寫(xiě)數(shù)據(jù) * Input : buf:數(shù)據(jù)緩存區(qū) * sector:扇區(qū) * cnt:扇區(qū)數(shù) * Output : None * Return : u8 * 0:ok * 其他,失敗。 *******************************************************************************/ u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt) { u8 r1; if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//轉(zhuǎn)換為字節(jié)地址 if(cnt==1) { r1=SD_SendCmd(CMD24,sector,0X01);//讀命令 if(r1==0)//指令發(fā)送成功 { r1=SD_SendBlock(buf,0xFE);//寫(xiě)512個(gè)字節(jié) } }else { if(SD_Type!=SD_TYPE_MMC) { SD_SendCmd(CMD55,0,0X01); SD_SendCmd(CMD23,cnt,0X01);//發(fā)送指令 } r1=SD_SendCmd(CMD25,sector,0X01);//連續(xù)讀命令 if(r1==0) { do { r1=SD_SendBlock(buf,0xFC);//接收512個(gè)字節(jié) buf+=512; }while(--cnt && r1==0); r1=SD_SendBlock(0,0xFD);//接收512個(gè)字節(jié) } } SD_DisSelect();//取消片選,釋放SPI總線 return r1; }
3.3讀取數(shù)據(jù)通過(guò) CMD17實(shí)現(xiàn)1、發(fā)送CMD17;
2、接收卡響應(yīng)R1;
3、接收數(shù)據(jù)起始令牌 0XFE;
4、接收數(shù)據(jù);
5、接收2個(gè)字節(jié)的 CRC,如果不使用CRC,這兩個(gè)字節(jié)在讀取后可以丟掉。
6、禁止片選之后,發(fā)多8個(gè)CLK;
/*******************************************************************************
* Function Name : SD_ReadDisk
* Description : 讀SD卡數(shù)據(jù)
* Input : buf:數(shù)據(jù)緩存區(qū)
* sector:扇區(qū)
* cnt:扇區(qū)數(shù)
* Output : None
* Return : u8
* 0:ok
* 其他,失敗。
*******************************************************************************/
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector 《《= 9;//轉(zhuǎn)換為字節(jié)地址
if(cnt==1)
{
r1=SD_SendCmd(CMD17,sector,0X01);//讀命令
if(r1==0)//指令發(fā)送成功
{
r1=SD_RecvData(buf,512);//接收512個(gè)字節(jié)
}
}else
{
r1=SD_SendCmd(CMD18,sector,0X01);//連續(xù)讀命令
do
{
r1=SD_RecvData(buf,512);//接收512個(gè)字節(jié)
buf+=512;
}while(--cnt && r1==0);
SD_SendCmd(CMD12,0,0X01); //發(fā)送停止命令
}
SD_DisSelect();//取消片選
return r1;
}
原文標(biāo)題:你必須知道的單片機(jī)存儲(chǔ)器的那些事!
文章出處:【微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
責(zé)任編輯:haq
-
芯片
+關(guān)注
關(guān)注
460文章
52520瀏覽量
440933 -
單片機(jī)
+關(guān)注
關(guān)注
6067文章
44992瀏覽量
650494 -
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7653瀏覽量
167407
原文標(biāo)題:你必須知道的單片機(jī)存儲(chǔ)器的那些事!
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
單片機(jī)實(shí)例項(xiàng)目:AT24C02EEPROM存儲(chǔ)器
MCU存儲(chǔ)器層次結(jié)構(gòu)解析
扒一扒單片機(jī)與存儲(chǔ)器的那些事

評(píng)論