软件iic协议

软件IIC协议
  • 硬件连接
    时钟线:SCL线(外接4.7K欧姆的电阻)
    数据线:SDA线(外接4.7K欧姆的电阻)
    D0线:控制外设的地址
    SCL、SDA都有普通gpio口代替,通过控制gpio口的输入输出状态来模拟iic的读写过程,这就是软件iic

  • iic的传输数据最高位400kHz

  • iic的时序图
    在这里插入图片描述

  • 待机时:SDA线和SCL线都处于高电平

  • 启动条件:在·SCL为高电平的状态下,SDA有高电平转变为低电平(下降沿)
    void iic_start(void)
    {
    SDA_Write(); //设置SCL、SDA对应的端口为输出状态
    iic_SCL_1; //SCL置1
    iic_SDA_1; //SDA置1
    delay();
    iic_SDA_0; //SDA置0
    delay();
    iic_SCL_0; //SCL置0
    delay();
    }

  • 结束条件:在SCL为高电平状态下,SDA由低电平转变为高电平(上升沿)
    void iic_stop(void)
    {
    SDA_Write();
    iic_SDA_0;
    iic_SCL_0;
    delay();
    iic_SCL_1;
    iic_SDA_1;
    delay();
    }

  • 应答信号:在SCL为高电平的状态下,SDA为低电平(mpu作为从机时使用)
    void iic_ack(void)
    {
    iic_SCL_0;
    SDA_Write();
    delay();
    iic_SDA_0;
    delay();
    iic_SCL_1;
    delay();
    iic_SCL_0;
    }

  • 非应答信号:在SCL为高电平的状态下,SDA为高电平(mpu作为从机时使用)
    void iic_Nack(void)
    {
    iic_SCL_0;
    delay();
    SDA_Write();
    iic_SDA_1;
    delay();
    iic_SCL_1;
    delay();
    iic_SCL_0;
    }

  • 等待应答信号

  • 返回0:有应答;返回1:无应答
    uint8_t iic_Waitack(void)
    {
    uint8_t i;
    SDA_Read(); //GPIO口设置为读取状态
    iic_SDA_1;
    delay();
    iic_SCL_1;
    delay();
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))
    { i++; //读取GPIO在一段时间内的值,若不为0,则无应答信号
    if(i>250)
    {
    iic_stop(); //无应答信号,返回待机状态
    return 1;
    }
    }
    iic_SCL_0;
    delay();
    return 0;
    }

  • iic发送数据函数(7位数据位+1位读写状态位)
    不同设备的读写状态位可能不同(可以是最高位,也可以是最低位)
    0:读取;1:写入
    void iic_Sendbyte(uint8_t txd)
    {
    uint8_t i;
    SDA_Write();
    iic_SCL_0;
    /*
    从高7位开始写入数据 ,数据由高位到低位逐位读取
    如果SDA的数据为1,即为1;否则即为0
    /
    for(i=0;i<8;i++)
    {
    if((txd & 0x80)>>7) //最高位为读写状态位
    iic_SDA_1;
    else
    iic_SDA_0;
    /
    保证数据有效性,在SDA为某个状态时经历1个周期的SCL /
    /
    左移1个字节 */
    txd<<=1; //数据左移一位
    delay();
    iic_SCL_1;
    delay();
    iic_SCL_0;
    delay();
    }
    }

  • iic读取数据函数
    当ack为1时,返回应答信号,读取结束;当ack返回1时,返回非应答信号,读取结束。
    uint8_t iic_Readbyte(uint8_t ack)
    {
    uint8_t i;
    uint8_t value = 0;
    SDA_Read();
    for(i=0;i<8;i++)
    {
    iic_SCL_0;
    delay();
    iic_SCL_1;
    /* 最高位为读写控制位,故从第7位开始读取数据 /
    value<<=1;
    /
    读取SDA口的电平状态 */
    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))
    {
    value++;
    }
    }
    if(!ack)
    iic_Nack();
    else
    iic_ack();
    return value;
    }

  • 完整iic写数据和读数据通讯过程示例
    void write_data(uint8_t data)
    {
    iic_start();
    iic_Sendbyte(address); //设备地址
    iic_Waitack();
    iic_Sendbyte(0x40); //寄存器地址
    iic_Waitack();
    iic_Sendbyte(data); //数据
    iic_Waitack();
    iic_stop();
    }
    void Read_data(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
    {
    iic_start();
    iic_Sendbyte(addr); //设备地址
    iic_Waitack(); //等待应答信号
    iic_Sendbyte(reg); //写入寄存器地址
    iic_Waitack(); //等待应答信号
    iic_start(); //启动信号
    iic_Sendbyte(addr|1); //设置为读取状态
    iic_Waitack();
    while(len)
    {
    if(len == 1)
    *buf = iic_Readbyte(0);
    else
    *buf = iic_Readbyte(1);
    len–;
    buf++;
    }
    iic_stop(); //读取结束,进入待机模式
    }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值