stm32f3的软件模拟i2c写地址后24c08没有应答信号

2019-07-14 17:03发布

我用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();
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
wq644921241
1楼-- · 2019-07-15 01:37
楼主整个逻辑分析仪看下
wq644921241
2楼-- · 2019-07-15 02:12
什么问题都能看出来
fantasyo老时光
3楼-- · 2019-07-15 03:30
 精彩回答 2  元偷偷看……
cnm4
4楼-- · 2019-07-15 03:58
1.可以确定的告诉你,模拟的可以运行
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加上啦电阻,具体软件,你按照IIC协议来就行了,需要用示波器观察波形,注意你的速率,很多器件速率不能超过400k
youxi8745
5楼-- · 2019-07-15 05:42
现在我才发现逻辑分析仪真的是个好东西,尤其分析IIC ,spi啥的,太方便了
leilijiao
6楼-- · 2019-07-15 09:40
cnm4 发表于 2018-10-10 15:28
1.可以确定的告诉你,模拟的可以运行
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加上啦电阻,具体软件,你按照IIC协议来就行了,需要用示波器观察波形,注意你的速率,很多器件速率不能超过400k

谢谢你的详细回复,问题已经解决,是硬件电路出了问题。

一周热门 更多>