STM32-IIC协议详解

[复制链接]
发表于 2026-2-10 06:41:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、IIC简介

        I²C(Inter-Integrated Circuit)协议由飞利浦公司于1980年代开辟,是一种用于集成电路间短隔断通讯的串行协议。它计划用于毗连低速外围装备,特殊得当于必要简单数据交换的场景。I²C协议利用两根信号线:SCL(串行时钟线)和SDA(串行数据线)。这些线缆通过开漏(Open-Drain)输出布局与外接上拉电阻共同工作,以包管数据传输的稳固性和可靠性。I²C协议支持多主机和多从机的通讯模式,装备通过唯一的地点举行辨认。地点长度可以是7位或10位,使得I²C可以满意差别规模的体系需求。
二、时序分析


  •         起始条件:SCL高电平期间,SDA从高电平切换到低电平。
  •         停止条件:SCL高电平期间,SDA从低电平切换到高电平。

示例:
  1. //产生IIC起始信号
  2. void IIC_Start(void)
  3. {
  4.         SDA_OUT();     //sda线输出
  5.         IIC_SDA=1;                    
  6.         IIC_SCL=1;
  7.         delay_us(4);
  8.         IIC_SDA=0;//START:when CLK is high,DATA change form high to low
  9.         delay_us(4);
  10.         IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
  11. }
  12. //产生IIC停止信号
  13. void IIC_Stop(void)
  14. {
  15.         SDA_OUT();//sda线输出
  16.         IIC_SCL=0;
  17.         IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
  18.         delay_us(4);
  19.         IIC_SCL=1;
  20.         IIC_SDA=1;//发送I2C总线结束信号
  21.         delay_us(4);                                                                  
  22. }
复制代码



  • 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后开释SCL,从机将在SCL高电平期间读取数据位,以是SCL高电平期间SDA不答应有数据变革,依次循环上述过程8次,即可发送一个字节。

示例:
  1. //IIC发送一个字节
  2. //返回从机有无应答
  3. //1,有应答
  4. //0,无应答                          
  5. void IIC_Send_Byte(u8 txd)
  6. {                        
  7.     u8 t;   
  8.         SDA_OUT();             
  9.     IIC_SCL=0;//拉低时钟开始数据传输
  10.     for(t=0;t<8;t++)
  11.     {              
  12.         IIC_SDA=(txd&0x80)>>7;
  13.         txd<<=1;           
  14.                 delay_us(2);   
  15.                 IIC_SCL=1;
  16.                 delay_us(2);
  17.                 IIC_SCL=0;       
  18.                 delay_us(2);
  19.     }         
  20. }
复制代码



  • 吸收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后开释SCL,主机将在SCL高电平期间读取数据位,以是SCL高电平期间SDA不答应有数据变革,依次循环上述过程8次,即可吸收一个字节(主机在吸收之前,必要开释SDA)。


示例:
  1. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
  2. u8 IIC_Read_Byte(unsigned char ack)
  3. {
  4.         unsigned char i,receive=0;
  5.         SDA_IN();//SDA设置为输入
  6.     for(i=0;i<8;i++ )
  7.         {
  8.         IIC_SCL=0;
  9.         delay_us(2);
  10.                 IIC_SCL=1;
  11.         receive<<=1;
  12.         if(READ_SDA)receive++;   
  13.                 delay_us(1);
  14.     }                                         
  15.     if (!ack)
  16.         IIC_NAck();//发送nACK
  17.     else
  18.         IIC_Ack(); //发送ACK   
  19.     return receive;
  20. }
复制代码



  • 发送应答:主机在吸收完一个字节之后,在下一个时钟发送一位数据,数据0体现应答,数据1体现非应答 吸收应答:主机在发送完一个字节之后,在下一个时钟吸收一位数据,判定从机是否应答,数据0体现应答,数据1体现非应答(主机在吸收之前,必要开释SDA)。

示例:
  1. //等待应答信号到来
  2. //返回值:1,接收应答失败
  3. //        0,接收应答成功
  4. u8 IIC_Wait_Ack(void)
  5. {
  6.         u8 ucErrTime=0;
  7.         SDA_IN();      //SDA设置为输入  
  8.         IIC_SDA=1;delay_us(1);          
  9.         IIC_SCL=1;delay_us(1);         
  10.         while(READ_SDA)
  11.         {
  12.                 ucErrTime++;
  13.                 if(ucErrTime>250)
  14.                 {
  15.                         IIC_Stop();
  16.                         return 1;
  17.                 }
  18.         }
  19.         IIC_SCL=0;//时钟输出0           
  20.         return 0;  
  21. }
  22. //产生ACK应答
  23. void IIC_Ack(void)
  24. {
  25.         IIC_SCL=0;
  26.         SDA_OUT();
  27.         IIC_SDA=0;
  28.         delay_us(2);
  29.         IIC_SCL=1;
  30.         delay_us(2);
  31.         IIC_SCL=0;
  32. }
  33. //不产生ACK应答                    
  34. void IIC_NAck(void)
  35. {
  36.         IIC_SCL=0;
  37.         SDA_OUT();
  38.         IIC_SDA=1;
  39.         delay_us(2);
  40.         IIC_SCL=1;
  41.         delay_us(2);
  42.         IIC_SCL=0;
  43. }
复制代码

 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表