IIC通信协议详解[转载]

article/2025/6/24 8:03:11

IIC的基本介绍

IIC的简介

IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。

  • IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
  • IIC总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

STM32的IIC接口

目前绝大多数的MCU都附带IIC总线接口,STM32也不例外。但是在本文中,我们不使用STM32的硬件IIC来读取24C02,而是通过软件的方式来模拟。

原因是因为:STM32的硬件IIC非常复杂,更重要的是它并不稳定,故不推荐使用。

 

IIC协议

IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。

先来看一下IIC总线的时序图:

这可能会比较复杂,可以先看一份简化了的时序图:

空闲状态

当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 

起始信号与停止信号

  • 起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;
  • 停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

应答信号

发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 

对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。

数据有效性

IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 

即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

数据的传达

在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

延时时间

 

IIC总线的数据传送

IIC总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(地址通过物理接地或者拉高),主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。

也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。

  • 主设备往从设备中写数据。数据传输格式如下:

淡蓝色部分表示数据由主机向从机传送,粉红色部分则表示数据由从机向主机传送。

写用0来表示(高电平),读用1来表示(低电平)。

  • 主设备从从设备中读数据。数据传输格式如下:

在从机产生响应时,主机从发送变成接收,从机从接收变成发送。之后,数据由从机发送,主机接收,每个应答由主机产生,时钟信号仍由主机产生。若主机要终止本次传输,则发送一个非应答信号,接着主机产生停止条件。

  •  主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:

在多主的通信系统中,总线上有多个节点,它们都有自己的寻址地址,可以作为从节点被别的节点访问,同时它们都可以作为主节点向其它的节点发送控制字节和传送数据。但是如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I2C总线上的仲裁。

I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。

这部分就暂时不介绍了,想要了解:可以参考链接浅谈I2C总线或I2C总线协议图解。

 

IIC底层驱动程序分析

现拟采用PB6、PB7来模拟IIC时序,其中:PB6为时钟线,PB7为数据线。

首先进行一些必要的宏定义:

  1. //IO方向设置
  2. #define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
  3. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
  4. //IO操作函数
  5. #define IIC_SCL PBout(6) //SCL
  6. #define IIC_SDA PBout(7) //SDA
  7. #define READ_SDA PBin(7) //输入SDA
  8. //IIC所有操作函数
  9. void IIC_Init(void); //初始化IIC的IO口
  10. void IIC_Start(void); //发送IIC开始信号
  11. void IIC_Stop(void); //发送IIC停止信号
  12. void IIC_Send_Byte(u8 txd); //IIC发送一个字节
  13. u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  14. u8 IIC_Wait_Ack(void); //IIC等待ACK信号
  15. void IIC_Ack(void); //IIC发送ACK信号
  16. void IIC_NAck(void); //IIC不发送ACK信号

由于IIC是半双工通信方式,因而数据线SDA可能会数据输入,也可能是数据输出,需要定义IIC_SDA来进行输出、READ_SDA来进行输入,与此同时就要对IO口进行模式配置:SDA_IN()和SDA_OUT()。

而时钟线SCL一直是输出的,所以就没有数据线SDA麻烦了。

  1. //初始化IIC
  2. void IIC_Init(void)
  3. {
  4. GPIO_InitTypeDef GPIO_InitStructure;
  5. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟
  6. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
  7. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
  8. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9. GPIO_Init(GPIOB, &GPIO_InitStructure);
  10. GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高,空闲状态
  11. }
  12. //产生IIC起始信号
  13. void IIC_Start(void)
  14. {
  15. SDA_OUT(); //sda线输出
  16. IIC_SDA=1;
  17. IIC_SCL=1;
  18. delay_us(4);
  19. IIC_SDA=0;    //START:when CLK is high,DATA change form high to low
  20. delay_us(4);
  21. IIC_SCL=0;    //钳住I2C总线,准备发送或接收数据
  22. }
  23. //产生IIC停止信号
  24. void IIC_Stop(void)
  25. {
  26. SDA_OUT();    //sda线输出
  27. IIC_SCL=0;
  28. IIC_SDA=0;    //STOP:when CLK is high DATA change form low to high
  29. delay_us(4);
  30. IIC_SCL=1;
  31. IIC_SDA=1;    //发送I2C总线结束信号
  32. delay_us(4);
  33. }
  34. //发送数据后,等待应答信号到来
  35. //返回值:1,接收应答失败,IIC直接退出
  36. // 0,接收应答成功,什么都不做
  37. u8 IIC_Wait_Ack(void)
  38. {
  39. u8 ucErrTime=0;
  40. SDA_IN(); //SDA设置为输入
  41. IIC_SDA=1;delay_us(1);
  42. IIC_SCL=1;delay_us(1);
  43. while(READ_SDA)
  44. {
  45. ucErrTime++;
  46. if(ucErrTime>250)
  47. {
  48. IIC_Stop();
  49. return 1;
  50. }
  51. }
  52. IIC_SCL=0;    //时钟输出0
  53. return 0;
  54. }
  55. //产生ACK应答
  56. void IIC_Ack(void)
  57. {
  58. IIC_SCL=0;
  59. SDA_OUT();
  60. IIC_SDA=0;
  61. delay_us(2);
  62. IIC_SCL=1;
  63. delay_us(2);
  64. IIC_SCL=0;
  65. }
  66. //不产生ACK应答
  67. void IIC_NAck(void)
  68. {
  69. IIC_SCL=0;
  70. SDA_OUT();
  71. IIC_SDA=1;
  72. delay_us(2);
  73. IIC_SCL=1;
  74. delay_us(2);
  75. IIC_SCL=0;
  76. }
  77. //IIC发送一个字节
  78. //返回从机有无应答
  79. //1,有应答
  80. //0,无应答
  81. void IIC_Send_Byte(u8 txd)
  82. {
  83. u8 t;
  84. SDA_OUT();
  85. IIC_SCL=0;            //拉低时钟开始数据传输
  86. for(t=0;t<8;t++)
  87. {
  88. //IIC_SDA=(txd&0x80)>>7;
  89. if((txd&0x80)>>7)
  90. IIC_SDA=1;
  91. else
  92. IIC_SDA=0;
  93. txd<<=1;
  94. delay_us(2);     //对TEA5767这三个延时都是必须的
  95. IIC_SCL=1;
  96. delay_us(2);
  97. IIC_SCL=0;
  98. delay_us(2);
  99. }
  100. }
  101. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  102. u8 IIC_Read_Byte(unsigned char ack)
  103. {
  104. unsigned char i,receive=0;
  105. SDA_IN();        //SDA设置为输入
  106. for(i=0;i<8;i++ )
  107. {
  108. IIC_SCL=0;
  109. delay_us(2);
  110. IIC_SCL=1;
  111. receive<<=1;
  112. if(READ_SDA)receive++;
  113. delay_us(1);
  114. }
  115. if (!ack)
  116. IIC_NAck();        //发送nACK
  117. else
  118. IIC_Ack();         //发送ACK
  119. return receive;
  120. }

这里是通过普通IO口(PB6、PB7)来模拟IIC时序的程序,其实本质上都是严格按照IIC的时序图进行的,认真读,仔细对比,应该是没有什么困难的。

就提一下:IIC_Read_Byte()函数,这个函数的参数表示读取一个字节之后,需要给对方应答信号或非应答信号。

 

普通IO口模拟IIC时序读取24C02

24C02芯片介绍

EEPROM (Electrically Erasable Programmable read only memory),带电可擦可编程只读存储器——一种掉电后数据不丢失的存储芯片。 

24Cxx芯片是EEPROM芯片的一种,它是基于IIC总线的存储器件,遵循二线制协议,由于其具有接口方便,体积小,数据掉电不丢失等特点,在仪器仪表及工业自动化控制中得到大量的应用。24Cxx在电路的作用主要是在掉电的情况下保存数据。

本文使用的是24C02芯片,总容量是2k个bit(256个字节)。这里芯片名称里的02代表着总容量。

24C02芯片的引脚分布和具体的作用见下图:

 

24C02芯片的引脚说明
引脚名称说明
A0-A2地址输入线
SDA数据线
SCL时钟线
WP写保护
GND、VCC提供电源

下图是本文中24C02和STM32的引脚连接图:

从图中可以看出:A0、A1、A2都为0。

对于并联在一条IIC总线上的每个IC都有唯一的地址。那么看一下从器件地址,可以看出对于不同大小的24Cxx,具有不同的从器件地址。由于24C02为2k容量,也就是说只需要参考图中第一行的内容:

根据图中的内容:如果是写24C02的时候,从器件地址为10100000(0xA0);读24C02的时候,从器件地址为10100001(0xA1)。

24C02芯片的时序图

这部分的内容应结合上文:I2C总线的数据传送的内容一起理解。

24C02字节写时序

对24C02芯片进行写字节操作的时候,步骤如下:

  1. 开始位,后面紧跟从器件地址位(0xA0),等待应答,这是为了在IIC总线上确定24C02的从地址位置;
  2. 确定操作24C02的地址,等待应答,也就是将字节写入到24C02中256个字节中的位置;
  3. 确定需要写入24C02芯片的字节,等待应答,停止位。

24C02字节读时序

对24C02芯片进行读字节操作的时候,步骤如下:

  1. 开始位,后面紧跟从器件地址位(0xA0),等待应答,这是为了在IIC总线上确定24C02的从地址位置;
  2. 确定操作24C02的地址,等待应答,也就是从24C02中256个字节中读取字节的位置;
  3. 再次开始位,后面紧跟从器件地址位(0xA1),等待应答;
  4. 获取从24C02芯片中读取的字节,发出非应答信号,停止位。

读取24C02芯片程序

  1. #define AT24C01 127
  2. #define AT24C02 255
  3. #define AT24C04 511
  4. #define AT24C08 1023
  5. #define AT24C16 2047
  6. #define AT24C32 4095
  7. #define AT24C64 8191
  8. #define AT24C128 16383
  9. #define AT24C256 32767
  10. //Mini STM32开发板使用的是24c02,所以定义EE_TYPE为AT24C02
  11. #define EE_TYPE AT24C02
  1. //初始化IIC接口
  2. void AT24CXX_Init(void)
  3. {
  4. IIC_Init();
  5. }
  6. //在AT24CXX指定地址读出一个数据
  7. //ReadAddr:开始读数的地址
  8. //返回值 :读到的数据
  9. u8 AT24CXX_ReadOneByte(u16 ReadAddr)
  10. {
  11. u8 temp=0;
  12. IIC_Start();
  13. if(EE_TYPE>AT24C16)            //为了兼容24Cxx中其他的版本
  14. {
  15. IIC_Send_Byte(0XA0); //发送写命令
  16. IIC_Wait_Ack();
  17. IIC_Send_Byte(ReadAddr>>8);    //发送高地址
  18. IIC_Wait_Ack();
  19. }else     IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
  20. IIC_Wait_Ack();
  21. IIC_Send_Byte(ReadAddr%256); //发送低地址
  22. IIC_Wait_Ack();
  23. IIC_Start();
  24. IIC_Send_Byte(0XA1); //进入接收模式
  25. IIC_Wait_Ack();
  26. temp=IIC_Read_Byte(0);     //读一个字节,非应答信号信号
  27. IIC_Stop();        //产生一个停止条件
  28. return temp;
  29. }
  30. //在AT24CXX指定地址写入一个数据
  31. //WriteAddr :写入数据的目的地址
  32. //DataToWrite:要写入的数据
  33. void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
  34. {
  35. IIC_Start();
  36. if(EE_TYPE>AT24C16)
  37. {
  38. IIC_Send_Byte(0XA0); //发送写命令
  39. IIC_Wait_Ack();
  40. IIC_Send_Byte(WriteAddr>>8);    //发送高地址
  41. }else
  42. {
  43. IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
  44. }
  45. IIC_Wait_Ack();
  46. IIC_Send_Byte(WriteAddr%256); //发送低地址
  47. IIC_Wait_Ack();
  48. IIC_Send_Byte(DataToWrite); //发送字节
  49. IIC_Wait_Ack();
  50. IIC_Stop();    //产生一个停止条件
  51. delay_ms(10);
  52. }
  53. //在AT24CXX里面的指定地址开始写入长度为Len的数据
  54. //该函数用于写入16bit或者32bit的数据.
  55. //WriteAddr :开始写入的地址
  56. //DataToWrite:数据数组首地址
  57. //Len :要写入数据的长度2,4
  58. void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
  59. {
  60. u8 t;
  61. for(t=0;t<Len;t++)
  62. {
  63. AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
  64. }
  65. }
  66. //在AT24CXX里面的指定地址开始读出长度为Len的数据
  67. //该函数用于读出16bit或者32bit的数据.
  68. //ReadAddr :开始读出的地址
  69. //返回值 :数据
  70. //Len :要读出数据的长度2,4
  71. u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
  72. {
  73. u8 t;
  74. u32 temp=0;
  75. for(t=0;t<Len;t++)
  76. {
  77. temp<<=8;
  78. temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
  79. }
  80. return temp;
  81. }
  82. //检查AT24CXX是否正常
  83. //这里用了24XX的最后一个地址(255)来存储标志字.
  84. //如果用其他24C系列,这个地址要修改
  85. //返回1:检测失败
  86. //返回0:检测成功
  87. u8 AT24CXX_Check(void)
  88. {
  89. u8 temp;
  90. temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX
  91. if(temp==0X55)return 0;
  92. else//排除第一次初始化的情况
  93. {
  94. AT24CXX_WriteOneByte(255,0X55);
  95. temp=AT24CXX_ReadOneByte(255);
  96. if(temp==0X55)return 0;
  97. }
  98. return 1;
  99. }
  100. //在AT24CXX里面的指定地址开始读出指定个数的数据
  101. //ReadAddr :开始读出的地址 对24c02为0~255
  102. //pBuffer :数据数组首地址
  103. //NumToRead:要读出数据的个数
  104. void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
  105. {
  106. while(NumToRead)
  107. {
  108. *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
  109. NumToRead--;
  110. }
  111. }
  112. //在AT24CXX里面的指定地址开始写入指定个数的数据
  113. //WriteAddr :开始写入的地址 对24c02为0~255
  114. //pBuffer :数据数组首地址
  115. //NumToWrite:要写入数据的个数
  116. void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
  117. {
  118. while(NumToWrite--)
  119. {
  120. AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
  121. WriteAddr++;
  122. pBuffer++;
  123. }
  124. }
  1. //要写入到24c02的字符串数组
  2. const u8 TEXT_Buffer[]={"WarShipSTM32 IIC TEST"};
  3. #define SIZE sizeof(TEXT_Buffer)
  4. int main(void)
  5. {
  6. u8 key;
  7. u16 i=0;
  8. u8 datatemp[SIZE];
  9. delay_init(); //延时函数初始化
  10. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  11. uart_init(115200); //串口初始化为115200
  12. LED_Init(); //初始化与LED连接的硬件接口
  13. LCD_Init(); //初始化LCD
  14. KEY_Init(); //按键初始化
  15. AT24CXX_Init(); //IIC初始化
  16. POINT_COLOR=RED;//设置字体为红色
  17. LCD_ShowString(30,50,200,16,16,"WarShip STM32");
  18. LCD_ShowString(30,70,200,16,16,"IIC TEST");
  19. LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  20. LCD_ShowString(30,110,200,16,16,"2015/1/15");
  21. LCD_ShowString(30,130,200,16,16,"KEY1:Write KEY0:Read"); //显示提示信息
  22. while(AT24CXX_Check())//检测不到24c02
  23. {
  24. LCD_ShowString(30,150,200,16,16,"24C02 Check Failed!");
  25. delay_ms(500);
  26. LCD_ShowString(30,150,200,16,16,"Please Check! ");
  27. delay_ms(500);
  28. LED0=!LED0;//DS0闪烁
  29. }
  30. LCD_ShowString(30,150,200,16,16,"24C02 Ready!");
  31. POINT_COLOR=BLUE;//设置字体为蓝色
  32. while(1)
  33. {
  34. key=KEY_Scan(0);
  35. if(key==KEY1_PRES)//KEY_UP按下,写入24C02
  36. {
  37. LCD_Fill(0,170,239,319,WHITE);//清除半屏
  38. LCD_ShowString(30,170,200,16,16,"Start Write 24C02....");
  39. AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
  40. LCD_ShowString(30,170,200,16,16,"24C02 Write Finished!");//提示传送完成
  41. }
  42. if(key==KEY0_PRES)//KEY1按下,读取字符串并显示
  43. {
  44. LCD_ShowString(30,170,200,16,16,"Start Read 24C02.... ");
  45. AT24CXX_Read(0,datatemp,SIZE);
  46. LCD_ShowString(30,170,200,16,16,"The Data Readed Is: ");//提示传送完成
  47. LCD_ShowString(30,190,200,16,16,datatemp);//显示读到的字符串
  48. }
  49. i++;
  50. delay_ms(10);
  51. if(i==20)
  52. {
  53. LED0=!LED0;//提示系统正在运行
  54. i=0;
  55. }
  56. }
  57. }

 

IIC总结

  1. 进行数据传送时,在SCL为高电平期间,SDA线上电平必须保持稳定,只有SCL为低时,才允许SDA线上电平改变状态。并且每个字节传送时都是高位在前;
  2. 对于应答信号,ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功;
  3. 如果从机需要延迟下一个数据字节开始传送的时间,可以通过把SCL电平拉低并保持来强制主机进入等待状态;
  4. 主机完成一次通信后还想继续占用总线在进行一次通信,而又不释放总线,就要利用重启动信号。它既作为前一次数据传输的结束,又作为后一次传输的开始;
  5. 总线冲突时,按“低电平优先”的仲裁原则,把总线判给在数据线上先发送低电平的主器件;
  6. 在特殊情况下,若需禁止所有发生在I2C总线上的通信,可采用封锁或关闭总线,具体操作为在总线上的任一器件将SCL锁定在低电平即可;
  7. SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。

 


http://chatgpt.dhexx.cn/article/UpmOe7Pb.shtml

相关文章

IIC通信协议学习

1.IIC简介 IIC&#xff1a;Inter-Integrated Circuit&#xff08;内部集成电路&#xff09; 需要两个管脚&#xff1a;SDA、SCL SPI协议&#xff1a;一个主设备对多个从设备&#xff0c;每增加一个从设备&#xff0c;需要增加一个端口CS* 特点&#xff1a;速度较快&#xff…

IIC总线设计①——IIC通信协议

目录 一、IIC&#xff08;Inter-Integrated Circuit&#xff09;总线介绍 二、IIC协议 &#xff08;一&#xff09;IIC通信过程 &#xff08;二&#xff09;起始信号和停止信号 程序 &#xff08;三&#xff09;应答信号和非应答信号 程序 &#xff08;四&#xff09;数…

STM32基于IIC通信协议的OLED模块使用(详解)

目录 前言 一、项目内容 实验简介 二、IIC模块 1、IIC协议简介 2、物理层 3、协议层 4、硬件IIC代码配置 5、软件模拟IIC配置 1、起始信号与停止信号 2、从机应答信号 3、数据的有效性 4、数据传输 三、OLED模块 1、软件配置 2、OLED原理 1、OLED初始化函数 …

IIC 通信协议 (一)

目录 引言 IIC协议 1、历史 2、特点 3、信号线 4、主从关系 5、通信过程 6、协议规范 地址 1、器件地址 2、存储器地址 读写时序 1、写时序 1.1、单字节写时序 1.2、连续写时序 2、读时序 2.1、单字节读时序 2.2、连续读时序 参考声明 引言 这个专栏闲置好…

基础通信协议之 IIC (I2C) 详细讲解

IIC是当今嵌入式应用中最常见的串行通信协议之一。对比OneWire严苛的时序要求&#xff0c;SPI等更多的线缆要求&#xff0c;IIC处于一个折中的位置&#xff1a;不那么多的2根线缆的硬件要求&#xff0c;不那么复杂严苛的时序要求&#xff0c;便可进行多主多从的双向通信&#x…

IIC 通信协议 (二)

目录 引言 子模块设计 思路 单字节 IIC 发送模块 思路 Verilog 源码 多字节发送控制模块 思路 Verilog 源码 仿真 思路 test bench 仿真结果 参考声明 引言 本篇博文承接前文&#xff0c;继续做 IIC 通信协议 FPGA实现相关的内容。用Verilog 编写一个 IIC 通信控…

IIC通信协议(硬件实现IIC通信详解I)

IIC通信协议 什么是IIC协议协议层起始信号和停止信号数据的有效性 什么是IIC协议 I2C&#xff08;Inter-Integrated Circuit&#xff09;通讯协议是由 Phiilps 公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准…

详解通信协议之IIC通信协议

详解通信协议之IIC通信协议 本文结合AT24C02对IIC通信协议原理进行了描述。 IIC通信协议(以AT24C02为例) IIC通讯协议(Inter&#xff0d;Integrated Circuit)是由 Philips 公司开发双向同步半双工串行总线&#xff0c;只需要两根线(SDA、SCL)即可在连接于总线上的器件之间传…

IIC(I2C)通信协议详解

简介 I2C 是飞利浦公司设计的&#xff0c;一种很常见的总线协议&#xff0c; I2C 使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线)&#xff0c;另外一条是SDA(串行数据线)&#xff0c;这两条数据线需要接上拉电阻&#xff0c;总线空闲的时候 SCL 和 SDA …

IIC 通信协议

一、IIC 通信协议介绍 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。 如今主要在服务器管理中使用&#xff0c;其中包括单个组件状态的通信。例如管理员可对各个组件进行查询&#xff0c;以管理系统…

三大通信协议(二):IIC通信协议

目录 1. 概念2. 硬件连接3. 数据传输协议3.1 开始信号3.2 地址位3.3 读写位&#xff08;R/W&#xff09;3.4 应答位&#xff08;ACK / NACK&#xff09;3.5 数据位&#xff08;8Bit&#xff09;3.6 停止信号 4. 软件编写4.1 初始化4.2 开始信号4.3 IIC发送一个字节数据4.4 IIC读…

IIC通信协议总结

&#xff08;1&#xff09;概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线&#xff0c;该总线由NXP&#xff08;原PHILIPS&#xff09;公司设计&#xff0c;多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场合使用&#xff0c;传输距离短&#xff0c;任意时…

IIC通信协议,搞懂这篇就够了

注&#xff1a;公众号后台发送 “IIC” 即可获取基于STM32上实现软件模拟IIC的完整代码。 I2C(IIC)属于两线式串行总线&#xff0c;由飞利浦公司开发用于微控制器(MCU)和外围设备(从设备)进行通信的一种总线&#xff0c;属于一主多从(一个主设备(Master)&#xff0c;多个从设备…

IIC通讯协议

一、简介 IIC&#xff08;Inter-integerted Circuit&#xff09;集成电路总线&#xff0c;该通信协议由NXP&#xff08;原PHILIPS&#xff09;公司设计&#xff0c;多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场景下使用&#xff0c;传输距离短&#xff0c;任意…

搜狗搜索正式接入微信公众号

搜狗搜索正式接入微信公众号 6月9日中午消息&#xff0c;搜狗搜索今日宣布正式接入微信公众号数据。用户将在搜狗搜索页面查询和浏览微信公众号文章。 据悉&#xff0c;在搜狗搜索框中输入微信公众号关键词&#xff0c;便可在搜索结果页中查看相关微信公众号的文章列表&#xf…

Python爬虫 selenium自动化 利用搜狗搜索爬取微信公众号文章信息

少年最好的地方就是:虽然嘴上说要放弃,心底却总会憋着一口气。——刘同 文章目录 一、需求和网页分析二、selenium爬虫一、需求和网页分析 URL:https://weixin.sogou.com/ 你是否有特别喜欢的一些公众号文章,比如说关于网易云热评的。 我那么多遗憾,那么多期盼,你知道…

RSS订阅微信公众号初探-feed43

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

python爬虫爬取微信公众号历史文章链接

一、最近公司有了要爬取微信公众号文章链接的需求&#xff0c;之前最初接触爬公众号文章的时候&#xff0c;用的是搜狗微信&#xff0c;在这个上面可以搜到相关的微信公众号文章&#xff0c;但是这些链接是有时效性的&#xff0c;第二天链接就打不开了&#xff08;不知道现在是…

python抓取搜狗微信公众号文章

初学python&#xff0c;抓取搜狗微信公众号文章存入mysql mysql表&#xff1a; 代码&#xff1a; import requests import json import re import pymysql# 创建连接 conn pymysql.connect(host你的数据库地址, port端口, user用户名, passwd密码, db数据库名称, charsetut…

搜狗微信文章采集php,[造轮子]爬取搜狗微信公众号文章

背景&#xff1a;想做一个公众号文章资源APP&#xff0c;发现搜狗有搜索公众号文章功能&#xff0c;果断开撸。http://wxiread.com (用CMS搭了个简易的站)。 Step1.分析栏目及接口 搜狗分了20个栏目&#xff0c;分别是 热门,推荐,段子手,养生堂,私房话… 对应地址从 /pcindex/p…