type
status
date
slug
summary
tags
password
category
Property
Feb 1, 2023 03:14 PM
icon
I2C通信协议
目的:在单片机和外部模块连接少量的几根线,实现单片机读写外部模块寄存器的功能
即使外挂芯片的各种寄存器不在STM32内部,仍然可以通过通信协议,实现读写外挂芯片寄存器的功能,从而完全掌控外挂芯片
不同于串口通信:两根通信线,全双工
异步时序的好处就是省一根时钟线,节省资源,缺点是对时间要求严格,对硬件电路的依赖较严重
同步时序的好处就是对时间要求不严格,对硬件不怎么依赖,缺点是多一根时钟线
- I2C总线(Intel IC BUS)是一种通用数据总线
- 两根通信线:SCL(Serial Clock,串行时钟线,一根时钟线,使用同步时序,降低对硬件的依赖),SDA(Serial Data,串行数据线,一根数据线兼具发送和接收,变全双工为半双工,最大化利用资源)
- 同步,半双工
- 带数据应答
- 支持总线挂载多设备(一主多从,多主多从)
在总线冲突时,I2C协议会进行仲裁,仲裁胜利的一方取得总线控制权,失败的一方自动变回从机
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa2430342-21ff-4dbd-8f5e-213440d63668%2FUntitled.png?table=block&id=d8e65a87-3a1b-49f0-9215-bbb822282212&t=d8e65a87-3a1b-49f0-9215-bbb822282212&width=856&cache=v2)
对于SCL,主机拥有SCL的绝对控制权,所以主机的SCL可以配置成推挽输出(实际上也配置为开漏输出模式,因为在多主机模式下会利用到线与),所有从机的SCL都配置成浮空输入或者上拉输入,数据流向是:主机发送,所有从机接收
为了避免SDA没协调好导致一个输出高,一个输出低的电源短路问题,I2C的设计是,禁止所有设备输出强上拉的高电平,只有用上拉电阻来的弱上拉高电平
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F885be7d3-ce4f-4389-9791-af97838d3697%2FUntitled.png?table=block&id=2ce2bcdb-eff8-4a4d-8d71-8b5c46831913&t=2ce2bcdb-eff8-4a4d-8d71-8b5c46831913&width=866&cache=v2)
起始和终止都是主机产生的
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc1af1675-1d85-498d-99a5-d53936bac779%2FUntitled.png?table=block&id=e972b8ff-298e-4214-8416-925b59e6e55e&t=e972b8ff-298e-4214-8416-925b59e6e55e&width=867&cache=v2)
(SCL低电平)主机发送-(SCL高电平)从机接收 循环八次
I2C高位先行,串口低位先行
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fd3f8c038-02e9-4878-a8fb-c2ea837eaf80%2FUntitled.png?table=block&id=d8dac394-a36c-4d4c-b0b8-5b77ed30de79&t=d8dac394-a36c-4d4c-b0b8-5b77ed30de79&width=852&cache=v2)
从机的数据变换基本都是贴着SCL下降沿进行,而主机可以在SCL高电平的任意时刻读取
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc5a1fc66-7dc3-45f5-951f-d643a118c126%2FUntitled.png?table=block&id=6beb736b-fe4e-4f36-999b-02a73c137a69&t=6beb736b-fe4e-4f36-999b-02a73c137a69&width=861&cache=v2)
从机设备地址,在I2C协议标准里分为7位和10位地址,每个I2C设备出厂时,厂商都会为它分配一个7位的地址,可在芯片手册中找到,若挂载相同型号,地址最后几位可以由引脚决定
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fec001dd0-e52a-420b-9f96-a82a33a9e875%2FUntitled.png?table=block&id=37d3e84b-9061-45dd-a899-82e12e9dde15&t=37d3e84b-9061-45dd-a899-82e12e9dde15&width=869&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7499676e-637c-4713-a8dc-0e02c6c1b2ac%2FUntitled.png?table=block&id=6eca5c95-60fc-4a86-8ea3-50683e7fe1f4&t=6eca5c95-60fc-4a86-8ea3-50683e7fe1f4&width=838&cache=v2)
- 指定地址写
- 对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)
发送的第一个字节是对从机寻址,一般第二个字节可以是寄存器地址或者是指令控制字,第三个字节开始是写入某个地址下寄存器的内容
以上操作在写入一个数据后,地址指针会自动+1,变成0x1A,所以第二个数据就写入到0x1A的位置,从而完成了在指定位置开始,按顺序连续写入多个字节
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F2b972b61-9279-4836-9995-3d9d43bea7a9%2FUntitled.png?table=block&id=6d7b506b-42ca-453c-a7d1-19342d891edb&t=6d7b506b-42ca-453c-a7d1-19342d891edb&width=863&cache=v2)
当前地址读,主机没有指定要读哪个地址,从机返回当前指针指向的寄存器的值
若调用指定地址写的时序,在0x19的位置写入了0xAA,那么指针就会+1,移动到0x1A的位置
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F2fe9f5fe-78b5-4d4d-bed8-8769cbb4aef8%2FUntitled.png?table=block&id=74dfde74-e5f6-4c82-bb17-494db33baaee&t=74dfde74-e5f6-4c82-bb17-494db33baaee&width=874&cache=v2)
前半部分:指定地址写还没来得及写
后半部分:当前地址读
主机给应答,从机继续发,主机给非应答,从机就不会再发了,交出SDA的控制权