STM32 Development Board Getting Started Tutorial (Thirteen) - SPI Mode Read and Write SD Card

Publisher:天涯拾遗Latest update time:2018-08-21 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
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;
}


Keywords:STM32 Reference address:STM32 Development Board Getting Started Tutorial (Thirteen) - SPI Mode Read and Write SD Card

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

STM32 ADC sampling period determination
1.  Determination of STM32  ADC  sampling  frequency 1.              : First look at some information to determine the ADC  clock: (1) The ADCCLK clock provided by the clock controller  is synchronized with PCLK2 (APB2  clock).  The CLK controller provides a dedicated programmable prescaler for the ADC  clock.  
[Microcontroller]
Stm32 debugging assert_param() assertion mechanism
void TIM_DeInit(TIM_TypeDef* TIMx) {     /* Check the parameters */     assert_param(IS_TIM_ALL_PERIPH(TIMx));          if (TIMx == TIM1)     {         RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);         RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1 , DISABLE);     } } This code is in the Stm32 firmware library
[Microcontroller]
STM32: Receive SPI bus data in DMA mode and process it according to the protocol
I. Introduction To meet the requirements of high-speed data transmission, the SPI bus is used. The MCU (STM32F072 Cortex-M0) receives the SPI data sent by the CPU (18 bytes of data per packet, the starting packet is 0xAA, and the last packet is CheckSum verification). After receiving, the verified data is assigned to
[Microcontroller]
Design of home service robot system based on STM32
   introduction   With the development of artificial intelligence and sensor technology, robots have entered people's daily life from the structured environment of factories. Robots can not only complete tasks autonomously, but also collaborate with people to complete tasks or complete tasks under the guidance of pe
[Security Electronics]
Design of home service robot system based on STM32
STM32 timer period dynamic modification
Recently, there is a need to simulate the serial port in the project at hand, and the simulated serial port part has such a requirement: when the Strat signal comes, start the timer TIM3, and sample whether the Start signal is a low level after 52us, and then change the timer period to 104us to sample the remaining 9
[Microcontroller]
STM32 timer period dynamic modification
Steps to set up interrupts for STM32
The following figure summarizes the interrupts of the STM32F10XXX series chips By default, the interrupt vector table is located in a read-only memory such as Flash, and there is no need to modify the vector table during operation. The interrupt vector table is located at the beginning of the memory by default (a
[Microcontroller]
Steps to set up interrupts for STM32
Download stm32 program via USB to TTL serial port
Table of contents: 1. Hardware and wiring 2. Drivers and software 3. Download program test   1. Hardware and wiring    1.1 USB to TTL flashing board (CH340 module upgrade board)                1.2 Main chip STM32F103C8T6 development board    1.3 Wiring        1.3.1 Serial port module wiring   Note: 3V3 and 5V ar
[Microcontroller]
Download stm32 program via USB to TTL serial port
Application of STM32 in variable frequency pulsator washing machine
With the guidance of the national energy conservation and emission reduction policy and the improvement of people's awareness of energy conservation and environmental protection, frequency conversion technology has been widely used in white household appliances such as air conditioners, refrigerators, and washing mach
[Microcontroller]
Application of STM32 in variable frequency pulsator washing machine
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号