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