STM32的I2C-EEPROM已调试成功

发布者:科技火箭最新更新时间:2016-09-26 来源: eefocus关键字:STM32  I2C  EEPROM 手机看文章 扫描二维码
随时随地手机看文章

万利的I2C-EEPROM例程有些问题,经本人两个昼夜的反复试验,已修改完善。

修改了两个地方,在void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)写操作函数和void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)读操作函数体内的开头先要执行一句I2C_EE_WaitEepromStandbyState();

这样在以后调用写操作函数和读操作函数时就不用执行I2C_EE_WaitEepromStandbyState()了。但上电复位后先要执行一次读操作,以后就可以无限制的随便调用这两个函数了。

详细如下。

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "i2c_ee.h"
#include"delay.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define I2C_Speed              10000
#define I2C1_SLAVE_ADDRESS7    0xA0

#define I2C_PageSize           4


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u16 EEPROM_ADDRESS;

/* Private function prototypes -----------------------------------------------*/

void I2C_Configuration(void);


/*******************************************************************************
* Function Name : I2C_Configuration
* Description    : I2C Configuration
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; 
I2C_InitTypeDef I2C_InitStructure;

/* Configure I2C1 pins: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//设置 I2C为 I2C模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速模式 Tlow / Thigh = 2
    
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;//设置第一个设备地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//应答 7位地址
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//设置时钟频率
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);//使能I2C外设
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStructure);
}

/*******************************************************************************
* Function Name : I2C_EE_Init
* Description    : Initializes peripherals used by the I2C EEPROM driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_Init()
{
/* I2C configuration */
I2C_Configuration();

/* depending on the EEPROM Address selected in the i2c_ee.h file */
#ifdef EEPROM_Block0_ADDRESS
/* Select the EEPROM Block0 to write on */
EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;
#endif
#ifdef EEPROM_Block1_ADDRESS
/* Select the EEPROM Block1 to write on */
EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;
#endif
#ifdef EEPROM_Block2_ADDRESS
/* Select the EEPROM Block2 to write on */
EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;
#endif
#ifdef EEPROM_Block3_ADDRESS
/* Select the EEPROM Block3 to write on */
EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;
#endif
}

/*******************************************************************************
* Function Name : I2C_EE_BufferWrite
* Description    : Writes buffer of data to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
NumByteToWrite:写入的字节数
*******************************************************************************/
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)//将缓冲器的数据写入EEPROM
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

Addr = WriteAddr % I2C_PageSize;//写入地址是每页的第几位
count = I2C_PageSize - Addr;//在开始的一页要写入的个数
NumOfPage = NumByteToWrite / I2C_PageSize;//要写入的页数
NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一页的个数
I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
/* If WriteAddr is I2C_PageSize aligned */
if(Addr == 0) //写入地址是页的开始
{
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0) //数据小于一页
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
      I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
    }
    /* If NumByteToWrite > I2C_PageSize */
    else //数据大于等于一页
    {
      while(NumOfPage--)//要写入的页数
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //写一页的数据
    I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize;
      }

      if(NumOfSingle!=0)//剩余数据小于一页
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
      }
    }
}
/* If WriteAddr is not I2C_PageSize aligned */
else //写入地址不是页的开始
{
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0) //数据小于一页
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
      I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
    }
    /* If NumByteToWrite > I2C_PageSize */
    else//数据大于等于一页
    {
      NumByteToWrite -= count;
      NumOfPage = NumByteToWrite / I2C_PageSize; //重新计算要写入的页数
      NumOfSingle = NumByteToWrite % I2C_PageSize;//重新计算不足一页的个数
      
      if(count != 0)//在此处count一定不为0,此判断条件好象有点多余
      { 
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);//将开始的空间写满一页
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += count;
        pBuffer += count;
      } 
      
      while(NumOfPage--)//要写入的页数
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);//写一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize; 
      }
      if(NumOfSingle != 0)//剩余数据小于一页
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //写少于一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
      }
    }
}
}

/*******************************************************************************
* Function Name : I2C_EE_ByteWrite
* Description    : Writes one byte to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
*******************************************************************************/
void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)//写一个字节到EEPROM
{
/* Send STRAT condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件

/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件

/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
      
/* Send the EEPROM's internal address to write to */
I2C_SendData(I2C1, WriteAddr);//通过外设 I2Cx发送地址
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件

/* Send the byte to be written */
I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据
   
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
/* Send STOP condition */
I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
}

/*******************************************************************************
* Function Name : I2C_EE_PageWrite
* Description    : Writes more than one byte to the EEPROM with a single WRITE
*                  cycle. The number of byte can't exceed the EEPROM page size.
* Input          : - pBuffer : pointer to the buffer containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
NumByteToWrite:写入的字节数
*******************************************************************************/
void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)//写少于一页的数据
{
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向

/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查最近一次 I2C事件是否是输入的事件

/* Send the EEPROM's internal address to write to */    
I2C_SendData(I2C1, WriteAddr); //通过外设 I2Cx发送地址

/* Test on EV8 and clear it */
while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //检查最近一次 I2C事件是否是输入的事件

/* While there is data to be written */
while(NumByteToWrite--) 
{
    /* Send the current byte */
    I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据

    /* Point to the next byte to be written */
    pBuffer++; 
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
}

/* Send STOP condition */
I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
}

/*******************************************************************************
* Function Name : I2C_EE_BufferRead
* Description    : Reads a block of data from the EEPROM.
* Input          : - pBuffer : pointer to the buffer that receives the data read 
*                    from the EEPROM.
*                  - ReadAddr : EEPROM's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要保存读出数据的数组的指针
ReadAddr:24c02中要读出数据的首地址
NumByteToRead:读出的字节数
*******************************************************************************/
void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//将EEPROM的数据读入缓冲器

I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件
/* In the case of a single data transfer disable ACK before reading the data */
if(NumByteToRead==1) 
{
    I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
}
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向

/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
/* Clear EV6 by setting again the PE bit */
I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外设

/* Send the EEPROM's internal address to write to */
I2C_SendData(I2C1, ReadAddr); //通过外设 I2Cx发送地址

/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
/* Send STRAT condition a second time */ 
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件
/* Send EEPROM address for read */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的从 I2C设备传送地址字,选择接收方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
/* While there is data to be read */
while(NumByteToRead) 
{
    /* Test on EV7 and clear it */
    if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检查最近一次 I2C事件是否是输入的事件
    {
      if(NumByteToRead == 2)
      {
        /* Disable Acknowledgement */
        I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
      }

      if(NumByteToRead == 1)
      {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
      }
      
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData(I2C1);//返回通过 I2Cx最近接收的数据

      /* Point to the next location where the byte read will be saved */
      pBuffer++; 
      
      /* Decrement the read bytes counter */
      NumByteToRead--;    
    }   
}

/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的应答功能
}

/*******************************************************************************
* Function Name : I2C_EE_WaitEepromStandbyState
* Description    : Wait for EEPROM Standby state
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_WaitEepromStandbyState(void) //EEPROM设为待命状态     
{
vu16 SR1_Tmp = 0;

do
{
    /* Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
    /* Read I2C1 SR1 register */
    SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);//读取指定的 I2C寄存器 I2C_SR1 并返回其值
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字 ,选择发送方向
}while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//地址发送结束
/* Clear AF flag */
I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清除 I2Cx的应答错误标志位


关键字:STM32  I2C  EEPROM 引用地址:STM32的I2C-EEPROM已调试成功

上一篇:STM32的串口通信
下一篇:STM32的AD输入口存在电压的问题--连续转换模式

推荐阅读最新更新时间:2024-03-16 15:12

STM32待机模式测试
环境: 主机:XP 开发环境:MDK4.10 单片机:STM32F103C8 功能: 开启RTC闹钟,然后进入待机模式,用闹钟唤醒后退出. 说明: 1.RTC闹钟唤醒事件发生时,同时进入闹钟中断,必须在初始化时与外部中断线17关联 2.如果仅想退出待机模式,RTC闹钟事件已经足够,不必与外部中断线17关联 3.退出待机模式后,接下来的流程类似于按下复位按键,程序会从头开始执行 源代码: 初始化时钟,配置时钟为内部时钟LSI,配置RTC闹钟唤醒以及外部中断线17 void RTC_Configuration(void) { //定义中断结构体 NVIC_InitTypeDef NVIC_
[单片机]
STM32片外内存的使用
1、STM32分为片上内存和片外内存。 (1)片上内存 用于任务栈,变量等。 (2)片外内存 一般编程人员会自己写内存管理方便的函数。例如通过总线挂载一个16M的内存,地址0x68000000。用户可以管理一个指针,通过移动指针来管理这块内存。 包括分配和释放。 typedef struct { WORD wFlag; WORD wLen; }TReserveSramInfo; //静态RAM操作 typedef struct { int totalLen; int startPos; int curLen; }STATICRAMINFO; STATIC
[单片机]
STM32PWM输出实现LED灯渐亮渐灭
/* *说明: *PA0:KEY1;PA1:KEY2; *PA2:LED1;PA3:LED2; *PA9:USART1_TX;PA10:USART1_RX */ #include stm32f10x.h #include stm32f10x_rcc.h #include stm32f10x_gpio.h #include stm32f10x_tim.h #include stm32f10x_pwr.h #include stm32f10x_exti.h #include system_stm32f10x.h #include misc.h void R
[单片机]
stm32专题三十六:MDK编译过程和文件类型(二)
MDK工程的文件类型: 1 下图为 Project 目录下的工程文件 实际上,只需要有 unprojx 文件,就可以恢复整个工程。 具体描述: 2 源文件 3 output 和 list 文件 详细分析: 1 uvprojx 文件 uvprojx 文件就是我们平时双击打开的工程文件,它记录了整个工程的结构,如芯片类型、工程包含了哪些源文件等内容。 可以使用vscode直接打开 uvprojx ,来看一下里面的具体内容: 2 uvoptx 文件 uvoptx 文件记录了工程的配置选项,如下载器的类型、变量跟踪配置、断点位置以及当前已打开的文件等。 我们在程序 main.c 的第81行
[单片机]
<font color='red'>stm32</font>专题三十六:MDK编译过程和文件类型(二)
STM32 无法使用IAR下载程序问题
一开始建立了工程,然后程序下载都很正常。不知道什么情况自己下载代码之后,再重新下载代码无法成功。 我按照提示找了一下FlashStm32f30x8.flash这个文件,却发现IAR的目录下没并没有。又怀疑是IAR文件丢失。 重新安装IAR,却发现问题仍然继续. ~~~~感觉像是芯片坏了~~~ 于是通过STVP工具,读取一下。 奇迹发生了,竟然可以读取程序。 嗯~~那可以排除芯片的问题。 好吧,那我重新用IAR下载应该可以吧。 于是重新下载程序, 晕~~~居然还是弹出那个错误。 难道自己的程序竟然会引起这样的错误??? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 于是通过STVP将
[单片机]
<font color='red'>STM32</font> 无法使用IAR下载程序问题
stm32 --- 灵活的静态存储器控制器FSMC
所有的外部存储器共享控制器输出的地址、数据和控制信号,每个外部设备可以通过一个唯一的片选信号加以区分。FSMC在任一时刻只访问一个外部设备。 具有静态存储器接口的器件包括: 1. 静态随机存储器(SRAM) 2. 只读存储器(ROM) 3. NOR闪存 4. PSRAM(4个存储器块)。可以外部扩展存储器。 FSMC模块挂载在AHB总线上。至于RD,WE,RS,CS信号都已经是FSMC控制器自动产生的,在操作中不用管这些信号的变化。 从FSMC的角度看,可以把外部存储器划分为固定大小为256M字节的四个存储块,见下图。 ● 存储块1用于访问最多4个NOR闪存或PSRAM存储设备。这个存储区被划分为4个NOR
[单片机]
stm32嵌入式操作系统具有怎样的优缺点
  STM32简单介绍   一、背景   如果你正为项目的处理器而进行艰难的选择:一方面抱怨16位单片机有限的指令和性能,另一方面又抱怨32位处理器的高成本和高功耗,那么,基于 ARM Cortex-M3内核的STM32系列处理器也许能帮你解决这个问题。使你不必在性能、成本、功耗等因素之间做出取舍和折衷。   即使你还没有看完STM32的产品手册,但对于这样一款融合ARM和ST技术的“新生儿”相信你和我一样不会担心这款针对16位MCU应用领域 的32位处理器的性能,但是从工程的角度来讲,除了芯片本身的性能和成本之外,你或许还会考虑到开发工具的成本和广泛度;存储器的种类、规模、性能和容 量;以及各种软件获得的难易,我相信你看完本
[单片机]
<font color='red'>stm32</font>嵌入式操作系统具有怎样的优缺点
基于STM32的铁路自动围栏系统设计
一、项目背景 随着城市规模的不断扩大和交通运输方式的日益发展,铁路与公路的交叉口已经成为常见的场景。然而,这些交叉口往往存在一定的安全隐患,因为有时不易发现列车行进的情况,导致公路上的车辆或行人可能会无意中闯入铁路区域,从而引发重大交通事故。 为了解决这个问题,当前开发了一款基于 STM32 的铁路自动围栏系统。该系统采用了STM32F103RCT6作为主控 芯片 ,并使用 步进电机 来控制铁路围栏的开启和闭合。同时,系统还配备了 红外 感应器,以便能够及时监测到列车的通过情况。 当系统监测到有列车即将通过铁路交叉口时,公路 信号 灯会立刻变为红灯,蜂鸣器也会发出警报声音,以提醒行人和车辆注意安全。同时,铁路两侧的围栏也会自动
[单片机]
基于<font color='red'>STM32</font>的铁路自动围栏系统设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved