请求老司机解答,看不懂

2019-07-15 08:13发布

#include<reg52.h>
#include<intrins.h>


#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit SDA=P3^6;
sbit SCL=P3^7;


//产生总线起始信号号
void I2CStart()
{
      SCL=1;
        SDA=1;
        I2CDelay();  //确保SDA产生下降沿信号时SCL为高电平
        SDA=0;            //拉低SDA产生一个下降沿
        I2CDelay();  //延时确保产生下降沿后稳定
        SCL=0;            //此时拉低SCL后SDA可变,即可以准备发送的信号
       
}
//产生总线停止信号
void I2CStop()
{
      SCL=0;            //拉低SDA,SCL
        SDA=0;          
        I2CDelay();
        SCL=1;            // 拉低SCL
        I2CDelay();  //确保SDA产生上升沿时,SCL为低电平。
        SDA=1;            //产生一个上升沿
        I2CDelay();  //
}
//I2C总线写操作,dat为待写入的字节
bit IC2Write(unsigned char dat)
{
      bit ACK;    //用与暂存丛机应答的值
        unsigned char mask;  //用于探测写入字节内某一位掩码的变量
        for(mask=0x80;mask!=0;mask>>=1)  //主机要发送的数据,先发送高位再发送低位                  此处有疑问
        {
               if(mask&dat==0)                     //dat不是一位么,I2C总线是一位一位的发送的,这里按位与后不是一个char型与一位与么。懵逼请教大能。萌新。后面读操作也类似。
                  {
                        SDA=0;
                  }
                  else
                  {
                        SDA=1;
                  }
                  I2CDelay();             //延时使其保持一段时间
                  SCL=1;            //拉高SCL
                  I2CDelay();                //再拉高SCL期间,SDA不可变。因为此时丛机会读取SDA,若SDA改变,则读取可能错误
                  SCL=0;           //再拉低SCL完成一个位周期          
        }
        SDA=1;               //8位数据发送完毕后,主机必须释放SDA线,以便从机进行应答
        I2CDelay();                  //丛机通过拉低或拉高SDA进行应答
        SCL=1;                          //拉高SCL从机即能应答
        ACK=SDA;             //读取此时SDA的值即为从机的应答值
        I2CDelay();
        SCL=0;              //再拉低SCL完成应答位
        return ~ACK;        //将应答值返回调用其的函数0表示成功,1表示发送失败。此处~为正常逻辑
}
//I2C总线的读操作,并发送非应答信号,返回值为读到的字节
unsigned char I2CReadyNAck()
{
     unsigned char mask;
        unsigned char dat;    //所读数据缓冲区
        SDA=1;                        //读之前自己引脚为高电平 与按键类似,避免占用总线
        for(mask=0x80;mask!=0;mask>>=1)
        {
               I2CDelay();
                  SCL=1;
                  if(SDA==0)
                  {
                       dat&=~mask;                //将dat对应的位清零
                  }
                  else
                  {
                       dat|=mask;
                  }
                  I2CDelay();
                  SCL=0;                                //再拉低SCL以使丛机发送下一位
        }
        SDA=1;                                        //当丛机将8位数据发送完毕后,拉高SDA,发送非应答信号
        I2CDelay();
        SCL=1;
        I2CDelay();
        SCL=0;                                          //再次拉低SCL完成非应答位,并保持住总线
        return dat;                          //将读到的数据返回               
}
//I2C总线读操作,并发送应答信号,返回值位为读到的字节
unsigned char I2CReadyAck()
{
    unsigned char mask;
    unsigned char dat;  //所读字节缓冲区
    SDA=1;             //确保主机释放SDA
    for(mask=0x08;mask!=0;mask>>=1)
    {
         I2CDelay();
            SCL=1;
            if(SDA==0)
            {
                dat&=~mask;
            }
            else(dat|=mask);
            I2CDelay();
            SCL=0;          //在拉低SCL,以使丛机发送出下一位
    }
    SDA=0;         //8为数据发送完毕后,拉低SDA,发送应答信号
    I2CDelay();
    SCL=1;        //拉高SCL
    I2CDelay();
    SCL=0;        //再拉低SCL完成应答位,并保持住总线            此处保持住总线是扫描意思?
    return dat;
}
请教老司机解答,实在蒙蔽,有些注释是我自己理解注释的有错误老司机见谅

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。