Simple SD card reading and writing for STM32

Publisher:HeavenlyLoveLatest update time:2017-11-02 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

SD cards generally support two read and write modes, SPI and SDIO modes. The pin arrangement of SD cards is shown in the figure below.


There are several important operation commands in SPI mode, namely:




The format of SD card R1 response is as follows


The typical initialization process in SPI mode is as follows:

1. Initialize hardware configuration, SPI configuration, IO configuration, etc.

2. Power-on delay. (>74CLK)

3. Reset the card. (CMD0)

4. Activate the card, initialize internally and obtain the card type.

5. Query OCR to obtain power supply status.

6. Whether to use CRC (CMD59).

7. Set the read/write block data length (CMD16).

8. Read CSD and obtain other information of the memory card (CMD9)

9. After sending 8CLK, chip select is disabled.

The typical process of reading data in SPI mode is as follows, which is implemented using CMD17.

1. Send CMD17.

2. The receiving card responds with R1.

3. Receive data start token 0XFE.

4. Receive data.

5. Receive two bytes of CRC. If CRC is not enabled, these two bytes can be discarded after reading.

6. Chip select is prohibited after 8CLK.

The typical process of writing data in SPI mode is as follows, where CMD24 is used to implement it.

1. Send CMD24.


2. The receiving card responds with R1.

3. Receive data start token 0XFE.

4. Receive data.

5. Send two bytes of pseudo CRC.

6. Chip select is prohibited after 8CLK.

The specific code implementation is as follows.

/*******************************************************************************
* Function Name : SPI_FLASH_Init
* Description : Initializes the peripherals used by the SPI FLASH driver.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SPI_SD_Init(void)
{
  
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable the clock of the corresponding SPI pin Enable the clock of SPI1*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
  
  /* Configure the SPI clock line SCK and the SPI MOSI line and the SPI MISO line*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Push-pull output of multiplexing function
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /*Configure SPI chip select line: CSN */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Push-pull output
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Pull up the CSN pin to stop enabling SD*/
  GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_8);
  GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);

  // Configure SPI to suit the characteristics of
  SDSPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Two-line bidirectional full-
  duplexSPI_InitStructure.SPI_Mode = SPI_Mode_Master; //Master deviceSPI_InitStructure.SPI_DataSize
  = SPI_DataSize_8b;//8-bit data lengthSPI_InitStructure.SPI_CPOL
  = SPI_CPOL_High; //Clock is high when floatingSPI_InitStructure.SPI_CPHA
  = SPI_CPHA_2Edge; //Data is captured at the second clock edgeSPI_InitStructure.SPI_NSS
  = SPI_NSS_Soft; //NSS signal is managed by external pinSPI_InitStructure.SPI_BaudRatePrescaler
  = SPI_BaudRatePrescaler_256;//Baud rate prescaler value is 4
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //The first byte of data transmission is MSB
  SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC polynomial
  SPI_Init(SPI1, &SPI_InitStructure);
  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);
}

/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Send a data and receive the data returned from FLASH at the same time
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
u8 SPIx_ReadWriteByte(u8 byte)
{
  /* Wait for the data send register to be cleared*/
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /* Send one byte of data through SPI*/
  SPI_I2S_SendData(SPI1, byte);

  /* Waiting for receiving a data (receiving a data is equivalent to sending a data) */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return received data */
  return SPI_I2S_ReceiveData(SPI1);
}

/*******************************************************************************
* Function Name : SPI_FLASH_SendHalfWord
* Description : Send and receive a half word of data (16 bits)
* Input : Half Word : Half Word to send.
* Output : None
* Return : The value of the received Half Word.
*******************************************************************************/
u16 SPIx_ReadWriteHalfWord(u16 HalfWord)
{
  /* Wait for the data send register to be cleared*/
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /* Send half word of data through SPI*/
  SPI_I2S_SendData(SPI1, HalfWord);

  /* Waiting for receiving a half-word of data (receiving a data is equivalent to completing sending a data) */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return received data*/
  return SPI_I2S_ReceiveData(SPI1);
}
//SPI speed setting function
//SpeedSet:
//SPI_BaudRatePrescaler_2 2 division (SPI  36M@sys  72M)
//SPI_BaudRatePrescaler_8 8 division (SPI  9M@sys  72M)
//SPI_BaudRatePrescaler_16 16 division (SPI  4.5M@sys  72M)
//SPI_BaudRatePrescaler_256 256 division (SPI  281.25K@sys  72M)
  
void SPIx_SetSpeed(u8 SpeedSet)
{
 SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
   SPI_Init(SPI1, &SPI_InitStructure);
 SPI_Cmd(SPI1,ENABLE);
}

/******************************END OF INIT_SPI*****************************/


/******************************START OF SD_OPERATION***********************/
/*******************************************************************************
* Function name: SD_Select
* Function description: Select SD card and wait for SD card to be ready
* Entry parameter: None.
* Return parameter: 0: Success 1: Failure
* Remarks: SD card is ready and will return 0XFF
*******************************************************************************/
u8 SD_Select(void)
{
 uint32_t t=0;
 SD_CS(OFF); //Chip select SD, low level enable
 do
 {
  if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
  t++;     
 }while(t<0XFFFFFF);//Wait for
 SD_DisSelect(); //Release bus
 return 1;//Wait for failure
}
/*******************************************************************************
* Function name: SD_RecvData
* Function description: Read the content of a data packet from the SD card
* Entry parameters: buf: data buffer array len: the length of the data to be read
* Return parameters: 0: success Others: failure
* Remarks: When reading, you need to wait for the SD card to send the data start token 0XFE
***********************************************************************************/
u8 SD_RecvData(u8*buf,u16 len)

 u16 Count=0xF000;//Wait timeswhile
 ((SD_SPI_ReadWriteByte(0XFF)!=0xFE)&&Count)Count--;//Wait to get the read data token 0xfe
 if (Count==0) return MSD_RESPONSE_FAILURE;//Failed to get the token, return 0XFF      
    while(len--)//Start receiving data
    {
        *buf=SPIx_ReadWriteByte(0xFF);
        buf++;
    }
    //Below are 2 dummy CRCs, pretending to receive 2 CRCs
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);                     
    return 0;//Read successful
}
/*******************************************************************************
* Function name: SD_SendBlock
* Function description: Write a data packet of 512 bytes to the SD card
* Entry parameters: buf: data buffer cmd: token for data sending 
* Return parameters: 0: success Others: failure
* Remarks: When writing data, you need to send the data start token 0XFE/0XFC/0XFD first
*******************************************************************************/
u8 SD_SendBlock(u8*buf,u8 cmd)

 u32 t,Count=0XFFFFFF; 
 while ((SD_SPI_ReadWriteByte(0XFF)!=0xFF)&&Count)Count--;//Wait for SD card to be readyif
 (Count==0) return MSD_RESPONSE_FAILURE;//SD card is not ready, failed, return
 SD_SPI_ReadWriteByte(cmd); //Send data start or stop tokenif
 (cmd!=0XFD)//Start sending data when it is not the end token
 {
  for(t=0;t<512;t++)SPIx_ReadWriteByte(buf[t]);//Increase speed and reduce function parameter transmission
     timeSD_SPI_ReadWriteByte(0xFF);//Send 2-byte CRC
     SD_SPI_ReadWriteByte(0xFF);
  t=SD_SPI_ReadWriteByte(0xFF);//Receive data write status immediately after CRCif
  ((t&0x1F)!=0x05)return MSD_DATA_WRITE_ERROR; //Write error                    
 }                           
    return 0;//Write successfully
}
/*******************************************************************************
* Function name: SD_SendCmd
* Function description: Write the content of a data packet of 512 bytes to the SD card
* Entry parameters: cmd: command arg: command parameter crc: crc check value and stop bit
* Return parameters: Return value: The response of the corresponding command returned by the SD card
* Remarks: The response is R1-R7, see SD Protocol Manual V2.0 (2006)
*******************************************************************************/
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1; 
 u8 Retry=0; 
 SD_DisSelect();//Cancel the last chip select and release the busif
 (SD_Select())return 0XFF;//Check if the chip select signal line is selected successfully
 //Send
    SD_SPI_ReadWriteByte(cmd | 0x40);//Write commands respectively
    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
    //Wait for response, or time out and exit
 Retry=0X1F;
 do //Send a certain number of clock signals, waiting for the SD card to respond with 0X01 (0x01 means the command is sent successfully, and 0XFF means failure)
 {
  r1=SD_SPI_ReadWriteByte(0xFF);
 }while((r1&0X80) && Retry--); //Wait for the return of non-0XFF data 
 //Return status value
    return r1;
}
/*******************************************************************************
* Function name: SD_GetCID
* Function description: Get the CID information of the SD card, including the manufacturer information
* Entry parameter: cid_data (memory to store CID, at least 16Byte
* Return parameter: 0: Success Others: Failure
* Remarks: For details of the CID register, please refer to the SD Protocol Manual V2.0 (2006)
*******************************************************************************/
u8 SD_GetCID(u8 *cid_data)
{
    u8 r1;    
    //Send CMD10 command, read CID
    r1=SD_SendCmd(CMD10,0,0x01);
    if(r1==0x00)
 {
  r1=SD_RecvData(cid_data,16);//Receive 16 bytes of data  
    }
 SD_DisSelect();//Cancel chip selectionif
 (r1)return 1;
 else return 0;
}
/***************************************************************************
* Function name: SD_GetCSD
* Function description: Get the CSD information of the SD card, including capacity and speed information
* Entry parameter: cid_data (memory to store CSD, at least 16Byte
* Return parameter: 0: Success Others: Failure
* Remarks: For details of the CSD register, please refer to the SD Protocol Manual V2.0 (2006)
*******************************************************************************/
u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;  
    r1=SD_SendCmd(CMD9,0,0x01);//Send CMD9 command, read CSD 
    if(r1==0)
 {
     r1=SD_RecvData(csd_data,16);//Receive 16 bytes of data 
    }
 SD_DisSelect();//Cancel chip selection
 if(r1)return 1;
 else return 0;

/********************************************************************************
* Function name: SD_GetSectorCount
* Function description: Get the total number of sectors of the SD card (number of sectors
* Input parameter: cid_data (memory for storing CSD, at least 16Byte
* Return parameter: 0: Error in getting capacity Others: SD card sector number value
* Remarks: Calculation formula for SD card capacity SD Protocol Manual V2.0 (2006)
*******************************************************************************/
u32 SD_GetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity;  
    u8 n;
 u16 csize;           
 //Get CSD information, if an error occurs during the process, return 0 
    if(SD_GetCSD(csd)!=0) return 0; //Failed to get capacity   
    //If it is an SDHC card, calculate as follows
    if((csd[0]&0xC0)==0x40) //V2.00 card
    { 
  csize = csd[9] + ((u16)csd[8] << 8) + 1;
  Capacity = (u32)csize << 10; //Get the number of sectors       
    }
 else //V1.XX card
    { 
  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);//Get the number of sectors   
    }
    return Capacity;
}
/*******************************************************************************
* Function name: SD_ReadDisk
* Function description: Read SD card
* Entry parameters: buf: data buffer sector: address to be read cnt: number of sectors to be read 
* Return parameters: 0: success Others: failure
* Remarks: 1. The address to be read must be the beginning of a sector
     2. It must be SD2.0 card, other cards are not processed
***************************************************************************/
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
 u8 r1;
 if(cnt==1)
 {
  r1=SD_SendCmd(CMD17,sector,0X01);//Read commandif
  (r1==0)//Command sent successfully
  {
   r1=SD_RecvData(buf,512);//receive 512 bytes    
  }
 }
 else
 {
  r1=SD_SendCmd(CMD18,sector,0X01);//continuous read commanddo
  {
  r1
   =SD_RecvData(buf,512);//receive 512 bytesbuf  
   +=512;  
  }while(--cnt && r1==0);  
  SD_SendCmd(CMD12,0,0X01); //send stop command
 }   
 SD_DisSelect();//cancel chip selectreturn
 r1;//
}
/***********************************************************************************
* Function name: SD_WriteDisk
* Function description: write SD card
* Entry parameter: buf: data buffer sector: address to be written cnt: number of sectors to be written 
* Return parameter: 0: success Others: failure
* Remarks: 1. The address to be written must be the beginning of a sector
     2. It must be an SD2.0 card, other cards are not processed
******************************************************************************/
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
 u8 r1;
 if(cnt==1)
 {
  r1=SD_SendCmd(CMD24,sector,0X01);//Single sector write command
  if(r1==0)//Command sent successfully
  {
   r1=SD_SendBlock(buf,0xFE);//Write 512 bytes    
  }
 }
 else
 {
  if(SD_Type!=SD_TYPE_MMC)
  {
   SD_SendCmd(CMD55,0,0X01); 
   SD_SendCmd(CMD23,cnt,0X01);//Send the number of sectors to be written, this command is used to pre-erase all sectors to be written 
  }
   r1=SD_SendCmd(CMD25,sector,0X01);//Continuous write command, send the starting address
  if(r1==0)
  {
   do
   {
    r1=SD_SendBlock(buf,0xFC);//Send 512 bytes  
    buf+=512;  
   }while(--cnt && r1==0);
   r1=SD_SendBlock(0,0xFD);//Send stop bit
  }
 }   
 SD_DisSelect();//Cancel chip selectreturn
 r1;//
}
/*******************************************************************************
* Function name: SD_Initialize
* Function description: Write SD card
* Entry parameter: None 
* Return parameter: 0: Success Others: Failure
* Remarks: 1. The address to be written must be the beginning of a sector
     2. It must be an SD2.0 card, other cards are not processed
***************************************************************************/
u8 SD_Initialize(void)
{
    u8 r1; // Store the return value of SD cardu16
    retry; // Used for timeout counting
    u8 buf[4];  
 u16 i;

 SPI_SD_Init(); //Initialize IO
  SD_SPI_SpeedLow(); //Set to low speed mode    
 for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//Send at least 74 pulses, keep the chip select line high at this time
 retry=20;
 do
 {
  r1=SD_SendCmd(CMD0,0,0x95);//Enter reset and select SPI mode at the same time (CSN is low when sending CMD0)
 }while((r1!=0X01) && retry--);
  SD_Type=0;//Default no cardif
 (r1==0X01)
 {
  if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//Use the V2.0 version SD card special command CMD8 to check whether it is a 2.0 card
  {
   for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
   if(buf[2]==0X01&&buf[3]==0XAA)//Does the card support 2.7~3.6V
   {
    retry=0XFFFE;
    do
    {
     SD_SendCmd(CMD55,0,0X01); //Send CMD55
     r1=SD_SendCmd(CMD41,0x40000000,0X01);//Send CMD41
    }while(r1&&retry--);
    if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//Identify the SD2.0 card version, read the OCR value
    {
     for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//get OCR valueif
     (buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //check CCS (bit 30)
     else SD_Type=SD_TYPE_V2;   
    }
   }
  }
  else//if it is not a 2.0 card, check whether it is a 1.0 card or MMC card
  {
   SD_SendCmd(CMD55,0,0X01); //send CMD55
   r1=SD_SendCmd(CMD41,0,0X01); //send CMD41
   if(r1<=1)//send CMD55 and CMD41 successfully, indicating that this is a 1.0 card
   {  
    SD_Type=SD_TYPE_V1;
    retry=0XFFFE;
    do //wait to exit IDLE mode
    {
     SD_SendCmd(CMD55,0,0X01); //Send CMD55
     r1=SD_SendCmd(CMD41,0,0X01); //Send CMD41 for initialization
    }while(r1&&retry--);
   }
   else //If it is not a 1.0 card, consider it to be an MMC card
   {
    SD_Type=SD_TYPE_MMC; //Assume it is an MMC card first
    retry=0XFFFE;
    do //Wait to exit IDLE mode
    {               
     r1=SD_SendCmd(CMD1,0,0X01); //Send CMD1 and use the reset function to determine whether it is an MMC card
    }while(r1&&retry--); //Send reset command. Reset fails if timeout 
   }
   if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR; //MMC card reset failed
  }
 }
 SD_DisSelect();//Cancel chip selection
 SD_SPI_SpeedHigh();//High speed
 if(SD_Type)return 0; //Initialization successful
 else if(r1)return r1; //Initialization failed    
 return 0xaa;//Other errors
}

 


Keywords:STM32 Reference address:Simple SD card reading and writing for STM32

Previous article:STM32 simulates IIC reading and writing AT24CXX
Next article:How to use STM32 firmware library V3.5 in Keil MDK environment

Recommended ReadingLatest update time:2024-11-16 18:09

stm32 HardFault_Handler exception handling crash
When developing the system, the HardFault_Handler hardware exception occurs, that is, the system crashes. Especially for a system that calls the OS, the program volume is large, and the stack overflow and array overflow detection are detected. After searching for a long time and finding nothing, I probably want to die
[Microcontroller]
STM32 IIC Detailed Explanation: STM32 IIC Slave Mode (Interrupt Mode to Send and Receive Data)
1. Introduction to IIC This part of the content will be used in the second section of the code. For IIC, the slave cannot actively send data, and the start conditions are all generated by the host.  1.1、Host sends data process   1) When the host detects that the bus is in the "idle state" (that is, the SDA and S
[Microcontroller]
[STM32] DMA basic principles, registers, library functions (DMA general steps)
STM32F1xx official information: "STM32 Chinese Reference Manual V10" - Chapter 10 DMA Controller Basic introduction to DMA Basic definition of DMA DMA, the full name of which is Direct Memory Access, is direct memory access. DMA transfer copies data from one address space to another, providing high-speed data tr
[Microcontroller]
[STM32] DMA basic principles, registers, library functions (DMA general steps)
Brief Analysis of CMSIS Files of STM32 Firmware Library V3.3.0
The STM32 V3.3.0 library contains a folder called CMSIS, which is the software interface standard for arm Cortex microcontrollers. Now I will make a brief analysis of my actual work:      1. Select the startup file: Select the correct startup file according to the chip model you are using. This is based on the divisio
[Microcontroller]
STM32 serial port receives character string and controls LED
Serial port related configuration GPIO_InitTypeDef GPIO_InitStructure;     USART_InitTypeDef USART_InitStructure;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    GPIO_InitStru
[Microcontroller]
STM32 serial port receives character string and controls LED
stm32 controls mpu9250 nine-axis sensor
1. Hardware  mpu mpu9250  and add a new DMP folder  2. Halib  no  3.          Remember to define the settings and shield some codes, otherwise errors will be reported. At the same time, the baud rate of the host computer should be set and data verification should be turned off.  4. Main #include "mpu.h"#include "mpu9
[Microcontroller]
stm32 controls mpu9250 nine-axis sensor
Using STM32 general-purpose timer to realize output of two complementary PWM with adjustable duty cycle and frequency
MCU:STM32F334C8T6 PWM, or pulse width modulation, can be used to drive motors, full-bridge circuits, etc. Those who have used STM32 know that its timer can easily achieve PWM output, and the advanced timer's TIMx_CHy and TIMx_CHyN can easily achieve the output of complementary PWM waveforms. Advanced timer resourc
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
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号