我用stm32f3 的PB8 (I2C1_SCL)和PB9(I2C1_SDA)模拟i2c,结果调试了好几天硬件的没有搞定,想用软件模拟,看时序感觉没问题,可是写地址后24c08没有应答信号,但是读的时候却能读出0xFF,不知哪里有问题,求高手帮忙看一下,谢谢。 代码如下: #define SCL_L() GPIOB->ODR &= ~(1<<8) #define SCL_H() GPIOB->ODR |= (1<<8) #define SDA_L() GPIOB->ODR &= ~(1<<9) //GPIOB->BRR = GPIO_Pin_9 #define SDA_H() GPIOB->ODR |= (1<<9) //GPIOB->BSRR = GPIO_Pin_9 #define SDA_out() {GPIOB->MODER &= 0xFFF3FFFF;GPIOB->MODER |= 0x00040000;} #define SDA_in() {GPIOB->MODER &= 0xFFF3FFFF;GPIOB->MODER |= 0x00000000;} #define SDA_High GPIOB->IDR&GPIO_Pin_9 #define Write 0xfe #define Read 0x01 #define A2 (1<<3) #define P1_P0(Addr) (((Addr / 256)& 0x03)<< 1) unsigned char ack; /************************************************************** *Function **************************************************************/ void I2c_delay(unsigned int t) { while(t--); } void I2c_start(void) //start: when scl is high,sda change grom high to low { SDA_out(); SDA_H(); // I2c_delay(20); SCL_H(); I2c_delay(500); SDA_L(); I2c_delay(500); SCL_L(); I2c_delay(50); } void I2c_stop(void) //stop:when scl is high,sda change from low to high { SDA_out(); SCL_L(); SDA_L(); I2c_delay(500); SCL_H(); I2c_delay(100); SDA_H(); I2c_delay(500); } unsigned char I2c_wait_ack(void) { unsigned char i; unsigned char I2c_bad; SDA_in(); SDA_H(); I2c_delay(100); SCL_H(); I2c_delay(100); for(i=0; i<3; i++) { if(SDA_High) { I2c_bad=1; } else { I2c_bad=0; break; } I2c_delay(100); } SCL_L(); I2c_delay(10); // SDA_out(); // I2c_delay(10); return I2c_bad; } void I2c_no_wait_ack(void) { // SDA_out(); // I2c_delay(20); SDA_H(); I2c_delay(60); SCL_H(); I2c_delay(100); SCL_L(); I2c_delay(40); } void I2c_send_ack(void) { SDA_out(); SCL_L(); I2c_delay(20); SDA_L(); I2c_delay(200); SCL_H(); I2c_delay(200); SCL_L(); I2c_delay(20); } void I2c_send_noack(void) { SDA_out(); SCL_L(); I2c_delay(10); SDA_H(); I2c_delay(200); SCL_H(); I2c_delay(200); SCL_L(); I2c_delay(10); } void I2c_wr8bit(unsigned char c) { unsigned char i; SDA_out(); SCL_L(); I2c_delay(10); for(i=0; i<8; i++) { if(c&0x80) SDA_H(); else SDA_L(); I2c_delay(20); SCL_H(); I2c_delay(200); SCL_L(); I2c_delay(200); c=c<<1; I2c_delay(200); } I2c_delay(10); } unsigned char I2c_rd8bit(void) { unsigned char i, val=0; SCL_H(); SDA_in(); I2c_delay(10); /* for(i=0x80; i>0;) { SCL_H(); I2c_delay(20); if(SDA_High) val=(val | i); // I2c_delay(10); SCL_L(); i>>=1; // I2c_delay(20); } I2c_delay(20); // return val;*/ for(i = 0; i < 8;i++) { SCL_L(); I2c_delay(200); SCL_H(); val <<= 1; if(SDA_High) val++; I2c_delay(100); } return val; } void I2c_write(unsigned char Addr,unsigned char Data,unsigned char DeviceID) { INT8U Ack; I2c_start(); I2c_wr8bit(DeviceID&Write); I2c_wait_ack(); I2c_wr8bit(Addr); I2c_wait_ack(); I2c_wr8bit(Data); I2c_wait_ack(); I2c_stop(); I2c_delay(1000); } unsigned char I2c_read(unsigned char Addr,unsigned char Data,unsigned char DeviceID) { I2c_start(); I2c_wr8bit(DeviceID&Write); I2c_wait_ack(); I2c_wr8bit(Addr); I2c_wait_ack(); I2c_start(); I2c_wr8bit(DeviceID|Read); I2c_wait_ack(); Data=I2c_rd8bit(); I2c_no_wait_ack(); I2c_stop(); return Data; } void I2c_wr8bit_low(unsigned char c) { char i; SDA_out(); for(i=0; i<8; i++) { if(c&0x01) SDA_H(); else SDA_L(); I2c_delay(10); SCL_H(); I2c_delay(10); SCL_L(); c>>=1; I2c_delay(10); } SDA_H(); } void Send_byte_low(unsigned char data_byte) { I2c_wr8bit_low(data_byte); I2c_wait_ack(); } void Send_byte (unsigned char data_byte) { I2c_wr8bit(data_byte); I2c_wait_ack(); } void sWriteI2C(INT8U *lubData,INT16U luwI2CAddr,INT8U lubDataLen) { INT8U Len; I2c_start(); I2c_wr8bit((0xa0 + P1_P0(luwI2CAddr))&Write); //Write Device Address I2c_wait_ack(); I2c_wr8bit(luwI2CAddr % 256); //Write Word Address I2c_wait_ack(); for(Len = 0;Len < lubDataLen;Len++) { I2c_wr8bit(*lubData); //Write high byte I2c_wait_ack(); lubData++; luwI2CAddr++; } I2c_stop(); } void sReadI2C(INT8U* lubData,INT16U luwI2CAddr,INT8U lubDataLen) { INT8U Len; I2c_start(); I2c_wr8bit((0xa0 + P1_P0(luwI2CAddr))&Write); //Write Device Address I2c_wait_ack(); I2c_wr8bit(luwI2CAddr % 256); //Write Word Address I2c_wait_ack(); I2c_start(); I2c_wr8bit((0xa0 + P1_P0(luwI2CAddr))|Read); I2c_wait_ack(); for(Len = 0;Len < lubDataLen - 1;Len++) { *lubData = I2c_rd8bit(); I2c_send_ack(); lubData++; luwI2CAddr++; } *lubData = I2c_rd8bit(); I2c_no_wait_ack(); I2c_stop(); } |
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加上啦电阻,具体软件,你按照IIC协议来就行了,需要用示波器观察波形,注意你的速率,很多器件速率不能超过400k
谢谢你的详细回复,问题已经解决,是硬件电路出了问题。