IIC

时序:

 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

/*
每一个IIC设备必须有一个地址
一共8位 其中前7位根硬件有关 最后一位表示读写位

为了防止IIC地址冲突,设备端不会IIC地址写死
预留几位,可以根据电路改变地址

A0 A1 A2  接低端
1010000  R/W


存储设备
24c02   字符类型存储芯片
256个字节  0~255
*/

//gpio模拟IIC   
//所谓GPIO模拟总线,用GPIO的高低电平模拟总线通信的时序
//总线 设备分离的思想
//myiic.c  只实现IIC 协议的部分
//初始化¯IIC
void IIC_Init(void)
{            
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIO

  //GPIOB8,B9初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
    
    IIC_SCL=1; //空闲状态,空闲的时候要拉高
    IIC_SDA=1;
}
//产生IIC起始信号

//IIC_Start()
//IIC_Send_Byte(0x5a)
//IIC_Wait_Ack() //等待应答不处理
//IIC_Stop()

//iic  clk(时钟线) pb8   sda(数据线)  PB9
//24c02 硬件手册中  IIC 时钟高电平 最低0.6us
//低电平 最低 1.2us
void IIC_Start(void)
{
    SDA_OUT();     //sda线输出
    IIC_SDA=1;            
    IIC_SCL=1;  
    delay_us(2);
     IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    delay_us(2);
    IIC_SCL=0;//钳住IIC总线,准备发送或接收数据
}      
//产生IIC停止信号
void IIC_Stop(void)
{
    SDA_OUT();//sda线输出
    IIC_SCL=0;
    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
     delay_us(2);
    IIC_SCL=1; 
    delay_us(1);
    IIC_SDA=1;//发送IIC总线结束信号
    delay_us(2);                                   
}
//等待应答信号到到
//返回值:1,接收应答失败
//        0,接收到应答成功
u8 IIC_Wait_Ack(void)
{
    u8 ucErrTime=0;
    SDA_IN();      //SDA设置为输入
    delay_us(1);       
    IIC_SCL=1;
    delay_us(1);     
    while(READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL=0;//ʱÖÓÊä³ö0        
    return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=0;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}
//不产生ACK应答        
void IIC_NAck(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=1;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}                                          
//IIC发送一个字节
//返回从机有无应答
//1有应答
//0无应答
//0X5A  01011010
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
      SDA_OUT();     //主机发送 输出模式
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
      IIC_SDA=(txd&0x80)>>7; //获取最高位,赋值给SDA数据线
            
      txd<<=1;       
            delay_us(1); //  
            IIC_SCL=1;
            delay_us(1); 
            IIC_SCL=0;    
            delay_us(1);
    }     
}         
//读1个字节,ack=1时, 发送ACK, ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{//1010
    unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
    {
      IIC_SCL=0; 
      delay_us(2);
            IIC_SCL=1;
      receive<<=1;
      if(READ_SDA)receive++;  
            delay_us(1); 
  }                     
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK
    return receive;
}
原文地址:https://www.cnblogs.com/baoshulin/p/6194686.html