你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32f3的软件模拟i2c

[复制链接]
alisa123 提问时间:2015-7-12 19:56 /
我用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();
}
收藏 评论7 发布时间:2015-7-12 19:56

举报

7个回答
左岸右岸 回答时间:2015-7-12 21:38:09
没模拟过,帮顶
lkl0305 回答时间:2015-7-12 23:12:10
楼主整个逻辑分析仪看下
lkl0305 回答时间:2015-7-12 23:12:33
什么问题都能看出来
yanhaijian 回答时间:2015-7-13 10:40:56
这就不要求助了,到各大电子论坛上一搜一大把。
ningzb 回答时间:2015-7-13 17:02:01
1.可以确定的告诉你,模拟的可以运行
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加上啦电阻,具体软件,你按照IIC协议来就行了,需要用示波器观察波形,注意你的速率,很多器件速率不能超过400k
数码小叶 回答时间:2015-7-13 19:25:06
现在我才发现逻辑分析仪真的是个好东西,尤其分析IIC ,spi啥的,太方便了
alisa123 回答时间:2015-7-13 21:18:17
ningzb 发表于 2015-7-13 17:02
1.可以确定的告诉你,模拟的可以运行
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加 ...

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

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版