主機(jī)環(huán)境:Windows 7 SP1
開(kāi)發(fā)環(huán)境:MDK5.14
目標(biāo)板:ST NUCLEO-F303RE
TFT型號(hào):2.4英寸,帶觸摸,SD卡,240*320分辨率,26萬(wàn)色
驅(qū)動(dòng)IC:ILI9325
ST庫(kù)版本:STM32Cube_FW_F3_V1.1.0
SD卡:Kingston 16GB Micro SDHC Class 10
本TFT模塊是帶有SD卡插槽的,之前連線一直沒(méi)接,現(xiàn)在可以使用了,對(duì)于該TFT模塊來(lái)說(shuō)一副圖片需要的空間為150K(240*320*2),如果圖片都存入FALSH空間肯定是存放不了多少圖片資源的,因此我們可以把圖片資源存入SD卡中等到需要時(shí)再?gòu)腟D卡讀取來(lái)顯示,這樣只要SD卡空間夠大我們就可以顯示很多圖片資源了,因此來(lái)研究看SD卡的讀寫(xiě)吧,這里是沒(méi)有為SD卡做文件系統(tǒng)的,那個(gè)是以后的事情了。
對(duì)于SD卡的操作跟LCD類似,EVAL的固件庫(kù)里面同樣有寫(xiě)好了的SD庫(kù)函數(shù)stm32303e_eval_sd.c/h,如下
基于SD卡資料文檔配合庫(kù)函數(shù)就可以完成我們SD卡的操作了,由于NUCLEO-F303RE的SPI1接口中的MOSI腳被用于LED2的操作,因此這里使用IO口模擬SPI通信來(lái)對(duì)SD卡進(jìn)行操作,接口聲明如下
#define SPI_SDCARD_SCK_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_SDCARD_MISO_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_SDCARD_MOSI_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_SDCARD_SCK_PIN GPIO_PIN_6
#define SPI_SDCARD_SCK_GPIO_PORT GPIOC
#define SPI_SDCARD_MISO_PIN GPIO_PIN_8
#define SPI_SDCARD_MISO_GPIO_PORT GPIOC
#define SPI_SDCARD_MOSI_PIN GPIO_PIN_5
#define SPI_SDCARD_MOSI_GPIO_PORT GPIOC
#define SPI_SDCARD_nCS_PIN GPIO_PIN_9
#define SPI_SDCARD_nCS_GPIO_PORT GPIOC
#define SPI_SDCARD_nCS_Set_Low() (GPIOC->BRR = GPIO_PIN_9)
#define SPI_SDCARD_nCS_Set_High() (GPIOC->BSRRL = GPIO_PIN_9)
#define SPI_SDCARD_SCK_Set_Low() {__NOP();__NOP(); \
__NOP();__NOP(); \
GPIOC->BRR = GPIO_PIN_6; \
__NOP();__NOP(); \
__NOP();__NOP();}
#define SPI_SDCARD_SCK_Set_High() {__NOP();__NOP(); \
__NOP();__NOP(); \
GPIOC->BSRRL = GPIO_PIN_6; \
__NOP();__NOP();}
#define SPI_SDCARD_MOSI_Set_Low() (GPIOC->BRR = GPIO_PIN_5)
#define SPI_SDCARD_MOSI_Set_High() (GPIOC->BSRRL = GPIO_PIN_5)
#define SPI_SDCARD_MISO_Read() (GPIOC->IDR & GPIO_PIN_8)
SD卡是有9個(gè)引腳的,分配如下
當(dāng)使用SPI模式時(shí)我們只用到了4個(gè)引腳,CLK、CS、DataIn、DataOut
SD里面是有一個(gè)接口控制器的,如下圖
接口里面有7個(gè)寄存器CID、RCA、SCD、SCR、OCR、CSR(Card Status)、SSR(SD Status)。
但是這些寄存器在不同的模式下有些許不同,大體上是一致的,SPI模式下RCA寄存器是不支持的。上面5個(gè)寄存器的內(nèi)容有很多,也很重要,文檔提了一大坨,用到時(shí)再來(lái)看吧。
SD卡系統(tǒng)特性如下
時(shí)鐘限制在0~25MHz,電壓限制在2.0~3.6V,一般是使用3.3V供電電壓。在使用SPI通信時(shí)數(shù)據(jù)在CLK的上升沿鎖存,CLK空閑狀態(tài)是低電平,MOSI在空閑狀態(tài)下為1
SDCard的通訊協(xié)議分三塊Command、Response、Data-block,形式如下:
發(fā)送一個(gè)命令后SD卡的控制器回返回一個(gè)response,之后傳輸數(shù)據(jù)且?guī)в?a href="http://m.weightgang.cn/zhuanti/LS4GuD" style="color:#4595e6;" target="_blank">CRC校驗(yàn)碼。但是SPI模式下CRC校驗(yàn)?zāi)J(rèn)是禁止的。
SD卡上電初始化時(shí)序
上電時(shí)需要74個(gè)時(shí)鐘周期來(lái)穩(wěn)定。SD卡在上電后默認(rèn)是SD模式,要想使用SPI模式需要發(fā)送命令給SD卡的控制器來(lái)進(jìn)行模式切換
即上電之后需要發(fā)送CMD0命令來(lái)實(shí)現(xiàn)模式的切換,文中提到雖然SPI模式下CRC校驗(yàn)是禁止的,但是CMD0命令的發(fā)送還是要帶上正確的7位CRC校驗(yàn)值0x4A,畢竟此時(shí)還不是SPI模式,發(fā)送CMD0命令完畢后,SD卡會(huì)進(jìn)入SPI模式同時(shí)會(huì)返回一個(gè)R1 response(0x01)。SD卡是支持單block的讀寫(xiě)和多blocks讀寫(xiě)。之前已經(jīng)看到了單block的讀操作,現(xiàn)在看以下多block的讀操作:
多block讀和單block讀基本相似,唯一不同的是多block讀在最后需要發(fā)送一個(gè)Stop命令(CMD12),再來(lái)看以下寫(xiě)操作
寫(xiě)操作與讀操作類似,但是讀操作的頻率是大于寫(xiě)操作的頻率,因?yàn)閿?shù)據(jù)一般都在SD卡中寫(xiě)好了的。寫(xiě)操作需要注意的是數(shù)據(jù)寫(xiě)完之后MCU需要去發(fā)送SEND_STATUS命令CMD13來(lái)檢測(cè)數(shù)據(jù)寫(xiě)入是否正確。此外還有讀取CID/CSD寄存器命令,SPI模式下與SD模式下讀取寄存器是不一樣的。
在SPI模式下讀取寄存器跟讀取block數(shù)據(jù)是一致的。
SPI通信還需要注意以下幾點(diǎn):
即所有操作完畢后,MCU仍需要提供8個(gè)clock給SD控制器以便其在MCU停止時(shí)鐘之前完成其操作。以上是SD卡在SPI模式下的操作流程,下面就說(shuō)說(shuō)其命令格式
命令共有6個(gè)字節(jié),且以MSB形式傳輸,第一個(gè)字節(jié)為Command后面會(huì)提到命令列表,bit[7:6]=01b固定,即Command只占用了6個(gè)字節(jié),即最多有64個(gè)命令;中間4個(gè)字節(jié)為命令參數(shù)(Command Argument)命令不需要參數(shù)時(shí)該值為0,最后一個(gè)字節(jié)為CRC值,bit[0]=1b固定,不使用CRC時(shí)寫(xiě)1即可,前面提到使SD卡進(jìn)入SPI模式是發(fā)送CMD1其CRC值為0x4A(1001010b),再加上bit[0]=1即為10010101b,CMD1不需要參數(shù),因此具體發(fā)送的數(shù)據(jù)為0x40 0x00 0x00 0x00 0x00 0x95。文檔中亦給出了CRC的計(jì)算方式
由于SPI模式下CRC默認(rèn)禁止了就沒(méi)去仔細(xì)研究這個(gè),以后用到了再細(xì)看吧。SD卡的命令分為了10類:class0-class9
命令列表如下
由于命令列表比較長(zhǎng),意思一下就行了。用到的時(shí)候再查文檔就可以了。
來(lái)看以下SPI的回碼R1
R1是用于響應(yīng)Command(除了SEND_STATUS之外),最高位固定為0,response還有R1b、R2、R3,此外還有data response如下
data token如下
還有data err token等,這里就不細(xì)說(shuō)了,不然太冗長(zhǎng)了。。。,開(kāi)始對(duì)比EVAL的庫(kù)函數(shù)以及文檔來(lái)編輯我們的SD卡操作,首先是SPI的驅(qū)動(dòng)函數(shù)
由于是模擬spi因此只需要初始化io口就夠了
/**********************************************************************
函數(shù):HAL_SPI_SDCARD_MspInit()
函數(shù)作用:sd卡spi資源初始化
參數(shù):無(wú)
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-02
說(shuō)明: SD卡通訊接口為模擬SPI
**********************************************************************/
void HAL_SPI_SDCARD_MspInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_SDCARD_SCK_GPIO_CLK_ENABLE();
SPI_SDCARD_MISO_GPIO_CLK_ENABLE();
SPI_SDCARD_MOSI_GPIO_CLK_ENABLE();
SPI_SDCARD_nCS_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = SPI_SDCARD_SCK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(SPI_SDCARD_SCK_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI_SDCARD_MOSI_PIN;
HAL_GPIO_Init(SPI_SDCARD_MOSI_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI_SDCARD_nCS_PIN;
HAL_GPIO_Init(SPI_SDCARD_nCS_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI_SDCARD_MISO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(SPI_SDCARD_MISO_GPIO_PORT, &GPIO_InitStruct);
}
其讀、寫(xiě)、初始化操作如下
/**********************************************************************
函數(shù):SPI_SDCARD_Init()
函數(shù)作用:sd卡spi初始化
參數(shù):無(wú)
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-02
說(shuō)明: SD卡通訊接口為模擬SPI
**********************************************************************/
void SPI_SDCARD_Init(void)
{
HAL_SPI_SDCARD_MspInit();
SPI_SDCARD_nCS_Set_High();
SPI_SDCARD_SCK_Set_Low();
SPI_SDCARD_MOSI_Set_High();
}
/**********************************************************************
函數(shù):SPI_SDCARD_Write()
函數(shù)作用:SPI SDCARD發(fā)送一個(gè)字節(jié)數(shù)據(jù)
參數(shù):
uint8_t value----------------------------待發(fā)送的字節(jié)數(shù)據(jù)
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-07-31
說(shuō)明: 上升沿鎖存數(shù)據(jù),MSB
**********************************************************************/
void SPI_SDCARD_Write(uint8_t value)
{
uint8_t i = 0;
for(i = 0; i < 8; i++)
{
SPI_SDCARD_SCK_Set_Low();
if(value&0x80)
{
SPI_SDCARD_MOSI_Set_High();
}
else
{
SPI_SDCARD_MOSI_Set_Low();
}
value<<=1;
SPI_SDCARD_SCK_Set_High();//鎖存數(shù)據(jù)
}
SPI_SDCARD_MOSI_Set_High();//釋放數(shù)據(jù)總線
}
/**********************************************************************
函數(shù):SPI_SDCARD_Read()
函數(shù)作用:SPI SDCARD接收一個(gè)字節(jié)數(shù)據(jù)
參數(shù):無(wú)
返回值:讀取的字節(jié)內(nèi)容
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-02
說(shuō)明: 上升沿鎖存數(shù)據(jù),MSB
**********************************************************************/
uint8_t SPI_SDCARD_Read(void)
{
uint8_t i = 0,value = 0;
for(i = 0; i < 8; i++)
{
SPI_SDCARD_SCK_Set_Low();
SPI_SDCARD_SCK_Set_High();//鎖存數(shù)據(jù)
value<<=1;
if(SPI_SDCARD_MISO_Read())
{
value|=0x01;
}
}
return value;
}
spi驅(qū)動(dòng)搞完后就是我們的SDCARD操作了,首先是初始化
這里有個(gè)提示當(dāng)SD卡處于IDLE模式時(shí)只有CMD1、ACMD41、CDM59、CDM58命令是有效的,MCU需持續(xù)的發(fā)送CMD1命令,直到SD卡退出IDLE模式
拷貝EVAL庫(kù)函數(shù)中的命令列表以及response碼如下
#define SDCARD_DUMMY_BYTE 0xFF
/**
* @brief Commands: CMDxx = CMD-number | 0x40
*/
#define SDCARD_CMD_GO_IDLE_STATE 0 /* CMD0 = 0x40 */
#define SDCARD_CMD_SEND_OP_COND 1 /* CMD1 = 0x41 */
#define SDCARD_CMD_SEND_CSD 9 /* CMD9 = 0x49 */
#define SDCARD_CMD_SEND_CID 10 /* CMD10 = 0x4A */
#define SDCARD_CMD_STOP_TRANSMISSION 12 /* CMD12 = 0x4C */
#define SDCARD_CMD_SEND_STATUS 13 /* CMD13 = 0x4D */
#define SDCARD_CMD_SET_BLOCKLEN 16 /* CMD16 = 0x50 */
#define SDCARD_CMD_READ_SINGLE_BLOCK 17 /* CMD17 = 0x51 */
#define SDCARD_CMD_READ_MULT_BLOCK 18 /* CMD18 = 0x52 */
#define SDCARD_CMD_SET_BLOCK_COUNT 23 /* CMD23 = 0x57 */
#define SDCARD_CMD_WRITE_SINGLE_BLOCK 24 /* CMD24 = 0x58 */
#define SDCARD_CMD_WRITE_MULT_BLOCK 25 /* CMD25 = 0x59 */
#define SDCARD_CMD_PROG_CSD 27 /* CMD27 = 0x5B */
#define SDCARD_CMD_SET_WRITE_PROT 28 /* CMD28 = 0x5C */
#define SDCARD_CMD_CLR_WRITE_PROT 29 /* CMD29 = 0x5D */
#define SDCARD_CMD_SEND_WRITE_PROT 30 /* CMD30 = 0x5E */
#define SDCARD_CMD_SDCARD_ERASE_GRP_START 32 /* CMD32 = 0x60 */
#define SDCARD_CMD_SDCARD_ERASE_GRP_END 33 /* CMD33 = 0x61 */
#define SDCARD_CMD_UNTAG_SECTOR 34 /* CMD34 = 0x62 */
#define SDCARD_CMD_ERASE_GRP_START 35 /* CMD35 = 0x63 */
#define SDCARD_CMD_ERASE_GRP_END 36 /* CMD36 = 0x64 */
#define SDCARD_CMD_UNTAG_ERASE_GROUP 37 /* CMD37 = 0x65 */
#define SDCARD_CMD_ERASE 38 /* CMD38 = 0x66 */
typedef enum
{
/**
* @brief SD reponses and error flags
*/
SDCARD_RESPONSE_NO_ERROR = (0x00),
SDCARD_IN_IDLE_STATE = (0x01),
SDCARD_ERASE_RESET = (0x02),
SDCARD_ILLEGAL_COMMAND = (0x04),
SDCARD_COM_CRC_ERROR = (0x08),
SDCARD_ERASE_SEQUENCE_ERROR = (0x10),
SDCARD_ADDRESS_ERROR = (0x20),
SDCARD_PARAMETER_ERROR = (0x40),
SDCARD_RESPONSE_FAILURE = (0xFF),
/**
* @brief Data response error
*/
SDCARD_DATA_OK = (0x05),
SDCARD_DATA_CRC_ERROR = (0x0B),
SDCARD_DATA_WRITE_ERROR = (0x0D),
SDCARD_DATA_OTHER_ERROR = (0xFF)
}SDCARD_Info;
這些都是我們后面要用到的,初始化SD卡就要發(fā)送命令,且要獲取響應(yīng)碼,因此編輯SDCARD_WriteCmd函數(shù)先
/**********************************************************************
函數(shù):SDCARD_WriteCmd()
函數(shù)作用:發(fā)送SD卡命令
參數(shù):
uint8_t cmd---------------------------------------發(fā)送的命令
uint32_t args-----------------------------------------命令參數(shù)
uint8_t crc_value--------------------------------------CRC校驗(yàn)碼
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-02
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
void SDCARD_WriteCmd(uint8_t cmd, uint32_t args, uint8_t crc_value)
{
uint8_t i = 0x00;
uint8_t frame[6];
/* Prepare Frame to send */
frame[0] = (cmd | 0x40); /* Construct byte 1 */
frame[1] = (uint8_t)(args >> 24); /* Construct byte 2 */
frame[2] = (uint8_t)(args >> 16); /* Construct byte 3 */
frame[3] = (uint8_t)(args >> 8); /* Construct byte 4 */
frame[4] = (uint8_t)(args); /* Construct byte 5 */
frame[5] = (crc_value); /* Construct byte 6 */
/* Send Frame */
for (i = 0; i < 6; i++)
{
SPI_SDCARD_Write(frame[i]); /* Send the Cmd bytes */
}
}
/**********************************************************************
函數(shù):SDCARD_WaitResponse()
函數(shù)作用:獲取SD卡回碼
參數(shù):
uint8_t response-----------------------------------指定的回碼
返回值:0:成功-1:失敗
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-02
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
int8_t SDCARD_WaitResponse(uint8_t response)
{
uint16_t time_out = 0xFFFF;
/* Check if response is got or a timeout is happen */
while ((SPI_SDCARD_Read() != response) && time_out)
{
time_out--;
}
if (time_out == 0)
{
/* After time out */
return (int8_t)-1;
}
else
{
/* Right response got */
return 0;
}
}
使用這兩個(gè)函數(shù)就可以實(shí)現(xiàn)我們的sd卡初始化了,如下
/**********************************************************************
函數(shù):SDCARD_Init()
函數(shù)作用:SD卡初始化
參數(shù):無(wú)
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-03
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
void SDCARD_Init(void)
{
uint8_t i = 0;
SPI_SDCARD_nCS_Set_High();
//發(fā)送80 個(gè)clks
for(i = 0; i < 10; i++)
{
SPI_SDCARD_Write(SDCARD_DUMMY_BYTE);
}
SPI_SDCARD_nCS_Set_Low();
SDCARD_WriteCmd(SDCARD_CMD_GO_IDLE_STATE,0x00000000,0x95);
if(0 != SDCARD_WaitResponse(SDCARD_IN_IDLE_STATE))
{
//進(jìn)入IDLE模式失敗
printf("response err!\r\n");
}
SPI_SDCARD_nCS_Set_High();
SPI_SDCARD_Write(SDCARD_DUMMY_BYTE);
printf("response success!\r\n");
SPI_SDCARD_nCS_Set_Low();
do
{
SDCARD_WriteCmd(SDCARD_CMD_SEND_OP_COND,0x00000000,0xFF);
}while(0 != SDCARD_WaitResponse(SDCARD_RESPONSE_NO_ERROR));
printf("sdcard init over!\r\n");
}
下載代碼到NUCLEO_F303RE目標(biāo)板運(yùn)行,發(fā)現(xiàn)只輸出了“response success”,SD卡是進(jìn)入了IDLE模式但是退不出來(lái),理想很豐滿,現(xiàn)實(shí)很骨感。。。試過(guò)改動(dòng)一些效果依然,可能是文檔不對(duì)頭吧,買TFT模塊提供的SD卡文檔是SanDisk Secure Digital Card product Manual Version2.2還是2004年的,而我的卡是Kingston的,但是找Kingston文檔找不到,就找SD規(guī)范組織的一個(gè)文檔SD Specifications part1 Physical Layer Simplified Specification Version 4.10這個(gè)就比較新了是2013年的,這個(gè)文檔就比較全面了,且提出了SDHC、SDXC,SDHC跟SDSC會(huì)有些許不同這個(gè)看文檔就曉得了。在初始化時(shí)有了不同的流程,之前我們?cè)贗DLE模式下不停的發(fā)送CMD1來(lái)使其退出IDLE模式,行不通。現(xiàn)在來(lái)看一下新文檔中有關(guān)SD卡初始化的流程
不再是單純的發(fā)送CMD1了而是多出了CMD8命令操作,在IDLE模式下發(fā)送CMD8命令,該命令是帶有參數(shù)的用來(lái)確認(rèn)SD卡的接口操作條件,如果該命令發(fā)送完畢后返回illegal command,表明其是Ver1.X規(guī)范的SD卡或者不是SD卡,如果該命令響應(yīng)正確表明該SD卡是符合Ver2.X規(guī)范就可以執(zhí)行其他操作了CMD58、ACMD41。官方文檔中不建議發(fā)送CMD1給SD卡了,因?yàn)樵撁詈茈y讓Host分辨出所接的是SD卡還是MMC卡。文檔中提到CMD8命令的CRC是一直使能的,因此CMD8和CMD1一樣,都要帶有正確的CRC值,現(xiàn)在來(lái)看一下CMD8的命令詳解
該命令參數(shù)中Arg[11:0]為有效位,但重要的是VHS域,來(lái)確定電壓提供范圍,這里當(dāng)然選擇1了——2.7-3.6V,Check pattern為任意值,谷歌一下很多人寫(xiě)的是0xAA,所以這里就寫(xiě)一樣的值吧,CRC=0x87,有關(guān)CRC的計(jì)算可以去網(wǎng)上下載計(jì)算工具,有很多,不然手動(dòng)計(jì)算很費(fèi)力的。CMD8的響應(yīng)碼為R7,5個(gè)字節(jié),如下
現(xiàn)在重寫(xiě)一下SDCARD_Init函數(shù)來(lái)看看其返回值
/**********************************************************************
函數(shù):SDCARD_Init()
函數(shù)作用:SD卡初始化
參數(shù):無(wú)
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-05
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
void SDCARD_Init(void)
{
uint8_t i = 0;
SPI_SDCARD_nCS_Set_High();
//發(fā)送80 個(gè)clks
for(i = 0; i < 10; i++)
{
SPI_SDCARD_Write(SDCARD_DUMMY_BYTE);
}
SPI_SDCARD_nCS_Set_Low();
SDCARD_WriteCmd(SDCARD_CMD_GO_IDLE_STATE,0x00000000,0x95);
if(0 != SDCARD_WaitResponse(SDCARD_IN_IDLE_STATE))
{
//進(jìn)入IDLE模式失敗
printf("response err!\r\n");
}
SPI_SDCARD_nCS_Set_High();
SPI_SDCARD_Write(SDCARD_DUMMY_BYTE);
printf("response success!\r\n");
SPI_SDCARD_nCS_Set_Low();
SDCARD_WriteCmd(SDCARD_CMD_SEND_IF_COND,0x1AA,0x87);//verify SD Card interface operating condition
while(1)
{
printf("ack:%02X\r\n",SPI_SDCARD_Read());
i++;
if(i >= 255)
{
break;
}
}
printf("sdcard init over!\r\n");
}
下載到目標(biāo)板查看串口輸出如下:
將結(jié)果跟R7對(duì)比,0xFF是無(wú)效值不用去管它,R7=0x01 0x00 0x00 0x01 0xAA共5個(gè)字節(jié),第一個(gè)字節(jié)為R1為IDLE模式,command version=0x00,voltage accepted=0x01,check pattern=0xAA,可以看到返回結(jié)果跟文檔匹配。說(shuō)明SD卡是支持CMD8命令同時(shí)可以在該電壓下工作,而且check pattern驗(yàn)證正確。啊,看到了一絲曙光那。。。
接下來(lái)對(duì)比前面的SPI模式初始化流程圖該發(fā)送CMD58(READ OCR)命令,流程圖中該框框是虛框即該步驟是可以省略的。CMD58命令格式如下:
其響應(yīng)碼為R3,R3的格式如下:
R3回碼由R1+OCR寄存器組成。
編輯SDCARD_Init函數(shù)增加讀取OCR寄存器代碼如下
SDCARD_WriteCmd (SDCARD_CMD_READ_OCR,0x00000000,SDCARD_NOCRC_BYTE);//read ocr register
while(1)
{
printf("acc:%02X\r\n",SPI_SDCARD_Read ());
i++;
if(i >= 250)
{
break;
}
}
查看返回值,如下:
在SPI模式下讀取寄存器是跟讀取block數(shù)據(jù)是一致的,返回值是一個(gè)字節(jié)響應(yīng)碼和幾個(gè)字節(jié)的data block,OCR寄存器的詳細(xì)內(nèi)容如下:
OCR寄存器是32bit共4個(gè)字節(jié),對(duì)比我們串口收到的回碼:0x01 0x00 0xFF 0x80 0x00,對(duì)比OCR寄存器可以發(fā)現(xiàn)OCR[23:15]=111111111b。UHS-II Card Status=0(只有UHS-I Card支持此位),CCS=0,busy=0(上電流程未完成),此時(shí)發(fā)送CMD58命令只能確認(rèn)其電壓范圍無(wú)法得知SD卡類型,等SD卡上電初始化完成之后再發(fā)送該命令就可以得知SD卡類型了通過(guò)CCS位來(lái)判斷。CCS=0:SD卡為SDSC,CCS=1:SD卡為SDHC/SDXC。CCS位只在busy=1時(shí)有效。因此在上電初始化時(shí)我們就省略這一步,直接操作下一步ACMD41命令。ACMD41命令是用來(lái)啟動(dòng)初始化流程并用來(lái)檢測(cè)SD卡的初始化流程是否完成,文檔中提到CMD8是一定要優(yōu)先于ACMD41命令發(fā)送的,SD卡接收CMD8命令后(如果有效)會(huì)擴(kuò)展CMD58和ACMD41指令。
啟動(dòng)初始化時(shí)用戶需要不斷的發(fā)送ACMD41命令給SD卡直到初始化完成即R1=0x00.ACMD41看名字就知道和CMD41不一樣,ACMD41命令是application specific command,在發(fā)送該命令之前需要發(fā)送CMD55命令(不帶參數(shù))來(lái)高速SD卡的控制器下一條命令是application specific command。
ACMD41命令格式如下:
其是帶有參數(shù)的,有效參數(shù)位為HCS,詳細(xì)信息如下
SPI模式下和SD模式下ACMD41的返回不一樣,在SPI模式下我們只需要將HCS位置1即可,表明支持高容量SD卡,再次修改SDCARD_Init函數(shù)
while(1)
{
SDCARD_WriteCmd (SDCARD_CMD_APP,0x00000000,SDCARD_NOCRC_BYTE);
SDCARD_GetResponse ();
SDCARD_WriteCmd (SDCARD_ACMD_SEND_OP_COND,0x40000000,SDCARD_NOCRC_BYTE);
while(1)
{
ack = SDCARD_GetResponse ();
printf("acc:%02X\r\n",ack);
i++;
if( i >= 5 || ack == 0x00)
{
break;
}
}
if(ack == 0x00)
{
break;
}
}
查看其返回結(jié)果,如下:
已經(jīng)初始化完畢,現(xiàn)在我們可以執(zhí)行CMD58命令來(lái)檢測(cè)SD卡類型,結(jié)果如下:
可以看到此時(shí)OCR寄存器中CCS位和busy位都是1,即初始化完成且SD卡類型為SDHC/SDXC。整合一下代碼,目前初始化的完整代碼如下
/********************************************************************** 函數(shù):SDCARD_Init() 函數(shù)作用:SD卡初始化 參數(shù):無(wú) 返回值:無(wú) 上一版本:無(wú) 當(dāng)前版本:1.0 作者:anobodykey 最后修改時(shí)間:2015-08-05 說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作 **********************************************************************/ void SDCARD_Init(void) { uint8_t i = 0; uint8_t ack = 0; SPI_SDCARD_nCS_Set_High(); //發(fā)送80 個(gè)clks for(i = 0; i < 10; i++) { SPI_SDCARD_Write(SDCARD_DUMMY_BYTE); } SPI_SDCARD_nCS_Set_Low(); SDCARD_WriteCmd(SDCARD_CMD_GO_IDLE_STATE,0x00000000,0x95); if(0 != SDCARD_WaitResponse(SDCARD_IN_IDLE_STATE)) { //進(jìn)入IDLE模式失敗 printf("response err!\r\n"); } SPI_SDCARD_nCS_Set_High(); SPI_SDCARD_Write(SDCARD_DUMMY_BYTE); printf("response success!\r\n"); SPI_SDCARD_nCS_Set_Low(); SDCARD_WriteCmd(SDCARD_CMD_SEND_IF_COND,0x1AA,0x87);//verify SD Card interface operating condition ack = SDCARD_GetResponse (); if(SDCARD_IN_IDLE_STATE != ack) { printf("get R1 err!\r\n"); return; } ack = SDCARD_GetResponse (); ack = SDCARD_GetResponse (); ack = SDCARD_GetResponse (); if(0x01 != ack) { printf("can't accept the voltage!\r\n"); return; } ack = SDCARD_GetResponse (); if(0xAA != ack) { printf("check pattern err!\r\n"); return; } while(1) { SDCARD_WriteCmd (SDCARD_CMD_APP,0x00000000,SDCARD_NOCRC_BYTE); SDCARD_GetResponse (); SDCARD_WriteCmd (SDCARD_ACMD_SEND_OP_COND,0x40000000,SDCARD_NOCRC_BYTE); while(1) { ack = SDCARD_GetResponse (); i++; if( i >= 5 || ack == 0x00) { break; } } if(ack == 0x00) { break; } } SDCARD_WriteCmd (SDCARD_CMD_READ_OCR,0x00000000,SDCARD_NOCRC_BYTE);//read ocr register ack = SDCARD_GetResponse (); ack = SDCARD_GetResponse (); SDCARD_GetResponse (); SDCARD_GetResponse (); SDCARD_GetResponse (); SPI_SDCARD_nCS_Set_High (); SDCARD_WriteDummy (); if(0xC0 == ack) { printf("sdhc/sdxc init over!\r\n"); } } 初始化結(jié)果如下: 終于搞定。。。SD卡信息比較大,這個(gè)代碼也是弄了三四天了吧大概,初始化完成之后剩下的就是讀寫(xiě)操作了。這里需要注意的是SDSC卡的block size是可以設(shè)定的,而sdhc/sdxc卡的block size是固定512字節(jié)的不可修改。讀寫(xiě)操作又可以參考EVAL庫(kù)函數(shù)里面的讀寫(xiě)函數(shù),先看一下讀寫(xiě)命令格式 可見(jiàn)參數(shù)為數(shù)據(jù)地址,這里SDSC和SDHC/SDXC又不同了, 對(duì)于SDSC來(lái)說(shuō)地址單元是字節(jié),對(duì)于SDHC/SDXC來(lái)說(shuō)地址單元是block即512字節(jié),(想想也就知道了只有32bit,按字節(jié)只能尋址4GB空間),發(fā)送完讀寫(xiě)命令后除了R1回碼外還有一個(gè)start block tokens and stop tran token。如下 我們的讀block函數(shù)如下
/**********************************************************************
函數(shù):SDCARD_ReadBlocks()
函數(shù)作用:讀取SD卡塊數(shù)據(jù)
參數(shù):
uint32_t blockStartAddr---------------------------塊的起始地址
uint8_t blockNumbers--------------------------------讀取的塊數(shù)
uint8_t *context---------------------------------數(shù)據(jù)存儲(chǔ)地址
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-05
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
int8_t SDCARD_ReadBlocks(uint32_t blockStartAddr, uint8_t blockNumbers, uint8_t *context)
{
uint32_t offset = 0;
uint16_t i = 0;
while(blockNumbers--)
{
SDCARD_WriteDummy ();
SDCARD_WriteCmd (SDCARD_CMD_READ_SINGLE_BLOCK,blockStartAddr+offset,SDCARD_NOCRC_BYTE);
if(0 != SDCARD_WaitResponse (SDCARD_RESPONSE_NO_ERROR))
{
return (int8_t)-1;
}
if(0 != SDCARD_WaitResponse (SDCARD_START_DATA_SINGLE_BLOCK_READ))
{
return (int8_t)-1;
}
for(i = 0; i < SDCARD_BLOCK_SIZE; i++)
{
*context = SPI_SDCARD_Read ();
context++;
}
offset += SDCARD_BLOCK_OFFSET;
/* get CRC bytes (not really needed by us, but required by SD) */
SPI_SDCARD_Read ();
SPI_SDCARD_Read ();
}
SDCARD_WriteDummy ();
return 0;
}
需要注意的是SDCARD_BLOCK_OFFSET在SDHC/SDXC中就不是512而是1了,如果sd卡類型是SDSC的話SDCARD_BLOCK_OFFSET就是可變的,由CMD16指令來(lái)確定,默認(rèn)的話一般是512,
#define SDCARD_DUMMY_BYTE 0xFF
#define SDCARD_NOCRC_BYTE 0xFF
#define SDCARD_BLOCK_SIZE 0x200
#define SDCARD_BLOCK_OFFSET 1
在主函數(shù)調(diào)用該函數(shù),
SPI_SDCARD_nCS_Set_Low ();
if(0 != SDCARD_ReadBlocks (0x00,1,arr))
{
printf("read err!\r\n");
}
SPI_SDCARD_nCS_Set_High ();
for(i = 0; i < 512; i++)
{
if(0 == i%16)
{
printf("\r\n");
}
printf("%02X ",arr[i]);
}
結(jié)果如下:
一看到最后的55 AA就曉得這個(gè)讀block函數(shù)是成功的,這個(gè)對(duì)比可以將SD卡通過(guò)讀卡器查到PC機(jī)上然后使用winhex軟件來(lái)查看其數(shù)據(jù)或者通過(guò)后面的寫(xiě)block函數(shù)來(lái)對(duì)比。讀block函數(shù)搞定后,寫(xiě)block就easy了,如下
/**********************************************************************
函數(shù):SDCARD_WriteBlocks()
函數(shù)作用:向SD卡寫(xiě)入塊數(shù)據(jù)
參數(shù):
uint32_t blockStartAddr---------------------------塊的起始地址
uint8_t blockNumbers--------------------------------寫(xiě)入的塊數(shù)
uint8_t *context---------------------------------數(shù)據(jù)存儲(chǔ)地址
返回值:無(wú)
上一版本:無(wú)
當(dāng)前版本:1.0
作者:anobodykey
最后修改時(shí)間:2015-08-05
說(shuō)明: 需使用SPI模式對(duì)SD卡進(jìn)行讀寫(xiě)操作
**********************************************************************/
int8_t SDCARD_WriteBlocks(uint32_t blockStartAddr, uint8_t blockNumbers, uint8_t *context)
{
uint16_t i = 0;
uint32_t offset = 0;
uint8_t ack = 0;
while(blockNumbers--)
{
SDCARD_WriteDummy ();
SDCARD_WriteCmd (SDCARD_CMD_WRITE_SINGLE_BLOCK,blockStartAddr+offset,SDCARD_NOCRC_BYTE);
if(0 != SDCARD_WaitResponse (SDCARD_RESPONSE_NO_ERROR))
{
return (int8_t)-1;
}
/* Send the data token to signify the start of the data */
SPI_SDCARD_Write (SDCARD_START_DATA_SINGLE_BLOCK_WRITE);
for(i = 0; i < SDCARD_BLOCK_SIZE; i++)
{
SPI_SDCARD_Write (*context);
context++;
}
offset+=SDCARD_BLOCK_OFFSET;
/* get CRC bytes (not really needed by us, but required by SD) */
SPI_SDCARD_Read ();
SPI_SDCARD_Read ();
ack = SDCARD_GetResponse ();//get data response
if(SDCARD_DATA_OK != ack)
{
return (int8_t)-1;
}
}
SDCARD_WriteDummy ();
return 0;
}
在主函數(shù)調(diào)用該函數(shù),
for(i = 0; i < 512; i++)
{
wri[i] = i;
}
SPI_SDCARD_nCS_Set_Low ();
if(0 != SDCARD_WriteBlocks (0x01,1,wri))
{
printf("write err!\r\n");
}
SPI_SDCARD_nCS_Set_High ();
SPI_SDCARD_nCS_Set_Low ();
if(0 != SDCARD_ReadBlocks (0x01,1,arr))
{
printf("read err!\r\n");
}
SPI_SDCARD_nCS_Set_High ();
for(i = 0; i < 512; i++)
{
if(0 == i%16)
{
printf("\r\n");
}
printf("%02X ",arr[i]);
}
不僅檢測(cè)了寫(xiě)函數(shù)同時(shí)還檢測(cè)了讀函數(shù),測(cè)試結(jié)果如下:
好了,SD卡的基本讀寫(xiě)也已經(jīng)完了,剩下的都是完善代碼了,三四天的感悟:多看文檔尤其是最新的文檔!以上代碼只針對(duì)SDHC卡,SDSC卡和SDXC卡由于我沒(méi)有所以就沒(méi)測(cè)試過(guò)。。。
上一篇:基于STM32的SDIO用4位總線24MHZDMA模式操作SHDC卡
下一篇:STM32CubeMx + SD Card + FatFs 讀寫(xiě)SD卡死等問(wèn)題
推薦閱讀
史海拾趣
近年來(lái),電子行業(yè)面臨著原材料價(jià)格上漲、市場(chǎng)競(jìng)爭(zhēng)激烈等挑戰(zhàn)。American Custom Components公司也不例外,面臨著成本壓力和市場(chǎng)份額的下降。為了應(yīng)對(duì)這些挑戰(zhàn),公司采取了一系列措施,包括優(yōu)化生產(chǎn)流程、降低生產(chǎn)成本、加強(qiáng)研發(fā)創(chuàng)新等。同時(shí),公司還積極拓展新的應(yīng)用領(lǐng)域和市場(chǎng),尋找新的增長(zhǎng)點(diǎn)。這些努力使得公司在行業(yè)競(jìng)爭(zhēng)中保持了一定的優(yōu)勢(shì)。
為了進(jìn)一步擴(kuò)大市場(chǎng)份額,GD Rectifiers Ltd實(shí)施了積極的國(guó)際化戰(zhàn)略。公司首先在歐洲市場(chǎng)設(shè)立了銷售分支機(jī)構(gòu),憑借其優(yōu)質(zhì)的產(chǎn)品和服務(wù)迅速贏得了當(dāng)?shù)乜蛻舻恼J(rèn)可。隨后,公司又陸續(xù)在北美、亞洲等地區(qū)建立了分銷網(wǎng)絡(luò),逐步構(gòu)建起覆蓋全球的營(yíng)銷體系。在國(guó)際化進(jìn)程中,GD Rectifiers Ltd注重與當(dāng)?shù)仄髽I(yè)的合作與交流,共同推動(dòng)行業(yè)標(biāo)準(zhǔn)的制定和技術(shù)進(jìn)步。通過(guò)不斷的努力,公司成功地將品牌和產(chǎn)品推向了全球市場(chǎng),實(shí)現(xiàn)了業(yè)務(wù)規(guī)模的快速增長(zhǎng)。
面對(duì)數(shù)字化時(shí)代的到來(lái),GD Rectifiers Ltd主動(dòng)擁抱變革,積極推進(jìn)數(shù)字化轉(zhuǎn)型。公司投入巨資建設(shè)了先進(jìn)的數(shù)字化生產(chǎn)管理系統(tǒng)和客戶關(guān)系管理系統(tǒng),實(shí)現(xiàn)了生產(chǎn)過(guò)程的智能化和透明化。通過(guò)數(shù)據(jù)分析和挖掘技術(shù),公司能夠更準(zhǔn)確地把握市場(chǎng)需求和客戶需求的變化趨勢(shì),為產(chǎn)品研發(fā)和市場(chǎng)營(yíng)銷提供有力支持。同時(shí),公司還加強(qiáng)了與供應(yīng)商和客戶的數(shù)字化連接和協(xié)作,提高了供應(yīng)鏈的協(xié)同效率和響應(yīng)速度。數(shù)字化轉(zhuǎn)型的成功實(shí)施為GD Rectifiers Ltd注入了新的活力,進(jìn)一步提升了公司的市場(chǎng)競(jìng)爭(zhēng)力和行業(yè)地位。
FINTEK公司成立于2000年代初,正值半導(dǎo)體技術(shù)快速發(fā)展的時(shí)期。公司初創(chuàng)時(shí),便聚焦于開(kāi)發(fā)高性能的模擬信號(hào)處理器(ASP)芯片。創(chuàng)始人帶領(lǐng)團(tuán)隊(duì),經(jīng)過(guò)數(shù)年的不懈努力,成功研發(fā)出了一款具有創(chuàng)新性的ASP芯片,該芯片在功耗、信噪比和信號(hào)處理速度上均優(yōu)于市場(chǎng)同類產(chǎn)品。這一技術(shù)突破不僅為公司贏得了首輪融資,也吸引了眾多行業(yè)巨頭的關(guān)注,為FINTEK在電子行業(yè)的初步立足奠定了堅(jiān)實(shí)的基礎(chǔ)。
隨著電子行業(yè)的快速發(fā)展,科達(dá)嘉意識(shí)到技術(shù)革新是企業(yè)持續(xù)發(fā)展的關(guān)鍵。因此,公司不斷增加自動(dòng)化生產(chǎn)設(shè)備,購(gòu)置先進(jìn)的質(zhì)量測(cè)試儀器,并籌建了電感元器件分析實(shí)驗(yàn)室和標(biāo)準(zhǔn)的AEC-Q200可靠性實(shí)驗(yàn)室。這些舉措大大增強(qiáng)了公司的研發(fā)分析能力,提升了產(chǎn)品質(zhì)量和生產(chǎn)效率??七_(dá)嘉逐漸形成了以材料研發(fā)、產(chǎn)品研發(fā)、生產(chǎn)、質(zhì)量及物控為基礎(chǔ)的完整產(chǎn)業(yè)鏈。
關(guān)于信號(hào)輸出對(duì)電路造成影響的問(wèn)題! 我現(xiàn)在遇到一個(gè)奇怪的問(wèn)題,如果我將電路中的某個(gè)信號(hào)賦值給一個(gè)輸出管腳的話,那么整個(gè)電路的邏輯都不對(duì)了。(如果不輸出的話,通過(guò)其它管腳觀察時(shí)邏輯是正確的) 大家有沒(méi)有碰到過(guò)這種情況?是怎么回事?請(qǐng)高手指點(diǎn)! 注:我是在quartus8.1中用 ...… 查看全部問(wèn)答∨ |
CPU為32位ARM芯片 Nand flash芯片為三星K9F1G08X0M (X8),有效存儲(chǔ)128M + 4M OOB 地址分配如下面所示: IO0 IO1 IO2 ...… 查看全部問(wèn)答∨ |
收購(gòu):現(xiàn)需要收購(gòu) SmartARM2400 的包裝盒若干個(gè),以及裝書(shū)的那個(gè)硬包裝盒若干個(gè),謝謝! 發(fā)現(xiàn) SmartARM 2400 的包裝盒裝東西非常合適,想弄幾個(gè), SmartARM套件中的那個(gè)裝書(shū)的硬紙盒也非常不錯(cuò),用來(lái)整理書(shū)架是非常不錯(cuò)的選擇,非常想多弄幾個(gè)。 可以和我郵件聯(lián)系, rampc@sian.com 不要太貴哦,我明天再把我想要的 ...… 查看全部問(wèn)答∨ |
信息產(chǎn)業(yè)部—硬件設(shè)計(jì)工程師培訓(xùn)火爆報(bào)名中!?。。?! 全國(guó)硬件工程師實(shí)訓(xùn)基地系信息產(chǎn)業(yè)部電子教育與考試中心指定的硬件工程師獨(dú)家教育機(jī)構(gòu),有著多年的IT業(yè)培訓(xùn)經(jīng)驗(yàn),與諸多IT企業(yè)有著密切聯(lián)系,經(jīng)過(guò)兩年多的精心策劃特推出PCB設(shè)計(jì)工程師,單片機(jī)設(shè)計(jì)工程師,嵌入式系統(tǒng)工程師職業(yè)培訓(xùn),詳情請(qǐng)百度搜索\"單 ...… 查看全部問(wèn)答∨ |
我最近使用W77E58,使用了看門狗復(fù)位,原先使用正常,但在其他與看門狗無(wú)關(guān)的地方作了一些程序修改,之后看門狗工作就不正常了,正常喂狗時(shí)沒(méi)什么問(wèn)題,但我一停止喂狗后,程序會(huì)停下來(lái),只不過(guò)它沒(méi)有從頭開(kāi)始.就死在那里了,不知道為什么,哪位幫幫我.我的看 ...… 查看全部問(wèn)答∨ |
是否可以做個(gè)這個(gè)Stellaris® Robotic 官方網(wǎng)站有資料,采用的是9B92,有興趣的可以去看看 [ 本帖最后由 chenzhufly 于 2011-3-5 17:25 編輯 ]… 查看全部問(wèn)答∨ |
我在使用uC/OSII的時(shí)候遇到一些問(wèn)題:使用ICCAVR專業(yè)版6.31編譯的時(shí)候出現(xiàn)如下的信息:C:\\icc\\bin\\imakew -f MainController.mak iccavr -o MainController -LC:\\icc\\lib\\ -g -uc ...… 查看全部問(wèn)答∨ |
本帖最后由 jameswangsynnex 于 2015-3-3 20:01 編輯 現(xiàn)在看到很多智能吸塵器(如:KV8,Deepoo等)都帶有自動(dòng)充電功能。 現(xiàn)在想詢問(wèn)一下,是怎樣讓吸塵器自動(dòng)找到充電座,然后準(zhǔn)確對(duì)接的,對(duì)這個(gè)問(wèn)題很是困惑,沒(méi)有一個(gè)好的解決方案。 ...… 查看全部問(wèn)答∨ |
用MSP430G2553做了一個(gè)控制板,一個(gè)TM1640芯片用作顯示,兩個(gè)595用作顯示和繼電器控制,但就是過(guò)不了群脈沖測(cè)試,群脈沖一打上去,顯示全亂了,觸摸按鍵也不靈光了,一不打,就好了,我不知道問(wèn)題出在哪?附件為原理圖?!? 查看全部問(wèn)答∨ |
請(qǐng)教07stack關(guān)于地址矛盾的問(wèn)題 不知道有沒(méi)人通過(guò)Zigbee 07stack的證書(shū)?想請(qǐng)教關(guān)于07stack關(guān)于地址矛盾的解決。之前我們的做法是一旦發(fā)生這個(gè)不管它是怎樣的狀況, 所有的地址矛盾的終端都重新派一個(gè)新的地址。但是最近發(fā)現(xiàn)要那證書(shū)的時(shí)候,完全被他們測(cè)試搞糊涂了, 而且07協(xié)議 ...… 查看全部問(wèn)答∨ |
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦
- Alif 大幅增強(qiáng)邊緣 AI 處理器性能
- VS Code+PlatformIO搭建ESP32 Arduino開(kāi)發(fā)環(huán)境
- ESP32學(xué)習(xí)筆記(49)——RFID RC522使用
- Esp32環(huán)境離線搭建參考
- ESP32使用舵機(jī)庫(kù)時(shí)的錯(cuò)誤
- ESP32 S3接ST7789屏幕線序
- Arduino IDE安裝ESP32開(kāi)發(fā)環(huán)境的最簡(jiǎn)單方法
- 基于S3C44B0X和μC/OS-Ⅱ智能家居嵌入式系統(tǒng)設(shè)計(jì)
- 8位還能打,新唐推出全新工業(yè)級(jí)MCU
- 半導(dǎo)體關(guān)稅可能會(huì)使您的下一輛汽車更加昂貴
- 潮起!人形機(jī)器人成本的20%-30%——靈巧手,國(guó)產(chǎn)3大廠商正快速產(chǎn)業(yè)化!
- AB Dynamics發(fā)布用于無(wú)人駕駛測(cè)試的物體檢測(cè)系統(tǒng)
- AI重構(gòu)出行:高階輔助駕駛的破局之路
- 廣汽即將發(fā)布全新星源增程技術(shù)
- Yole表示,到2030年,數(shù)據(jù)中心芯片市場(chǎng)規(guī)模將達(dá)到5000億美元
- 綠色節(jié)能趨勢(shì)下的延時(shí)繼電器發(fā)展:低功耗設(shè)計(jì)與環(huán)保材料應(yīng)用
- 國(guó)內(nèi)車企在固態(tài)電池領(lǐng)域的挑戰(zhàn)和技術(shù)方案
- 資本熱捧 + 政策護(hù)航,2025 人形機(jī)器人能否叩開(kāi) “量產(chǎn)元年” 大門?
- 耐世特推出用于智能運(yùn)動(dòng)控制的 MotionIQ?軟件套件
- 學(xué)習(xí)贏京東卡 | 從12V電池及供電網(wǎng)絡(luò)優(yōu)化的角度分析電動(dòng)汽車E/E架構(gòu)的趨勢(shì)
- 新年狂歡盛宴,TI開(kāi)發(fā)板秒不停?。。?/a>
- 芯幣 積分禮品兌換
- 閱讀瑞薩電子電源模塊系列白皮書(shū),贏雙重好禮:提升能量有禮&推薦100%有禮 !
- 愛(ài)“拼”才會(huì)贏 英飛凌柵極驅(qū)動(dòng)IC拼圖闖關(guān) 活動(dòng)開(kāi)始啦!
- 看東芝在線展會(huì)視頻,聽(tīng)權(quán)威汽車技術(shù)講解!
- 免費(fèi)申請(qǐng)|超小型 Linux 開(kāi)發(fā)套件:Quantum Tiny Linux(帶 SoM 和擴(kuò)展板)
- 三人行必有我?guī)煛狤Eworld網(wǎng)友原創(chuàng)教程隆重登場(chǎng)!
- 可提供硅基OLED等系列微顯示芯片,芯視半導(dǎo)體獲千萬(wàn)元融資
- 思科財(cái)測(cè)消極,公布自愿退休和裁員計(jì)劃
- 蘋(píng)果申請(qǐng)骨傳導(dǎo)技術(shù)耳機(jī)專利!會(huì)是下一個(gè)AirPods嗎?
- 通富微電:公司系聯(lián)發(fā)科國(guó)內(nèi)封測(cè)業(yè)務(wù)最主要的合作廠商之
- 敦泰電子:對(duì)莫良華及其關(guān)聯(lián)公司追責(zé)未結(jié)束
- 士蘭微向子公司增資,提升MEMS傳感器產(chǎn)品市占率
- 中國(guó)AI看北京 北京AI看中關(guān)村
- 晶方科技預(yù)計(jì)2017年凈利潤(rùn)同比增加81.52%,受益手機(jī)功能創(chuàng)新
- 士蘭微預(yù)計(jì)2017年凈利潤(rùn)同比增長(zhǎng)90%,8寸產(chǎn)能達(dá)預(yù)期
- vivo X20 Plus屏幕指紋版發(fā)布 全球首款屏下指紋手機(jī)量產(chǎn)
- 凌陽(yáng)61單片機(jī)與外設(shè)串口通信,我有一個(gè)模塊定義的協(xié)議如下文,請(qǐng)哪位高手幫我用C代碼實(shí)現(xiàn)一下,謝謝!
- ATSHA204A是如何實(shí)現(xiàn)硬件加密的 ?
- controlSUITE-----學(xué)習(xí)C2000 MUC必備的、有效的的工具
- wince下開(kāi)發(fā)ASP程序問(wèn)題
- 利用xilinx作IO擴(kuò)展
- 這個(gè)電路可以當(dāng)做4-20ma的電路來(lái)用嗎
- 【MSP430共享】IAR開(kāi)發(fā)環(huán)境中的數(shù)據(jù)、函數(shù)定位方法
- SPARQ系列述評(píng)之一
- pdf閱讀器開(kāi)發(fā)
- 武漢急招wince應(yīng)用開(kāi)發(fā)人員