打印
[经验分享]

单片机IO口模拟I2C软件驱动

[复制链接]
729|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-11-4 11:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//延时函数
static void I2c_Delay(uint8_t count)
{
    uint8_t i;

    for(i = 0;i < count;i++);
}  
//读取SDA脚位状态
static uint8_t I2c_SDAStatus(void)
{
    uint8_t SDA_Status;

    SDA_Status = PB06_GETVALUE();

    return SDA_Status?1:0;
}
//设置SDA脚为输出
void SDA_OutMode(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    GPIO_InitStructure.Pins = GPIO_PIN_6;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;  
    GPIO_InitStructure.IT   = GPIO_IT_NONE;
    GPIO_Init(CW_GPIOB,&GPIO_InitStructure);
}
//设置SDA脚为输入
void SDA_inputMode(uint8_t InputMode)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    GPIO_InitStructure.Pins = GPIO_PIN_6;
    if(InputMode == 0)
    {
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;  //无下拉,只能输出低电平作ACK(2004特殊I2C协议,主机即作写数据又作ACK,最后一字节非ACK)
    }
    else
    {
        GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;  
    }
    GPIO_InitStructure.IT   = GPIO_IT_NONE;
    GPIO_Init(CW_GPIOB,&GPIO_InitStructure);
}
//I2C开始信号
void I2c_Start(void)
{   
    SDA_OutLow;
    I2c_Delay(30);
    SCL_OutLow;
    I2c_Delay(30);
}
//I2C停止信号
void I2c_Stop(void)
{
    SCL_OutLow;
    I2c_Delay(30);

    SDA_OutLow;
    I2c_Delay(30);

    SCL_OutHigh;
    I2c_Delay(30);

    SDA_OutHigh;
}
//等待(从机)应答
uint8_t I2c_WaitAck(uint8_t AckFlag)
{
    uint8_t AckNack = 1;

    if(AckFlag)  //2004特殊I2C协议,主机即作写数据又作ACK,最后一字节非ACK
    {
        SDA_inputMode(0);  //输入下拉,模拟假应答;主机写主机应答/非应答,从机2004识别
        SDA_OutLow;
    }
    else
    {
        SDA_inputMode(0);  //输入下拉,模拟假应答;主机写主机应答/非应答,从机2004识别
        SDA_OutHigh;
    }

    I2c_Delay(12);

    SCL_OutHigh;
    I2c_Delay(30);
    SCL_OutLow;
    I2c_Delay(10);

    SDA_OutMode();
    I2c_Delay(5);

    return AckNack;
}
//发送ACK
void I2c_SendAck(void)
{
    SDA_OutLow;
    I2c_Delay(30);
    SCL_OutHigh;
    I2c_Delay(30);
    SCL_OutLow;
    I2c_Delay(30);
}
//发送NACK
void I2c_SendNack(void)
{
    SDA_OutHigh;
    I2c_Delay(30);
    SCL_OutHigh;
    I2c_Delay(30);
    SCL_OutLow;
    I2c_Delay(30);
}
//写一个字节
void I2c_WriteByte(uint8_t Byte)
{
    uint8_t i;

    for(i = 0;i < 8;i++)
    {
        I2c_Delay(26);
        I2c_Delay(6);

        if(Byte&0x80)
        {
            SDA_OutHigh;
        }
        else
        {
            SDA_OutLow;
        }
        I2c_Delay(30);
        SCL_OutHigh;
        I2c_Delay(30);   
        SCL_OutLow;

        Byte <<= 1;
    }
    SCL_OutLow;
    I2c_Delay(5);
}
//读一个字节
uint8_t I2c_ReadByte(void)
{
    uint8_t i,byte;

    SDA_inputMode(0);
    I2c_Delay(5);

    for(i = 0;i < 8;i++)
    {
        byte <<= 1;
        I2c_Delay(26);

        if(I2c_SDAStatus())
        {
           byte |= 0x01;
        }
        I2c_Delay(26);
        SCL_OutHigh;
        I2c_Delay(26);
        SCL_OutLow;
    }

    SDA_OutMode();

    return byte;
}
//连续写多个字节
void I2c_WriteNbyte(uint8_t I2C_Addr,uint8_t* data,uint8_t len)
{
    uint8_t j = 0;

    I2c_Start();
    I2c_WriteByte(I2C_Addr);
    I2c_WaitAck(1);

    for(j = 0;j < len;j++)
    {
        I2c_WriteByte(data[j]);  
        if(j < (len-1))
        {
            I2c_WaitAck(1); //2004特殊I2C协议,主机写,还得主机应答

        }
        else
        {
            I2c_WaitAck(0); //最后一个字节NACK
        }
    }

    I2c_Stop();
}
//读取多个字节
void I2c_ReadNbyte(uint8_t I2C_Addr,uint8_t* buf,uint8_t len)
{
    uint8_t j;

//    I2C_Addr <<= 1;

    I2c_Start();
    I2c_WriteByte(I2C_Addr|0x01);

    if(!I2c_WaitAck(1))
    {
        I2c_Stop();
        return;
    }
    for(j = 0;j < len;j++)
    {
        buf[j] = I2c_ReadByte();
        if(j != (len-1))
        {
            I2c_SendAck();
        }
        else
        {
            I2c_SendNack();
        }
    }
    I2c_Delay(26);
    I2c_Stop();
}
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_50707044/article/details/141259267
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_50707044/article/details/141259766

使用特权

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

本版积分规则

1931

主题

15611

帖子

11

粉丝