I2C通信协议底层编程代码

主要是模拟I2C通信的代码,有需要的可以自行复制使用,具体的引脚定义自己可以写在头文件中

//开始,SCL为高电平,SDA从高电平到低电平
//bit1为SDA。bit2为SCL

void IC_Start(void)
{
  P1DIR |=BIT1;   //设置为输出口
  P1OUT |=BIT2;     //SCL=1;
  P1OUT |=BIT1;     //SDA=1;
  nop();            //延迟
  nop();
  P1OUT &=(~BIT1);  //SDA=0;
  nop();
  nop();
  P1OUT &=(~BIT2);  //SCL=0;
}

//结束,SCL为高电平,SDA从低电平到高电平
void  IC_Stop(void)
{
  P1OUT &=(~BIT2);  //SCL=0;
  P1DIR |=BIT1;   //设置为输出口
  P1OUT &=(~BIT1);  //SDA=0;
  nop();
  nop();
  P1OUT |=BIT2;     //SCL=1;
  nop();            //延迟
  nop();
  P1OUT |=BIT1;     //SDA=1;
}

//写一个字节
unsigned char IC_WriteByte(unsigned char wdata)
{
  unsigned char i;
  P1DIR |=BIT1;   //设置为输出口
  for(i=0;i<8;i++){
    P1OUT &=(~BIT2);  //SCL=0;
    nop();
    nop();
    if(wdata&0x80)
      P1OUT |=BIT1;     //从高位开始读,根据数据来读高电平则SDA=1,低电平则SDA=0;
    else P1OUT &=(~BIT1);
    nop();
    nop();
    P1OUT |=BIT2;     //SCL=1;
    wdata<<=1;        //左移一位
  }
  P1OUT &=(~BIT2);  //SCL=0;
  nop();
  nop();
  P1DIR &=(~BIT1);   //设置为输入口
  P1OUT |=BIT2;     //SCL=1;
  i=0;
  while((P1IN & BIT1) >> 1)//用来判断ACK信号
  {
    if(++i>12){
      P1OUT &=(~BIT2);  //SCL=0;
      return(0);
    }
  }
  P1OUT &=(~BIT2);  //SCL=0;
  return(1);
}

//读一个字节
unsigned char IC_ReadByte(void){
  unsigned char i;
  unsigned char IC_data=0;
  P1OUT &=(~BIT2);  //SCL=0;
  P1DIR |=BIT1;   //设置为输出口
  P1OUT |=BIT1;     //SDA=1;
  P1DIR &=(~BIT1);   //设置为输入口
  for(i=0;i<8;i++){
    P1OUT |=BIT2;     //SCL=1;
    nop();
    nop();
    IC_data<<=1;          //从低位开始读入
    IC_data|=((P1IN & BIT1) >> 1);
    nop();
    P1OUT |=BIT2;     //SCL=1;
    nop();
    P1OUT &=(~BIT2);  //SCL=0;
    nop();
  }
  nop();
  nop();
  P1OUT &=(~BIT2);  //SCL=0;
  P1DIR &=(~BIT1);   //设置为输入口
  P1OUT &=(~BIT1);  //SDA=0;
  return(IC_data);
}

//从寄存器地址addr开始读num个字节保存在*EEbuf中
unsigned char IC_readEEone(unsigned char *EEbuf,unsigned char addr,unsigned char num){
  unsigned char i;
  IC_Start();
  if(IC_WriteByte(0x64)==0){   //发送分设备的地址以及写请求
    IC_Stop();return(0);
  }
  if(IC_WriteByte(addr)==0){    // 发送要读取的第一个寄存器的地址
    IC_Stop();return(0);
  }
  IC_Start();
  if(IC_WriteByte(0x65)==0){    //发送分设备的地址以及读请求
    IC_Stop();return(0);
  }
  for(i=0;i<num-1;i++)
  {
    EEbuf[i]=IC_ReadByte(); //读取
    P1DIR |=BIT1;   //设置为输出口
    P1OUT &=(~BIT1);  //SDA=0;主设备发送ACK信号
    P1OUT |=BIT2;     //SCL=1;
  }
  EEbuf[num-1]=IC_ReadByte();
  P1DIR |=BIT1;   //设置为输出口
  P1OUT |=BIT1;     //SDA=1;
  nop();
  P1OUT |=BIT2;     //SCL=1;
  IC_Stop();
  return(1);
}

//把*EEbuf中的num个字节写入寄存器地址addr开始的寄存器中
unsigned char IC_writeEEone(unsigned char *EEbuf,unsigned char addr,unsigned char num){
  unsigned char i;
  IC_Start();
  if(IC_WriteByte(0x64)==0){   //发送分设备的地址以及写请求
    IC_Stop();return(0);
  }
  if(IC_WriteByte(addr)==0){    // 发送要写入的第一个寄存器的地址
    IC_Stop();return(0);
  }
  for(i=0;i<num;i++)
  {
    if(IC_WriteByte(EEbuf[i])==0){   //写入数据到寄存器中
      IC_Stop();
      return(0);
    }
  }
  IC_Stop();
  nop();
  nop();
  P1OUT &=(~BIT1);  //SDA=0;
  P1OUT &=(~BIT2);  //SCL=0;
  return(1);
}

猜你喜欢

转载自blog.csdn.net/qq_27524749/article/details/88813357