我用stm32f3 的PB8 (I2C1_SCL)和PB9(I2C1_SDA)模拟i2c,结果调试了好几天都是写地址后没有应答信号,但是读的时候却能读出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);
/* SDA_H();
I2c_delay(50);
SCL_H();
I2c_delay(60);
SDA_in();
ack = (SDA_High)?(0):(1);
SCL_L();
I2c_delay(50);*/
}
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);
}
/* if(!ack)
I2c_send_noack();
else
I2c_send_ack();*/
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();
}
|