[单片机] GPIO模拟IIC

/*
本程序是IIC作为主设备(主动发起启动信号)
*/
#define uint8_t unsigned char
#define DEV_ADDR 0x70 //需要控制的设备地址
#define ADDRESS_DEV (DEV_ADDR << 7)

int SDA = 0; // 某GPIO_DAT;如51单片机时 #define SDA P1_0
int SCL = 0; // 某GPIO_CLK;如51单片机时 #define SCL P1_1

void I2C_SendByte(uint8_t _ucByte)
{
    uint8_t i;

    IIC_Delay();
    /* 先发送字节的高位bit7 */
    for (i = 0; i < 8; i++)
    {
        if (_ucByte & 0x80)
        {
            SDA = 1;
        }
        else
        {
            SDA = 0;
        }
        IIC_Delay();
        SCL = 1;
        IIC_Delay();
        SCL = 0;
        if (i == 7)
        {
            SDA = 1;
        }
        _ucByte <<= 1; /* 左移一个bit */
        IIC_Delay();
    }
}

uint8_t I2C_ReadByte(void)
{
    uint8_t i;
    uint8_t value = 0;
    IIC_Delay();
    // 读到第1个bit为数据的bit7
    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        SCL = 1;
        IIC_Delay();
        if (SDA == 1)
        {
            value++;
        }
        IIC_Delay();
        SCL = 0;
        IIC_Delay();
    }
    return value;
}
/*SDA下降沿=start*/
void I2C_Start(void)
{
    IIC_Delay();
    SDA = 1; // 顺序不能反了,先是SDA=1;
    SCL = 1;
    IIC_Delay();
    SDA = 0;
    IIC_Delay();
    SCL = 0;
    IIC_Delay();
}

/*SDA上升沿=stop*/
void I2C_Stop(void)
{
    IIC_Delay();
    SDA = 0; // 顺序不能反了,先是SDA=0;
    IIC_Delay();
    SCL = 1;
    IIC_Delay();
    SDA = 1;
}

void I2C_Ack(void)
{
    IIC_Delay();
    SDA = 0;
    IIC_Delay();
    SCL = 1;
    IIC_Delay();
    SCL = 0;
    IIC_Delay();
    SDA = 1;
}

void I2C_NAck(void)
{
    IIC_Delay();
    SDA = 1;
    IIC_Delay();
    SCL = 1;
    IIC_Delay();
    SCL = 0;
    IIC_Delay();
}

void I2C_WaitAck(void)
{
    uint8_t i = 100;

    IIC_Delay();
    SCL = 1;
    IIC_Delay();
    while ((SDA == 1) && (i > 0))
    {
        IIC_Delay();
        i--;
    }
    SCL = 0;
    IIC_Delay();
    if (i == 0)
    {
    }
}

void I2C_WriteSensor(uint8_t addrReg, uint8_t buf)
{
    I2C_Start(); /*发送启动信号*/
    I2C_SendByte(ADDRESS_DEV);
    I2C_WaitAck(); /* 检测设备的ACK应答 */
    I2C_SendByte(addrReg);
    I2C_WaitAck(); /* 检测设备的ACK应答 */
    I2C_SendByte(buf);
    I2C_WaitAck(); /* 检测设备的ACK应答 */
    I2C_Stop();
}
void I2C_ReadSensor(uint8_t addrReg, uint8_t *buffer, uint8_t len)
{
    uint8_t i;
    I2C_Start();
    /*发送启动信号*/
    /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
    I2C_SendByte(ADDRESS_DEV);
    I2C_WaitAck();
    /* 检测设备的ACK应答*/
    I2C_SendByte(addrReg);
    I2C_WaitAck();
    /*检测设备的ACK应答*/
    //========================
    I2C_Start();
    /*发送启动信号*/
    I2C_SendByte(ADDRESS_DEV + 1);
    I2C_WaitAck();
    /*检测设备的ACK应答 */
    for (i = 0; i < len - 1; i++)
    {
        *buffer++ = I2C_ReadByte();
        I2C_Ack();
    }
    *buffer++ = I2C_ReadByte();
    I2C_NAck();
    I2C_Stop();
}

void IIC_Delay(void)
{
    uint8_t i;
    for (i = 0; i < 10; i++)
    {
        nop();
    }
}
void I2C_Init(void) // 初始化
{
    SDA = 1;
    IIC_Delay();
    SCL = 1;
    IIC_Delay();
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值