Function introduction: Use SPI mode to read and write SD card block data and send it to PC through serial port for viewing |
SD card is the abbreviation of Secure Digital Card, which literally translates into Chinese as "Secure Digital Card". It is a brand-new memory card product jointly developed by Japan's Panasonic, Toshiba and the United States' SANDISK. SD memory card is a completely open standard (system), which is mostly used in MP3, digital video cameras, digital cameras, e-books, AV equipment, etc., especially widely used in ultra-thin digital cameras. Haha, why do we like to use SD cards when making things now? It has a large capacity and a low price. The number of read and write times is more than 100,000 times (some data say it is 300,000 times, haha). This number is powerful enough, and the reading and writing speed is also very fast. Now the high-speed SD card can write at a speed of up to 20M/S. Haha, if the SD card you bought cannot reach this speed, you should consider whether you have bought a fake. Haha, SD cards are very cheap now. It seems that a 4G card is only 50 yuan each. |
Well, let's not go off topic, let's get back to the point. There are two ways to read and write SD cards, one is SD mode and the other is SPI mode. The SD mode has a complex operation timing and uses many IO ports. The commonly used mode is SPI mode. The SPI mode we introduce today is also simple in interface and easy to transplant. The speed is not slow. Using the high-speed SPI mode, 1M/S should be easy to achieve. I just transplanted the SD card reading and writing under STM32, but I didn't test the reading and writing speed. I'll test the reading and writing speed next time I have time and post it. |
SD card initialization process: 1. Initialize the SPI interface of STM32 to use low-speed mode 2. Delay at least 74clock 3. Send CMD0, need to return 0x01, enter Idle state 4. Loop and send CMD55+ACMD41 until it returns 0x00 and enters Ready state 5. Set the read and write block size to 512byte 5. Set the STM32 SPI to high-speed mode The process of reading a block 1. Send CMD17 (single block) or CMD18 (multiple blocks) read command, return 0x00 2. Receive data start token 0xfe + formal data 512Bytes + CRC check 2Bytes The process of writing a block 1. Send CMD24 (single block) or CMD25 (multiple blocks) write command, return 0x00 2. Send data start token 0xfe + formal data 512Bytes + CRC check 2Bytes Attach a datasheet with the standard spi mode initialization flow |
初始化函数 /******************************************************************************* * Function Name : SD_MMC_SPI_Init * Description : SD_MMC_SPI_Init * Input : None * Output : None * Return : zero init success, non-zero init error *******************************************************************************/ u8 SD_MMC_SPI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_SD_MMC_SPI_CS, ENABLE); /* Configure SPI1 pins: SCK, MISO and MOSI */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure SD_MMC_SPI_CS */ GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_CS_Pin_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure); //////////////////////////////////////////////////////////////////////////////////////////////// /* initialize SPI with lowest frequency */ SD_MMC_Low_Speed(); /* card needs 74 cycles minimum to start up */ for(u8 i = 0; i < 10; ++i) { /* wait 8 clock cycles */ SD_MMC_ReadWrite_Byte(0x00); } /* address card */ SD_MMC_SPI_SELECT(); /* reset card */ u8 response; for(u16 i = 0; ; ++i) { response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE , 0 ); if( response == 0x01 ) break; if(i == 0x1ff) { SD_MMC_SPI_DESELECT(); return 1; } } /* wait for card to get ready */ for(u16 i = 0; ; ++i) { response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0); if(!(response & (1 << R1_IDLE_STATE))) break; if(i == 0x7fff) { SD_MMC_SPI_DESELECT(); return 1; } } /* set block size to 512 bytes */ if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512)) { SD_MMC_SPI_DESELECT(); return 1; } /* deaddress card */ SD_MMC_SPI_DESELECT(); /* switch to highest SPI frequency possible */ SD_MMC_High_Speed(); return 0; } |
Send a command /********************************************** ********************************* * Function Name: SD_MMC_Send_Command * Description: SD_MMC_Send_Command * Input: None * Output: None * Return: None ********************************************** *********************************/ u8 SD_MMC_Send_Command(u8 cmd, u32 arg) { u8 Response; u8 Retry = 0; SD_MMC_ReadWrite_Byte(0xff); SD_MMC_SPI_SELECT(); //Write commands respectively SD_MMC_ReadWrite_Byte(cmd | 0x40); SD_MMC_ReadWrite_Byte(arg >> 24); SD_MMC_ReadWrite_Byte(arg >> 16); SD_MMC_ReadWrite_Byte(arg >> 8); SD_MMC_ReadWrite_Byte(arg); SD_MMC_ReadWrite_Byte(0x95); do{ // Wait for response, the start bit of the response is 0 Response = SD_MMC_ReadWrite_Byte(0xff); Retry++; }while( ((Response&0x80)!=0) && (Retry < 200) ) ; SD_MMC_SPI_DESELECT(); return Response; //Return status value } |
读一个block块 读取成功返回0 非0 则读取失败 /******************************************************************************* * Function Name : SD_MMC_Read_Single_Block * Description : SD_MMC_Read_Single_Block * Input : sector number and buffer data point * Output : None * Return : zero success, non-zero error *******************************************************************************/ u8 SD_MMC_Read_Single_Block(u32 sector, u8* buffer) { u8 Response; u16 i; u16 Retry = 0; //读命令 send read command Response = SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, sector<<9); if(Response != 0x00) return Response; SD_MMC_SPI_SELECT(); // start byte 0xfe while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe) { if(++Retry > 0xfffe) { SD_MMC_SPI_DESELECT(); return 1; //timeout } } for(i = 0; i < 512; ++i) { //读512个数据 *buffer++ = SD_MMC_ReadWrite_Byte(0xff); } SD_MMC_ReadWrite_Byte(0xff); //伪crc SD_MMC_ReadWrite_Byte(0xff); //伪crc SD_MMC_SPI_DESELECT(); SD_MMC_ReadWrite_Byte(0xff); // extra 8 CLK return 0; } |
写一个block块 成功返回0 非0 则写入失败 /******************************************************************************* * Function Name : SD_MMC_Write_Single_Block * Description : SD_MMC_Write_Single_Block * Input : sector number and buffer data point * Output : None * Return : zero success, non-zero error. *******************************************************************************/ u8 SD_MMC_Write_Single_Block(u32 sector, u8* buffer) { u8 Response; u16 i; u16 retry=0; //写命令 send write command Response = SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, sector<<9); if(Response != 0x00) return Response; SD_MMC_SPI_SELECT(); SD_MMC_ReadWrite_Byte(0xff); SD_MMC_ReadWrite_Byte(0xff); SD_MMC_ReadWrite_Byte(0xff); //发开始符 start byte 0xfe SD_MMC_ReadWrite_Byte(0xfe); //送512字节数据 send 512 bytes data for(i=0; i<512; i++) { SD_MMC_ReadWrite_Byte(*buffer++); } SD_MMC_ReadWrite_Byte(0xff); //dummy crc SD_MMC_ReadWrite_Byte(0xff); //dummy crc Response = SD_MMC_ReadWrite_Byte(0xff); //等待是否成功 judge if it successful if( (Response&0x1f) != 0x05) { SD_MMC_SPI_DESELECT(); return Response; } //等待操作完 wait no busy while(SD_MMC_ReadWrite_Byte(0xff) != 0x00) { if(retry++ > 0xfffe) { SD_MMC_SPI_DESELECT(); return 1; } } SD_MMC_SPI_DESELECT(); SD_MMC_ReadWrite_Byte(0xff);// extra 8 CLK return 0; } |
Previous article:Precautions for using stm32 official SD card driver
Next article:Implementation of stm32f4 reading and writing SD card with fatfs based on spi
Recommended ReadingLatest update time:2024-11-15 07:49
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Regarding loop compensation, this article is enough
- Espressif ESP32-C3 Function Introduction (Preview: ESP32-C3-DevKitM-1 Review will be launched on May 17)
- [GD32L233C-START Review] Display Control of DWIN Smart Screen
- Why does MCU also need AI?
- How to design solutions for wireless charging of wearable devices
- Newbie help, how to use 51 MCU to do EV1527 433Mhz decoding??
- [NXP Rapid IoT Review] +3. Rapid IoT Studio online IDE Test 1 - BLE control indicator
- TO220 package and heat sink fixing problem
- How to calculate clock pulse width from sampling rate of serial ADC?
- After the power supply common mode surge protection, the power supply output voltage rises instead of falling