STM8 I/O口模拟I2C

STM8I/O口模拟I2C所读数据不正确
STM8 I/O口模拟I2C


#define I2C_ERR   0

#define I2C_CRR   1

#define  I2CDataIn  1

#define  I2CDataOut 0

#define I2C_PORT  (GPIOC)

#define I2CSCL   (GPIO_PIN_7)

#define I2CSDA   (GPIO_PIN_6)


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

// I2C Data input/output

// 0-Output, 1-Input

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

void I2CDataInOut(bool InOut)

{

if(InOut)

  {

  GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_IN_FL_NO_IT);

  }

else

  {

  GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_OUT_OD_LOW_FAST);

  }

}

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

//  Send start condition

//  ensure data is high then issue a start condition

//  see also i2c_Start() macro

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

void I2C_Start (void)

{

GPIO_WriteHigh(I2C_PORT, I2CSDA);

_delay_5us(5);

GPIO_WriteHigh(I2C_PORT, I2CSCL);

_delay_5us(5);

GPIO_WriteLow(I2C_PORT, I2CSDA);

_delay_5us(5);

}

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

//   Send stop condition

//   data low-high while clock high

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

void I2C_Stop (void)

{

GPIO_WriteLow(I2C_PORT, I2CSDA);

_delay_5us(5);

GPIO_WriteHigh(I2C_PORT, I2CSCL);

_delay_5us(5);

GPIO_WriteHigh(I2C_PORT, I2CSDA);

}

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

//ROUTINE NAME : I2C_Ack

//INPUT/OUTPUT : None.

//DESCRIPTION  : Acknoledge generation from now.

//COMMENTS     : Transfer sequence = DATA, ACK.

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

void I2C_Rack(void)

{

GPIO_WriteLow(I2C_PORT, I2CSDA);

_delay_5us(5);

GPIO_WriteHigh(I2C_PORT, I2CSCL);

_delay_5us(5);

GPIO_WriteLow(I2C_PORT, I2CSCL);

_delay_5us(5);

}


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

//ROUTINE NAME : I2C_nAck

//INPUT/OUTPUT : None.

//DESCRIPTION  : Non acknoledge generation from now.

//COMMENTS     : Transfer sequence = DATA, NACK.

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

void I2C_nAck (void)

{

GPIO_WriteHigh(I2C_PORT, I2CSDA);

_delay_5us(5);

GPIO_WriteHigh(I2C_PORT, I2CSCL);

_delay_5us(5);

GPIO_WriteLow(I2C_PORT, I2CSCL);

_delay_5us(5);

}

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

//  Send a byte to the slave 写一个数据没有应答

//  return I2C_ERR OR I2C_CRR

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

bool SendByte(UCHAR I2cData)

{

UCHAR i;

bool I2CStatus;


for(i=0; i<8; i++)

  {

  GPIO_WriteLow(I2C_PORT, I2CSCL);

  _delay_5us(5);

  if(I2cData & 0x80)

   {GPIO_WriteHigh(I2C_PORT, I2CSDA);}

  else

   {GPIO_WriteLow(I2C_PORT, I2CSDA);}

  GPIO_WriteHigh(I2C_PORT, I2CSCL);

  _delay_5us(5);

  I2cData <<= 1;

  }

  GPIO_WriteLow(I2C_PORT, I2CSCL);

  GPIO_WriteHigh(I2C_PORT, I2CSDA);//发送完一字节,接收应答

  

  I2CDataInOut(I2CDataIn);


  GPIO_WriteHigh(I2C_PORT, I2CSCL);

  _delay_5us(5);

  if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 0)

   {

   I2CStatus = I2C_CRR;

   }

  else

   {

   I2CStatus = I2C_ERR;

   }

  I2CDataInOut(I2CDataOut);

  return I2CStatus;

}


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

//ROUTINE NAME : I2Cm_RxData

//INPUT/OUTPUT : Last byte to receive flag (active high)/Received data byte.

//DESCRIPTION  : Receive a data byte.

//COMMENTS     : Transfer sequence = DATA, ACK, EV7...

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

UCHAR RcvByte(void)

{   

    UCHAR i;

    UCHAR ReadByte=0;

   GPIO_WriteHigh(I2C_PORT, I2CSDA);


I2CDataInOut(I2CDataIn);

_delay_5us(10);

for(i=0; i<8; i++)

  {

   ReadByte <<= 1;

   GPIO_WriteLow(I2C_PORT, I2CSCL);

   _delay_5us(5);

   GPIO_WriteHigh(I2C_PORT, I2CSCL);

   _delay_5us(5);


   if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 1)

    {ReadByte |= 0x01;}

   _delay_5us(5);

  }  

GPIO_WriteLow(I2C_PORT, I2CSCL);

I2CDataInOut(I2CDataOut);

_delay_5us(10);

   return ReadByte;

}


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

  读N个数据,参数:?

   wrDAdr: write device-address 写器件地址??

   wordAdr: word address 读数据的寄存器地址??

   rdDAdr: read device-address 读器件地址

   *pRdDat: p->read data 读数据指针

   num: number 需要读数据的个数

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

bool I2C_Read(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pRdDat,UCHAR num)

{

bool I2CAck;

UCHAR i=0;

UCHAR rdDAdr;

rdDAdr = wrDAdr+1; //读器件地址为写地址加1

I2C_Start();  /*启动I2C*/

_delay_5us(5);

I2CAck = SendByte(wrDAdr); /*发写器件地址*/

if(!I2CAck)

  {

   return I2C_ERR;

  }

I2CAck = SendByte(wordAdr); /*发寄存器地址*/

if(!I2CAck)

  {

   return I2C_ERR;

  }


I2C_Start();   /*重启I2C*/

  I2CAck = SendByte(rdDAdr); /*发读器件地址*/

if(!I2CAck)

  {

   return I2C_ERR;

  }

_delay_5us(5);

for(i=0;i<num-1;i++)

  {

  *(pRdDat+i) = RcvByte();

  I2C_Rack();

   }

if(i==num-1)

  {

  *(pRdDat+i) = RcvByte();

  I2C_nAck();

  }

I2C_Stop();

return I2C_CRR;

}


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

写N个数据,前N-1个要应答,最后一个不要应答

wrDAdr: write device-address 写器件地址??

  wordAdr: word address 写数据的寄存器地址?

  *pWrDat: p->write data 写数据指针

  num: number  需要写入的数据个数

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

bool I2C_Write(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pWrDat,UCHAR num)

{

bool I2CAck;

unsigned char i;


I2C_Start();      /*启动I2C*/

_delay_5us(5);

I2CAck = SendByte(wrDAdr); /*发写器件地址*/

if(!I2CAck)

  {

   return I2C_ERR;

  }

I2CAck = SendByte(wordAdr);  /*发要写的寄存器地址*/

if(!I2CAck)

  {

   return I2C_ERR;

  }

for(i=0;i<num-1;i++)

  {

  I2CAck = SendByte(*(pWrDat+i));

  if(!I2CAck)

   {return I2C_ERR;}

  }

if(i==num-1)

  {

  I2CAck = SendByte(*(pWrDat+num-1));

  if(!I2CAck)

   {return I2C_ERR;}

  }

I2C_Stop();

return I2CAck;

} 

以上代码不知为何读出数据不正确,用示波器看我发送的器件地址,寄存器地址这些都对,器件输出的数据是0xFF,程序中读出返回的数据是0x00,弄了一天没对相当郁闷,同志们指点下



终于搞定了, 应该跟我的器件有关,另外if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 1)这种不能写成==1,要直接写成if(GPIO_ReadInputPin(I2C_PORT,I2CSDA)),太郁闷了


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值