2018-08-22总线I2C的驱动FM24CL64,亲测好用

//#include "../user/main.h"

include "stm32f4xx.h"

include "stm32f4xx_conf.h"

//#include "common.h"

define I2CSUCCESS 0

define I2CERROR 1

/* I2C PORT Define */

define GPIO_PORT_I2C (GPIOH)

define RCC_I2C_PORT (RCC_AHB1Periph_GPIOH)

define I2C_SCL_PIN (GPIO_Pin_7)

define I2C_SDA_PIN (GPIO_Pin_8)

/* I2C Line State Define /
/
Using Function */

define I2C_SCL_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 1 */

define I2C_SCL_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 0 */

define I2C_SDA_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 1 */

define I2C_SDA_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 0 */

define I2C_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN) /* Read SDA State */

///////////////////////////////////////////////////////////////////////////////////////

/* I2C PORT Define */

define GPIO_PORT_FM (GPIOH)

define RCC_FM_PORT (RCC_AHB1Periph_GPIOH)

define FM_SCL_PIN (GPIO_Pin_7)

define FM_SDA_PIN (GPIO_Pin_8)

/* I2C Line State Define /
/
Using Function */

define FM_SCL_1() GPIO_SetBits(GPIO_PORT_FM, I2C_FM_PIN) /* SCL = 1 */

define FM_SCL_0() GPIO_ResetBits(GPIO_PORT_FM, FM_SCL_PIN) /* SCL = 0 */

define FM_SDA_1() GPIO_SetBits(GPIO_PORT_FM, FM_SDA_PIN) /* SDA = 1 */

define FM_SDA_0() GPIO_ResetBits(GPIO_PORT_FM, FM_SDA_PIN) /* SDA = 0 */

define FM_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_FM, FM_SDA_PIN) /* Read SDA State */

/////////////////////////////////////////////////////////////////////////////////////////////////

/* I2C PORT Define */

define GPIO_PORT_DB (GPIOH)

define RCC_DB_PORT (RCC_AHB1Periph_GPIOH)

define DB_SCL_PIN (GPIO_Pin_10)

define DB_SDA_PIN (GPIO_Pin_11)

/* I2C Line State Define /
/
Using Function */

define DB_SCL_1() GPIO_SetBits(GPIO_PORT_DB, DB_SCL_PIN) /* SCL = 1 */

define DB_SCL_0() GPIO_ResetBits(GPIO_PORT_DB, DB_SCL_PIN) /* SCL = 0 */

define DB_SDA_1() GPIO_SetBits(GPIO_PORT_DB, DB_SDA_PIN) /* SDA = 1 */

define DB_SDA_0() GPIO_ResetBits(GPIO_PORT_DB, DB_SDA_PIN) /* SDA = 0 */

define DB_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_DB, DB_SDA_PIN) /* Read SDA State */

///////////////////////////////////////////////////////////////////////////////////////////////////

/* I2C PORT Define */

define GPIO_PORT_RX8025 (GPIOH)

define RCC_RX8025_PORT (RCC_AHB1Periph_GPIOH)

define RX8025_SCL_PIN (GPIO_Pin_10)

define RX8025_SDA_PIN (GPIO_Pin_11)

/* I2C Line State Define /
/
Using Function */

define RX8025_SCL_ON() GPIO_SetBits(GPIO_PORT_RX8025, RX8025_SCL_PIN)

define RX8025_SCL_OFF() GPIO_ResetBits(GPIO_PORT_RX8025, RX8025_SCL_PIN)

define RX8025_SDA_ON() GPIO_SetBits(GPIO_PORT_RX8025, RX8025_SDA_PIN)

define RX8025_SDA_OFF() GPIO_ResetBits(GPIO_PORT_RX8025, RX8025_SDA_PIN)

define RX8025_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_RX8025, RX8025_SDA_PIN) /* Read SDA State */

///////////////////////////////////////////////////////////////////////////////

/* EEPROM Define */

define EE_DEV_ADDR (0xa0) /* Device Address */

define EE_PAGESIZE (256) /* Page Size */

define EE_TOTALSIZE (8192) /* Total Capacity */

define I2C_WR (0) /* Write Control Bit */

define I2C_RD (1) /* Read Control Bit */

define I2CACK (0) /* ACK Response */

define I2CNAK (1) /* NAK Response */

uint8_t Ack2,Ack21;
uint8_t StateFlag8025;
void Rx8025_rdnbyt(unsigned int SLA,unsigned int dev_addr,unsigned char *pnt11,unsigned int length);
struct
{
unsigned int millisecond;
unsigned char s;
unsigned char min;
unsigned char hour;
unsigned char day;
unsigned char mouth;
unsigned int year;
}daly;

unsigned char timetest[7];
unsigned char Data11[7];
unsigned char RtcRstFlag;

/* main.c */
extern void Delayus(uint16_t us);
extern void Delayms(uint16_t ms);

////////////////////////////////
//////////////////////////////////////
typedef enum{FALSE = 0, TRUE = !FALSE} bool;
/////////////////////////////////////////////////
///////////////////////////////////////////////////////////
uint16_t safecode = 0;
//#define GPIO_PORT_I2C (GPIOH)
//#define RCC_I2C_PORT (RCC_AHB1Periph_GPIOH)

define SCLK64 (GPIO_Pin_7)

define SDA64 (GPIO_Pin_8)

define sck_on64() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN); /* SCL = 1 */

define sck_off64() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN); /* SCL = 0 */

define sda_on64() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN); /* SDA = 1 */

define sda_off64() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN); /* SDA = 0 */

define ISSDA64() (GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN)) /* Read SDA State*/

define SDA_IN64() {sda_on64();}//{GPIOD->CRL&=0XFFFFF0FF;GPIOD->CRL|=0XFFFFF8FF;}

define SDA_OUT64() {sda_off64();}//{GPIOD->CRL&=0XFFFFF0FF;GPIOD->CRL|=0X00000300;}

define EP_start 0x00 /* E2ROM???? */

define EP_config_size sizeof(config_sys) /* ????????? */

define EP_tab_start sizeof(config_sys) /* ?????????? */

define EP_tab_size sizeof(table_alr) /* ?????????? */

define EP_crc_start (sizeof(config_sys)+sizeof(table_alr)) /* ??????????? */

define EP_crc_size sizeof(table_check) /* ????????????*/

define EP_cail_start (EP_crc_start+sizeof(table_check)) /* ???????? */

define EP_cail_size sizeof(cali_chn) /* ?????????? */

define EP_idle_start (EP_cail_start+EP_cail_size)

define EP_idle_size 200

define s_offset (200+EP_idle_start)

define CT_ADD (4+EP_idle_start)

extern void init_pass(void);
extern void cali_init(void);
extern void init_uart(void);
extern void init_chn(void);
extern bool WriteCali(unsigned char area);
extern bool WriteConfig(unsigned char area);

/********************************************************************************************************/
/* E2ROM?????? /
/
??? /
/********************************************************************************************************/
void new_64Start(void)
{
sda_on64()
sck_on64()
Delayus(320);
sda_off64()
Delayus(320);
sck_off64()
}
/********************************************************************************************************/
/
E2ROM?????? /
/
??? /
/********************************************************************************************************/
void new_64Stop(void)
{
sda_off64()
Delayus(320);
sck_on64()
Delayus(320);
sda_on64()
Delayus(320);
}
/********************************************************************************************************/
/
E2ROM????? /
/
??? /
/********************************************************************************************************/
void new_64_Mack(void)
{
sda_off64()
Delayus(320);
sck_on64()
Delayus(320);
sck_off64()
}
/********************************************************************************************************/
/
E2ROM??????? /
/
??? /
/********************************************************************************************************/
void new_64_MNack(void)
{
sda_on64()
Delayus(320);
sck_on64()
Delayus(320);
sck_off64()
}
/********************************************************************************************************/
/
E2ROM?????? /
/
??? /
/
?? 0 ???? /
/
?? 1 ???? /
/********************************************************************************************************/
unsigned char new_64_Ackn(void)
{
unsigned char StateFlag;
sda_off64()
SDA_IN64() /
??SDA??? /
Delayus(320);
sck_on64()
Delayus(320);
StateFlag=0; /
????? ????=0 /
if(ISSDA64()) StateFlag=1;
sck_off64()
SDA_OUT64() /
??SDA??? /
return StateFlag;
}
/********************************************************************************************************/
/
E2ROM????? /
/
??? /
/
?????????? /
/********************************************************************************************************/
unsigned char new_64ReceiveByte(void)
{
unsigned char i;
unsigned char Rbyte=0x00;
SDA_IN64() /
??SDA??? /
for(i=0;i<8;i++){
Rbyte<<=1;
sck_on64()
Delayus(320);
if(ISSDA64()) Rbyte+=1;
sck_off64()
Delayus(320);
}
SDA_OUT64() /
??SDA??? /
return Rbyte;
}
/********************************************************************************************************/
/
E2ROM????? /
/
?? Wbyte:???? /
/********************************************************************************************************/
void new_64SentByte(unsigned char Wbyte)
{
unsigned char i;
for(i=0;i<8;i++){
if(Wbyte&0x80) sda_on64()
else sda_off64()
Wbyte<<=1;
sck_on64()
Delayus(320);
sck_off64()
Delayus(320);
}
}
/********************************************************************************************************/
/
E2ROM??? /
/
?? SLA:??AS4?,0xa2?64;0xa0?02 /
/
?? ADDR:?????? /
/
*pnt??????? /
/
length ??????? /
/********************************************************************************************************/
bool new_64WritePageChar(unsigned char SLA,unsigned short ADDR,unsigned char pnt,unsigned short length)
{
unsigned short i;
unsigned char j;
unsigned char len;
unsigned short temp_len;
unsigned char temp_pch;
unsigned short temp_int;
unsigned char P_Len;
if(safecode !=0x1234)
return FALSE;
P_Len = 32;
temp_len = length;
temp_pch = pnt;
temp_int = ADDR;
j = 0;
len = ADDR%32;
len = 32 -len;
len = len>length?length:len;
do {
new_64Start();
new_64SentByte(SLA);
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(ADDR>>8));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(ADDR));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
if(j)len=length>P_Len?P_Len:length; /
????????,?????pnt? /
for(i=0;i<len;i++){
new_64SentByte(
pnt);
new_64_Ackn();
pnt++;
}
length-=len;
if(length) {
new_64Stop(); /
???????6ms /
Delayus(2);
ADDR+=len;
}
j++;
}while(length); /
?????,????????? /
new_64Stop(); /
2010 9 21 ?????? /
Delayus(2);
new_64Start();
new_64SentByte(SLA);
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(temp_int>>8));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(temp_int));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64Start(); /
start condition /
new_64SentByte(SLA|0x01); /
write slave address to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
for(i=0;i<temp_len;i++){
if(
temp_pch!=new_64ReceiveByte()){new_64Stop(); return FALSE;}
if(i==(temp_len-1)) new_64_MNack(); /
send no ack /
else new_64_Mack(); /
send ack /
temp_pch++;
}
new_64Stop();
safecode =0;
return TRUE;
}
/********************************************************************************************************/
/
E2ROM??? /
/
?? ADDR:?????? /
/
pnt??????? /
/
length??????? /
/********************************************************************************************************/
bool new_64SDREAD_Char(unsigned char SLA,unsigned int Addr,unsigned char pnt,unsigned short length)
{
unsigned short i=0;
new_64Start(); /
start condition /
new_64SentByte(SLA); /
write slave address to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(Addr>>8)); /
write operate address MSB to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)Addr); /
write operate address LSB to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64Start(); /
start condition /
new_64SentByte(SLA|0x01); /
write slave address to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
for(i=0;i<length;i++){
pnt=new_64ReceiveByte();
if(i==(length-1)) new_64_MNack(); /
send no ack /
else new_64_Mack(); /
send ack /
pnt++;
}
new_64Stop();
return TRUE;
}
/********************************************************************************************************/
/
E2ROM??? /
/
?? SLA:??AS4?,0xa2?64;0xa0?02 /
/
?? ADDR:?????? /
/
pnt??????? /
/
length ??????? /
/********************************************************************************************************/
bool new_64_WrFMwordNByte(const unsigned char SLA, unsigned short Addr,unsigned short pnt,unsigned short length)
{
unsigned short i=0;
unsigned char j=0;
unsigned char dd,dd1;
unsigned char len;
unsigned short temp_len;
unsigned short temp_pint;
unsigned short temp_int;
unsigned char P_Len;
P_Len = 32;
dd=dd1=0;
temp_len = length;
temp_pint = pnt ;
temp_int = Addr;
len = Addr%32;
len = 32 -len;
len = len>length?length:len;
if(safecode==0x1234){
do {
new_64Start();
new_64SentByte(SLA);
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(Addr>>8));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(Addr));
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
if(j)len=(length>P_Len?P_Len:length);
for(i=0;i<len;i++){
if(dd==0){
dd = 1;
new_64SentByte((
pnt));
new_64_Ackn();
}else{
dd =0;
new_64SentByte((
pnt)>>8);
new_64_Ackn();
pnt++;
}
}
length-=len;
if(length) {
new_64Stop(); /
2010 9 21 ??????6ms ?????? /
Delayus(1);
Addr+=len;
}
j++;
}while(length);
}
new_64Stop();
Delayus(1);
new_64Start(); /
start condition /
new_64SentByte(SLA); /
write slave address to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)(temp_int>>8)); /
write operate address MSB to eeprom
/
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64SentByte((unsigned char)temp_int); /
write operate address LSB to eeprom
/
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
new_64Start(); /
start condition /
new_64SentByte(SLA|0x01); /
write slave address to eeprom /
if(new_64_Ackn()) {new_64Stop(); return FALSE;}
temp_len/=2;
for(i=0;i<temp_len;i++){
dd = new_64ReceiveByte();
new_64_Mack(); /
send ack /
dd1 = new_64ReceiveByte();
if(i==(temp_len-1)) new_64_MNack(); /
send no ack /
else new_64_Mack(); /
send ack */
temp_int = ((int)dd1<<8)+(int)dd;
if(temp_int != temp_pint){new_64Stop(); return FALSE;}
dd=dd1=0;
temp_pint++;
}
new_64Stop();
return TRUE;
}
/
-------------------------------------------------------------

  • ?N??????? // ?????2??? // ??????
    -------------------------------------------------------------/
    bool new_64_RdFMwordNByte(unsigned char SLA,unsigned short Addr,unsigned short pnt,unsigned short length)
    {
    unsigned short i=0;
    unsigned char dd,dd1;
    new_64Start(); /
    start condition /
    new_64SentByte(SLA); /
    write slave address to eeprom /
    if(new_64_Ackn()) {new_64Stop(); return FALSE;}
    new_64SentByte((unsigned char)(Addr>>8)); /
    write operate address MSB to eeprom/
    if(new_64_Ackn()) {new_64Stop(); return FALSE;}
    new_64SentByte((unsigned char)Addr); /
    write operate address LSB to eeprom/
    if(new_64_Ackn()) {new_64Stop(); return FALSE;}
    new_64Start(); /
    start condition /
    new_64SentByte(SLA|0x01); /
    write slave address to eeprom /
    if(new_64_Ackn()) {new_64Stop(); return FALSE;}
    for(i=0;i<length;i++){
    dd=new_64ReceiveByte();
    new_64_Mack(); /
    send ack /
    i++;
    dd1=new_64ReceiveByte();
    if(i==(length-1)) new_64_MNack(); /
    send no ack /
    else new_64_Mack(); /
    send ack */
    pnt=((int)dd1<<8)+(int)dd;
    pnt++;
    }
    new_64Stop();
    return TRUE;
    }
    /********************************************************************************************************/
    /
    E2ROM??? /
    /
    ?? SLA:??AS4?,0xa2?64;0xa0?02 /
    /
    ?? ADDR:?????? /
    /
    *pnt??????? /
    /
    length ??????? */
    /********************************************************************************************************/
    bool clearall(void)
    {
    // safecode=0x1234;
    // cali_init();//???????
    // if(WriteCali(0)==FALSE){
    // if(WriteCali(0)==FALSE){
    // WriteCali(0);
    // }
    // }
    // init_pass();
    // init_uart();
    // init_chn();
    // if(WriteConfig(0)==FALSE){
    // if(WriteConfig(0)==FALSE){
    // WriteConfig(0);
    // }
    // }

// CTCheck[0]=19500;
// CTCheck[1]=19500;
// CTCheck[2]=19500;
// CTCheck[3]=19500;
// CTCheck[4]=30000;
// CTCheck[5]=30000;
// CTCheck[6]=30000;
// CTCheck[7]=30000;
// CTCheck[8]=0x07;
// safecode=0x1234;
// if(new_64_WrFMwordNByte(0xa0,CT_ADD,&CTCheck[0],18)==FALSE)
// {
// safecode=0x1234;
// if(new_64_WrFMwordNByte(0xa0,CT_ADD,&CTCheck[0],18)==FALSE)
// new_64_WrFMwordNByte(0xa0,CT_ADD,&CTCheck[0],18);

// }

// Delayus(2);
// return TRUE;
}
/*****************************************************************************/
/* ?FM24CL64???? /
/
?????? */
/*****************************************************************************/

void I2C_Delay(void)
{
uint8_t delayCount = 1;

while (delayCount--);
}

/*******************************************************************************************************/
/**

  • I2C Start.
  • @param none
  • @return none

*******************************************************************************************************/
void i2cStart(void)
{
/* SDA change HIGH to LOW, When SCL is HIGH */
I2C_SDA_1();
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
I2C_SDA_0();
I2C_Delay();
I2C_SCL_0();
I2C_Delay();
}

/*******************************************************************************************************/
/**

  • I2C Stop.
  • @param none
  • @return none

*******************************************************************************************************/
void i2cStop(void)
{
/* SDA change LOW to HIGH, When SCL is HIGH */
I2C_SDA_0();
I2C_SCL_0();
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
I2C_SDA_1();
I2C_Delay();
I2C_SCL_0();
I2C_Delay();
}

/*******************************************************************************************************/
/**

  • I2C Wait ACK(0).
  • @param none
  • @return uint8_t

*******************************************************************************************************/
uint8_t i2cWaitAck(void)
{
uint8_t status;

I2C_SCL_0(); /* Release SDA */
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
status = (I2CACK == I2C_SDA_READ()) ? I2CSUCCESS : I2CERROR;
I2C_SCL_0();
I2C_Delay();
return status;
}

/*******************************************************************************************************/
/**

  • I2C Send Byte.
  • @param uint8_t
  • @return none

*******************************************************************************************************/
void i2cSendByte(uint8_t _ucByte)
{
uint8_t i;

/* HIGH bit sent first */
for (i=0; i<8; i++)
{
I2C_SCL_0();
I2C_Delay();
if (_ucByte & 0x80)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}

  _ucByte <<= 1;
  I2C_Delay();
  I2C_SCL_1();
  I2C_Delay();

}
I2C_SCL_0();
i2cWaitAck();
}

/*******************************************************************************************************/
/**

  • I2C Read Byte.
  • @param none
  • @return uint8_t

*******************************************************************************************************/
uint8_t i2cReadByte(void)
{
uint8_t i;
uint8_t value = 0;

/* HIGH bit Gotten first */
for (i=0; i<8; i++)
{
value <<= 1;
I2C_SCL_0();
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
if (I2C_SDA_READ())
{
value = value | 0x01;
}
I2C_SCL_0();
I2C_Delay();
}

return value;
}

/*******************************************************************************************************/
/**

  • I2C Send ACK(0).
  • @param none
  • @return none

*******************************************************************************************************/
void i2cAck(void)
{
I2C_SCL_0();
I2C_SDA_0();
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
I2C_SCL_0();
I2C_Delay();
}

/*******************************************************************************************************/
/**

  • I2C Send NAK(1).
  • @param none
  • @return none

*******************************************************************************************************/
void i2cNAck(void)
{
I2C_SCL_0();
I2C_SDA_1();
I2C_Delay();
I2C_SCL_1();
I2C_Delay();
I2C_SCL_0();
I2C_Delay();
}

/*******************************************************************************************************/
/**

  • I2C Read Multiple Bytes.
  • @param uint8_t *: Pointer to buffer to store data
  • @param uint16_t: Adress to read
  • @param uint16_t: Size of bytes to read
  • @return uint8_t: Ack Response

*******************************************************************************************************/
uint8_t I2CReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint8_t slaveAddr, dataAddrLow, dataAddrHigh;

dataAddrHigh = _usAddress / EE_PAGESIZE;
dataAddrLow = _usAddress % EE_PAGESIZE;

slaveAddr = EE_DEV_ADDR;

/* Send START command */
i2cStart();

/* Send Device Address to Write */
i2cSendByte(slaveAddr);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

/* Send high data addrress */
i2cSendByte(dataAddrHigh);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

/* Send low data addrress */
i2cSendByte(dataAddrLow);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

/* Send START command */
i2cStart();

/* Send Device Address to Read */
i2cSendByte(slaveAddr+1);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

/* Read All data */
while (_usSize--)
{
*_pReadBuf++ = i2cReadByte();

  /* Send ACK, except the last one to send NAK */
  if (_usSize != 0)
  {
     i2cAck();
  }
  else
  {
     i2cNAck();
  }

}

/* Send STOP command */
i2cStop();

return (I2CSUCCESS);

I2CRFAIL:
/* Send STOP command */
i2cStop();

return (I2CERROR);
}

/*******************************************************************************************************/
/**

  • I2C Write Multiple Bytes.
  • @param uint8_t *: Pointer to buffer to write data
  • @param uint16_t: Adress to write
  • @param uint16_t: Size of bytes to write
  • @return uint8_t: Ack Response

*******************************************************************************************************/
uint8_t I2CWriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint8_t slaveAddr, dataAddrLow, dataAddrHigh;

dataAddrHigh = _usAddress / EE_PAGESIZE;
dataAddrLow = _usAddress % EE_PAGESIZE;

slaveAddr = EE_DEV_ADDR;

/* Send START command */
i2cStart();

/* Send Device Address to Read */
i2cSendByte(slaveAddr );
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CWFAIL;
}

/* Send high data addrress */
i2cSendByte(dataAddrHigh);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CWFAIL;
}

/* Send low data addrress */
i2cSendByte(dataAddrLow);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CWFAIL;
}

while (_usSize--)
{
/* Write Data /
i2cSendByte(
_pWriteBuf++);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CWFAIL;
}
}

/* Send STOP command */
i2cStop();

return (I2CSUCCESS);

I2CWFAIL:
/* Send STOP command */
i2cStop();

return (I2CERROR);
}

/*******************************************************************************************************/
/**

  • I2C Erase Chip.
  • @param none
  • @return uint8_t: Indicate I2C Operation Result

*******************************************************************************************************/
uint8_t I2CEraseChip(void)
{
uint16_t i;
uint8_t buf[EE_TOTALSIZE];

/* Fill buffer to 0xff */
for (i=0; i<EE_TOTALSIZE; i++)
{
buf[i] = 0xff;
}

/* Write to EEPROM */
return (I2CWriteBytes(buf, 0, EE_TOTALSIZE));
}

/*******************************************************************************************************/
/**

  • I2C GPIO Initialize.
  • @param none
  • @return none

*******************************************************************************************************/
void I2CInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);

/* Send STOP command */
i2cStop();
}

/*******************************************************************************************************/
/**

  • I2C Check Device.
  • @param none
  • @return uint8_t: Success(0/ACK), Error(!0/NAK)

*******************************************************************************************************/
uint8_t I2CCheckDevice(void)
{
uint8_t status;

/* Send START command */
i2cStart();

/* Send Device Address to Write */
i2cSendByte(EE_DEV_ADDR | I2C_WR);
status = i2cWaitAck();

/* Send STOP command */
i2cStop();

return status;
}
/*******************************************************************************************************/
/** @} */

/*******************************************************************************************************************/
/* RX8025???? */
/*******************************************************************************************************************/
/***************************************************************************************************************/
/************** RX8025A???? ******************/
/***************************************************************************************************************/

void i2c_delay(void)
{
unsigned int i;
unsigned int tem;
for(i=0;i<200;i++)
{
tem++;
}
}

/* ????:???? /
void I2C_Sta_RX8025(void)
{
RX8025_SDA_ON(); /
sda=1 /
RX8025_SCL_ON(); /
scl=1 /
i2c_delay();
RX8025_SDA_OFF(); /
sda=0 /
i2c_delay();
RX8025_SCL_OFF(); /
scl=0 */
}

/* ????:?????? /
void I2C_Stop_RX8025(void)
{
RX8025_SDA_OFF(); /
sda=0 /
i2c_delay();
RX8025_SCL_ON(); /
scl=1 /
i2c_delay();
RX8025_SDA_ON(); /
sda=1 */
}

/* ????? /
void I2C_Mack_RX8025(void)
{
RX8025_SDA_OFF(); /
SDA???? /
i2c_delay();
RX8025_SCL_ON(); /
SCL???? /
i2c_delay();
RX8025_SCL_OFF(); /
SCL???? */
}

/* ?????? /
void I2C_MNack_RX8025(void)
{
RX8025_SDA_ON(); /
SDA???? /
i2c_delay();
RX8025_SCL_ON(); /
SCL???? /
i2c_delay();
RX8025_SCL_OFF(); /
SCL???? */
}

/* ????? /
void I2C_Ackn_RX8025(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOF,&GPIO_InitStructure);
i2c_delay();
RX8025_SCL_ON();
i2c_delay();
StateFlag8025=0; /
????? ????=0 /
if(GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_15))
{
StateFlag8025=1;
}
RX8025_SCL_OFF();
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; /
0x0FC0-->0xFFFF 20150623 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF,&GPIO_InitStructure);
}

/* ????? */
void I2C_WR_BYT_RX8025(unsigned int number0)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((number0&0x0080))
{
RX8025_SDA_ON();
RX8025_SCL_ON();
i2c_delay();
RX8025_SCL_OFF();
i2c_delay();
/////RX8025_SDA_OFF();
/////i2c_delay();
}
else
{
RX8025_SDA_OFF();
RX8025_SCL_ON();
i2c_delay();
RX8025_SCL_OFF();
i2c_delay();
}
number0<<=1;
}
}

/* ????? */
unsigned int I2C_RD_BYT_RX8025(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
unsigned char i;
unsigned char number1=0xff;

GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
GPIO_Init(GPIOF,&GPIO_InitStructure);
for(i=0;i<8;i++)
{
    number1<<=1;
    RX8025_SCL_ON();
    i2c_delay();
    if(GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_15))
    {
       number1=(number1|0x01);
    }
    else
    {
       number1=(number1&0xfe);
    }
    i2c_delay();
    RX8025_SCL_OFF();
    i2c_delay();
}
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;             /* 0x0FC0-->0xFFFF 20150623 */
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF,&GPIO_InitStructure);
return(number1);

}

/* ??????Rx8025 */
void Rx8025_wrnbyt(unsigned int SLA,unsigned int dev_addr,unsigned char pnt11,unsigned int length)
{
unsigned char i,j;
j=0;
do
{
I2C_Sta_RX8025();
I2C_WR_BYT_RX8025(SLA);
I2C_Ackn_RX8025();
j++;
}while((StateFlag8025==1)&&(j<50));
j=0;
do
{
I2C_WR_BYT_RX8025(dev_addr);
I2C_Ackn_RX8025();
j++;
}while((StateFlag8025==1)&&(j<50));
for(i=0;i<length;i++)
{
j=0;
do
{
j++;
I2C_WR_BYT_RX8025(
pnt11);
I2C_Ackn_RX8025();
}while((StateFlag8025==1)&&(j<50));
pnt11++;
}
I2C_Stop_RX8025();
}

/* ????Rx8025 */
void Rx8025_rdnbyt(unsigned int SLA,unsigned int dev_addr,unsigned char *pnt11,unsigned int length)
{
unsigned char i,j;
j=0;
do
{
I2C_Sta_RX8025();
I2C_WR_BYT_RX8025(0x64);
I2C_Ackn_RX8025();
j++;
}while((StateFlag8025==1)&&(j<50));
j=0;
do
{
I2C_WR_BYT_RX8025(dev_addr);
I2C_Ackn_RX8025();
j++;
}while((StateFlag8025==1)&&(j<50));
j=0;
do
{
I2C_Sta_RX8025();
I2C_WR_BYT_RX8025(0x65);
I2C_Ackn_RX8025();
j++;
}while((StateFlag8025==1)&&(j<50));
for(i=0;i<(length-1);i++)
{
*pnt11=I2C_RD_BYT_RX8025();
I2C_Mack_RX8025();
pnt11++;
}
*pnt11=I2C_RD_BYT_RX8025();
I2C_MNack_RX8025();
I2C_Stop_RX8025();
}

const unsigned char Tab_check_day[12] ={0x31,0x28,0x31,0x30,0x31,0x30,0x31,0x31,0x30,0x31,0x30,0x31}; /* ??? /
const unsigned char Tab_check_day1[12]={0x31,0x29,0x31,0x30,0x31,0x30,0x31,0x31,0x30,0x31,0x30,0x31}; /
?? /
/
-------------------------------------------------------------------------------------

  • ????????????????
  • *pnt ?? seconds, mininutes, hours, weeks, days, months, years
    -------------------------------------------------------------------------------------/

unsigned char CheckTime(unsigned char pnt)
{
unsigned char i,TimeErr=0x00;
if((
pnt>0x60)||((pnt&0x0f)>=0x0a)) TimeErr=0xff; / seconds?? /
else
{
pnt++;
if((
pnt>0x60)||((pnt&0x0f)>=0x0a)) TimeErr=0xff; / minutes?? /
else
{
pnt++;
if((
pnt>0x24)||((pnt&0x0f)>=0x0a)) TimeErr=0xff; / hours?? /
else
{
pnt++;
pnt++;
pnt++;
if((
pnt>0x13)||(((pnt&0x0f)>=0x0a)&&((pnt&0x0f)<0x10))||(pnt==0x00)) TimeErr=0xff; / months?? /
else
{
i=
pnt;
if(i>=0x10) i=i-0x06;
pnt++;
if(((pnt&0x0f)>=0x0a)||((pnt&0xf0)>=0xa0)) TimeErr=0xff; /* years?? /
else
{
if(((
pnt&0x03)==0x00)||((pnt&0xf0)/1610+(pnt&0x0f)/4==0x00)) / ?? /
{
pnt--;
pnt--;
if(((
pnt&0x0f)>=0x0a)||(pnt>Tab_check_day1[i-1])||(pnt==0x00)) TimeErr=0xff; /* ??? /
}
else /
??? /
{
pnt--;
pnt--;
if(((
pnt&0x0f)>=0x0a)||(pnt>Tab_check_day[i-1])||(pnt==0x00)) TimeErr=0xff;/* ??? */
}
}
}

            }
      }
}
return  TimeErr;

}

/---RX8025 initial program---/
void RTCInitial(void)
{
Rx8025_rdnbyt(0x64,0xe0,&timetest[0],0x02); /* read rx8025 control register /
if((timetest[1]&0x10==0x10)||(timetest[0]!=0x23)) /
?????????1?ct2,ct1,ct0!=0x011,rx8025?????1 /
{
RtcRstFlag=1;
i2c_delay();
}
else
{ /
????? /
i2c_delay();
RtcRstFlag=0;
Rx8025_rdnbyt(0x64,0x00,&timetest[0],0x07); /
read rx8025 time /
if(CheckTime(&timetest[0])==0xff)
{
RtcRstFlag=2; /
??RX8025??????,?????????2 /
}
else
{
daly.s=((timetest[0]&0xf0)>>4)
10+(timetest[0]&0x0f); /* ? /
daly.min=((timetest[1]&0xf0)>>4)
10+(timetest[1]&0x0f); /* ? /
daly.hour=((timetest[2]&0xf0)>>4)
10+(timetest[2]&0x0f); /* ? /
daly.day=((timetest[4]&0xf0)>>4)
10+(timetest[4]&0x0f); /* ? /
daly.mouth=((timetest[5]&0xf0)>>4)
10+(timetest[5]&0x0f); /* ? /
daly.year=((timetest[6]&0xf0)>>4)
10+(timetest[6]&0x0f)+2000; /* ? /
}
}
//RtcRstFlag=0;
if(RtcRstFlag!=0) /
???????? /
{
Data11[0]=0x23; /
RX8025 ?????1 /
Data11[1]=0x20; /
RX8025 ?????2 /
Delayms(5);
Rx8025_wrnbyt(0x64,0xe0,&Data11[0],0x02); /
write 8025 control register /
Delayms(5);
//Rx8025_rdnbyt(0x64,0x00,&timetest[0],0x07); /
read rx8025 time /
if(CheckTime(&timetest[0])==0xff) /
????????????? /
{
Data11[0]=0x01; /
? /
Data11[1]=0x55; /
? /
Data11[2]=0x10; /
? /
Data11[3]=0x04; /
? /
Data11[4]=0x16; /
? /
Data11[5]=0x07; /
? /
Data11[6]=0x15; /
? /
daly.s=((Data11[0]&0xf0)>>4)
10+(Data11[0]&0x0f); /* ? /
daly.min=((Data11[1]&0xf0)>>4)
10+(Data11[1]&0x0f); /* ? /
daly.hour=((Data11[2]&0xf0)>>4)
10+(Data11[2]&0x0f); /* ? /
daly.day=((Data11[4]&0xf0)>>4)
10+(Data11[4]&0x0f); /* ? /
daly.mouth=((Data11[5]&0xf0)>>4)
10+(Data11[5]&0x0f); /* ? /
daly.year=((Data11[6]&0xf0)>>4)
10+(Data11[6]&0x0f)+2000; /* ? /
Rx8025_wrnbyt(0x64,0x00,&Data11[0],0x07); /
write 8025 time */

        i2c_delay();
        Delayus(500);
        Rx8025_rdnbyt(0x64,0x00,&timetest[1],7);
        i2c_delay();
    }
}

}

/*****************************************************************************

  • ??: I2C_Write_NuData(uint16_t WriteAddr,uint16_t *WrData,uint16_t length)

  • ??: ?*Wbyte???n???????????WriteAddr???????

  • ????:length(??),????????*Wbyte???????
    *****************************************************************************/
    void I2C_Write_Nu16Data(uint16_t WriteAddr,uint16_t *WrData,uint16_t length)
    {
    uint8_t slaveAddr, dataAddrLow, dataAddrHigh,i,j;

    dataAddrHigh = WriteAddr / EE_PAGESIZE;
    dataAddrLow = WriteAddr % EE_PAGESIZE;

    slaveAddr = EE_DEV_ADDR;

//Send START command
i2cStart();

//Send Device Address to Write
i2cSendByte(slaveAddr | I2C_WR);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

//Send high data addrress
i2cSendByte(dataAddrHigh);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

//Send low data addrress
i2cSendByte(dataAddrLow);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

//Send START command
i2cStart();

//Send Device Address to Read
i2cSendByte(slaveAddr | I2C_RD);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

j=0;
for(j=0; j<length; j++)
{
    i=0;
    do
    {
        i2cSendByte((uint8_t)((*WrData)>>8));
        i++;
    } while(Ack2&&i<3);

    i=0;
    do
    {
        i2cSendByte((uint8_t)(*WrData));
        i++;
    } while(Ack2&&i<3);
    WrData++;
}
i2cStop();                                  //????

I2CRFAIL:
//Send STOP command
i2cStop();
}

/*****************************************************************************

  • ??: I2C_Read_NuData(uint16_t ReadAddr,uint16_t *RdData,uint16_t length)

  • ??: ??????n????

  • ????:length(??????),???????*Wbyte???????
    *****************************************************************************/
    void I2C_Read_Nu16Data(uint16_t ReadAddr,uint16_t *RdData,uint16_t length)//length<255
    {
    uint8_t slaveAddr, dataAddrLow, dataAddrHigh,i,j,tem0,tem1;
    uint16_t size;

    dataAddrHigh = ReadAddr / EE_PAGESIZE;
    dataAddrLow = ReadAddr % EE_PAGESIZE;

    slaveAddr = EE_DEV_ADDR;

i2cStart();

i2cSendByte(slaveAddr | I2C_WR);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

i2cSendByte(dataAddrHigh);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

i2cSendByte(dataAddrLow);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

i2cStart();

i2cSendByte(slaveAddr | I2C_RD);
if (i2cWaitAck() != I2CSUCCESS)
{
goto I2CRFAIL;
}

    for(j=0; j<length-1; j++)
{
  tem0=i2cReadByte();
  if (size != 0)
  {
     i2cAck();
  }
  else
  {
     i2cNAck();
  }
            
  tem1=i2cReadByte();
  if (size != 0)
  {
     i2cAck();
  }
  else
  {
     i2cNAck();
  }

        *RdData=tem0*256+tem1;
        RdData++;
}
    tem0=i2cReadByte();
    if (size != 0)
    {
         i2cAck();
    }
    else
    {
         i2cNAck();
    }
        
    tem1=i2cReadByte();
    if (size != 0)
    {
         i2cAck();
    }
    else
    {
         i2cNAck();
    }

    *RdData=tem0*256+tem1;

i2cStop();     

I2CRFAIL:

i2cStop(); //????
}

//void I2C_Write_Nu16Data(uint16_t WriteAddr,uint16_t *WrData,uint16_t length)
//{
// new_64_WrFMwordNByte(0xa0,WriteAddr,WrData,length);
//}
//void I2C_Read_Nu16Data(uint16_t ReadAddr,uint16_t *RdData,uint16_t length)//length<255
//{
// new_64_RdFMwordNByte(0xa0,ReadAddr,RdData,length);
//}

void I2C_Write_Nu16Data1(uint16_t WriteAddr,uint16_t *WrData,uint16_t length)
{
}

void I2C_Read_Nu16Data1(uint16_t ReadAddr,uint16_t *RdData,uint16_t length)
{
}

/*****************************************************************************/
/******************************** END NO MORE ********************************/
/*****************************************************************************/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • 参考链接:http://blog.csdn.net/sweetsnow24/article/details/863...
    Tony1213阅读 4,226评论 0 0
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,621评论 0 3
  • 这篇文章是写给一个学弟看的,关于IIC,关于24C02的单字节写入\读取..页写入和读取,,学弟总是害怕协议,,,...
    杨奉武阅读 1,923评论 0 1
  • 前言一: 直播是互联网今年的关键词,风口催生出的一大批公司现在几乎都在烧钱,要么烧钱推广,要么烧钱买主播。但是开公...
    红二阅读 1,189评论 0 1
  • 李莹决定要离开,有点舍不得。死党又决定不来大组会,觉得很失落,还想好好欣赏下她脸肿的样子。 这也是人生的一部分。 ...
    王王111阅读 105评论 3 1