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