发一个IO模拟I2C从机的代码吧

2019-12-11 18:14发布

本帖最后由 xiaob135 于 2014-5-11 16:22 编辑

今天下了一天雨,无聊写点代码吧。
发现网上都是io口模拟i2c主机的代码,很少有模拟i2c从机的。所以写一个贡献出来。对于学习i2c的时序还是挺有帮助的。
需要两个带中断的io口,必须支持上升沿和下降沿中断。


typedef enum
{
                I2C_SLAVE_IDLE,
                I2C_SLAVE_ADD,//write iic add
                I2C_SLAVE_REG,//write the register add
                I2C_SLAVE_WRITE,//master write and slave read
                I2C_SLAVE_READ,//master read and slave write
                I2C_SLAVE_BUSY
}e_I2C_SLAVE_MODE;

static e_I2C_SLAVE_MODE                i2c_slave_mode = I2C_SLAVE_IDLE;
static unsigned char I2C_DATA_TEMP = 0;
static unsigned char i2c_slave_reg_p = 0;//the register add
static unsigned char i2c_slave_data_p = 0;//


void i2c_slave_scl_h( void )
{
        I2C_SDA_INT_EN();
        switch( i2c_slave_mode )
        {
                case I2C_SLAVE_ADD:
                case I2C_SLAVE_REG:
                case I2C_SLAVE_WRITE:
                        I2C_DATA_TEMP <<= 1;
                        if( I2C_SDA_IN() )
                                I2C_DATA_TEMP ++;
                        i2c_slave_data_p++;
                        break;               
                default:break;
        }
}

void i2c_slave_scl_l( void )
{
        I2C_SDA_INT_DIS();
       
        if( i2c_slave_data_p > 8 )
        {
                i2c_slave_data_p = 0;
                I2C_SDA_H();//end ack;
                return;
        }
       
        I2C_SCL_L();//slow the i2c speed
        switch( i2c_slave_mode )
        {
                case I2C_SLAVE_ADD:
                        if( i2c_slave_data_p == 8 )
                        {
                                        if( I2C_DATA_TEMP >> 1 == I2C_ADD )
                                        {
                                                I2C_SDA_L();//ack
                                                if( I2C_DATA_TEMP & 0x01 )//read
                                                {
                                                        i2c_slave_mode = I2C_SLAVE_READ;
                                                }
                                                else
                                                        i2c_slave_mode = I2C_SLAVE_REG;//write regster add
                                        }
                                        else
                                                i2c_slave_mode = I2C_SLAVE_BUSY;//nack
                        }
                        break;
                case I2C_SLAVE_REG:
                        if( i2c_slave_data_p == 8 )
                        {
                                        I2C_SDA_L();//ack
                                        i2c_slave_reg_p = I2C_DATA_TEMP;
                                        i2c_slave_mode = I2C_SLAVE_WRITE;
                        }
                        break;
                case I2C_SLAVE_WRITE:
                        if( i2c_slave_data_p == 8 )
                        {//
                                        if( I2C_SLAVE_WRITE_BYTE( i2c_slave_reg_p++, I2C_DATA_TEMP ) )
                                        {
                                                        I2C_SDA_L();
                                        }
                                        else
                                        {
                                                        i2c_slave_mode = I2C_SLAVE_BUSY;
                                        }
                        }
                        break;
                case I2C_SLAVE_READ:
                        if( i2c_slave_data_p < 8 )
                        {
                                        if( I2C_DATA_TEMP & 0x80 )//output a bit
                                                I2C_SDA_H();
                                        else
                                                I2C_SDA_L();               
                                        I2C_DATA_TEMP <<= 1;
                                        i2c_slave_data_p++;
                        }
                        else if( i2c_slave_data_p == 8 )
                        {
                                        if( I2C_SLAVE_READ_BYTE(i2c_slave_reg_p++, &I2C_DATA_TEMP) )
                                        {
                                                        I2C_SDA_L();
                                        }
                                        else
                                        {
                                                        i2c_slave_mode = I2C_SLAVE_BUSY;
                                        }
                        }
                        break;
                        default:break;
        }
        I2C_SCL_H();
}

void i2c_slave_sda_h( void )
{
                if( I2C_SCL_IN() )
                {
                        I2C_SCL_INT_DIS();
                        i2c_slave_mode = I2C_SLAVE_IDLE;
                }
}

void i2c_slave_sda_l( void )
{
        switch( i2c_slave_mode )
        {
                case I2C_SLAVE_IDLE:
                        if( I2C_SCL_IN() )
                        {
                                I2C_SCL_INT_EN();
                                i2c_slave_mode = I2C_SLAVE_ADD;
                                i2c_slave_data_p = 0;
                        }
                        break;
                default:break;
        }
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
60条回答
andy_huang
1楼-- · 2019-12-16 09:22
谢谢分享!
guo407214944
2楼-- · 2019-12-16 10:17
        /* Connect EXTI Line2 to PA2 pin */
guo407214944
3楼-- · 2019-12-16 13:48
        /* Connect EXTI Line2 to PA2 pin */        /* Connect EXTI Line3 to PA3 pin */  你好,PA2,和PA3接口应该连接到哪里呢,连接主机SCL,SDA口么?看你代码,应该是PA6,PA7这2个脚连接主机的SCL和SDA,代码如下,                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ;                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                 GPIO_Init(GPIOA, &GPIO_InitStructure);                                  I2C_SCL_H();                 I2C_SDA_H();。
guo407214944
4楼-- · 2019-12-16 19:45
        /* Connect EXTI Line2 to PA2 pin */        /* Connect EXTI Line3 to PA3 pin */  你好,PA2,和PA3接口应该连接到哪里呢,连接主机SCL,SDA口么?看你代码,应该是PA6,PA7这2个脚连接主机的SCL和SDA,代码如下,                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ;                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                 GPIO_Init(GPIOA, &GPIO_InitStructure);                                  I2C_SCL_H();                 I2C_SDA_H();
online9930
5楼-- · 2019-12-16 20:07
 精彩回答 2  元偷偷看……
PANGKUN
6楼-- · 2019-12-16 23:48
make!make!

一周热门 更多>