打印
[STM32F3]

stm32 模拟i2c

[复制链接]
1377|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Alisa_song|  楼主 | 2015-7-12 19:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用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();
}
沙发
一清如水| | 2015-7-12 20:14 | 只看该作者
你可以参考,原子的模拟IIC。不注释,不是好习惯,呵呵

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
Alisa_song + 3 赞一个!
板凳
309030106| | 2015-7-12 21:52 | 只看该作者
芯片内部没有IIC资源吗

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
Alisa_song + 3
地板
Alisa_song|  楼主 | 2015-7-13 21:22 | 只看该作者
一清如水 发表于 2015-7-12 20:14
你可以参考,原子的模拟IIC。不注释,不是好习惯,呵呵

谢谢你的回复,问题已经解决,是硬件连接出了问题,注释以后我会多多注意。

使用特权

评论回复
5
Alisa_song|  楼主 | 2015-7-13 21:23 | 只看该作者
309030106 发表于 2015-7-12 21:52
芯片内部没有IIC资源吗

内部有i2C ,可是没搞明白,感觉软件模拟会简单,所以就先这样做了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

94

帖子

1

粉丝