单片机
返回首页

STM8 I/O口模拟I2C

2019-11-11 来源:eefocus

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  

  {  

  

  *(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  

  {  

  

  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)),太郁闷了 


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章