51单片机的IIC总线

一、IIC
(一)、IIC有什么作用
51单片机的IIC总线_第1张图片 51单片机的IIC总线_第2张图片
穿插:
上垃电阻一般接电源,下拉电阻一般接地

上拉电阻作用:
1、增加驱动电流
2、让线悬空电平不好确定,让总线在浮空的状态下,有确定的电平,滤除干扰

(二)、IIC通信协议
51单片机的IIC总线_第3张图片
1、起始信号
SCL为高电平时,SDA由高变低
SCL为高电平时,SDA由低变高

函数:
void iic_start()
{
    SDA = 1;//首先操作SDA,再操作SCK,防止SCK在高电平时,SDA出现高低电平的变化
      SCK = 1;
      delay_us(1);//10us
      SDA = 0;
      delay_us(1);//10us

      SCK = 0;//钳住总线,让iic总线失效
}

void iic_stop()
{
    SDA = 0;
      SCK = 1;
      delay_us(1);
      SDA = 1;
      delay_us(1);

      SCK = 0;
}

2、IIC总线的数据传送
规定:
SCK(时钟线)为1时,数据必须保持稳定
SCK为0时,数据允许变化
传送一个字节,先发数据最高位,再发次高位,直至最低位

IIC发送数据函数
unsigned char iic_send_byte(unsigned char byte)
{
    unsigned char i;

      for(i =0; i < 8; i++)
      {
              SDA = byte & 0x80;//51中,若unsigned char 赋给一个bit类型的,则bit类型的值当unsigned char非0时为1,                                                                 否则为0
              SCK = 1; //先给SCK赋值,保持时钟为高电平时,数据稳定
              delay_us(1);//10us
              SCK = 0;
              byte <<= 1;
        }
        //检测应答信号
        SDA = 1;
        SCK = 1;
        delay_us(1);//10us
     
        if(0 == SDA)
        {
              SCK = 0;
              return SUCC;
        }
        else
        {
              SCK = 0;
              return FAIL;
        }
}

IIC接收数据函数

unsigned char iic_rcv_byte()
{
    unsigned char i;
      unsigned char temp;

      SDA = 1;//防止上一次操作将SDA给拉低

      for(i = 0; i < 8; i++)
      {
              SCK = 0;
              delay_us(1);
              SCK = 1;
              delay_us(1);

              temp <<= 1;//发送最高位,先放在最低位,然后移位,一直移到第八次

              if(1 == SDA)
                {
                      temp += 1;//如果SDA为0,为temp+=0,所以省略
                }
        }

        SCK = 0;//钳住总线
        return temp;

}

3、应答信号和非应答信号
应答:在SCK为高电平期间,接收设备将SDA拉低为低电平,

应答信号函数:
void iic_ack()//应答函数
{
    SDA = 0;
      SCK = 1;
      delay_us(1);

      SCK = 0;//钳住总线
}

在发送函数末尾可以添加:
        //检测应答信号
        SDA = 1;
        SCK = 1;
        delay_us(1);//10us
     
        if(0 == SDA)
        {
              SCK = 0;
              return SUCC;
        }
        else
        {
              SCK = 0;
              return FAIL;
        }

非应答信号:
void iic_noack()//非应答信号
{
    SDA = 1;
      SCK = 1;
      delay_us(1);

      SCK = 0;//钳住总线
}

二、EEPROM
型号                    容量
AT24C02        256bit  (开发板)  
AT24C04        512bit
AT24C08        1024bit
AT24C16        2048bit

关于设备的地址:
51单片机的IIC总线_第4张图片
对EEPROM写入
unsigned char at24c02_send_str(unsigned char device_addr,unsigned char rom_addr,unsigned char *str,unsigned char num)
{
    unsigned char result;
      unsigned char i;

      iic_start();

      result = iic_send_byte(device_addr);
      if(FAIL == result)
        {
              return FAIL;
        }

      result = iic_send_byte(rom_addr);
      if(FAIL == result)
        {
              return FAIL;
        }

        for(i = 0; i < num; i++)
      {
                result = iic_send_byte(*str++);

                if(FAIL == result)
                {
                        return FAIL;
                }
        }

        iic_stop();

        return SUCC;
}

对EERPOM读取:
unsigned char at24c02_rcv_str(unsigned char device_addr,unsigned char rom_addr,unsigned char *str,unsigned char num)
{
    unsigned char result;
      unsigned char i;

      iic_start();

      result = iic_send_byte(device_addr);
      if(FAIL == result)
        {
              return FAIL;
        }

      result = iic_send_byte(rom_addr);
      if(FAIL == result)
        {
              return FAIL;
        }

        iic_start();

      result = iic_send_byte(device_addr + 1);
      if(FAIL == result)
        {
              return FAIL;
        }

        for(i = 0; i < num - 1; i++)
      {
                *str++ = iic_rcv_byte();            

        iic_ack();                    
        }

        *str = iic_rcv_byte();

        iic_noack();
        iic_stop();

        return SUCC;
}

















你可能感兴趣的:(C51)