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

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
wyxy163@126.com 回答时间:2015-7-13 19:25:06
提示: 作者被禁止或删除 内容自动屏蔽
alisa123 回答时间:2015-7-13 21:18:17
ningzb 发表于 2015-7-13 17:02
1.可以确定的告诉你,模拟的可以运行
2.初始化时,时钟初始化成输出模式,数据初始化成开漏输出,外面要加 ...

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

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版