物联网嵌入式工程师40周[包含电子书]|之 IIC总线通信(一)

113 阅读13分钟

物联网嵌入式工程师40周[包含电子书]|之 IIC总线通信(一)

附上资源MP4下载地址

我用夸克网盘分享了「2025年物联网嵌入式工程师40周[包含电子书]-完结」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。 链接:pan.quark.cn/s/3b0a95006…

失效访问:cowcowit.com/course/4/4

一、IIC总线介绍

IIC(Inter-Integrated Circuit,集成电路)总线是一种由PHILIPS公司开发的串行总线,用于连接微控制器及其外围设备,它具有如下特点。

l (1)只有两条总线线路: 一条串行数据线(SDA) , 一条串行时钟线(SCL)

l (2)每个连接到总线的器件都可以 使用软件根据它的 唯一的地址 来识别

l (3)传输数据的设备间是简单的主/从关系

l (4)主机可以用作主机发送器或主机接收器

l (5)它是一个真正的多主机总线,两个或多个主机同时发起数据传输时,可以通过冲突检测和仲裁来防止数据被破坏

l (6) 串行的8位双向数据传输 ,位速率在标准模式下可达100kbit/s,在快速模式下可达400kbit/s,在高速模式下可达3.4Mbit/s

暂时无法在飞书文档外展示此内容

二、IIC总线的信号类型

IIC总线在传送数据过程中共有3种类型信号:开始信号、结束信号和响应信号.

开始信号(S)和结束信号§

  1. 开始信号 :SCL 为高电平时, SDA由高电平向低电平跳变 , 开始传送数据 结束信号 :SCL 为高电平时, SDA由低电平向高电平跳变 , 结束传送数据

响应信号(ACK)

接收器在接收到8位数据后,在第9个时钟周期,拉低SDA电平

注意:SDA上传输的数据必须在SCL为高电平期间保持稳定,SDA上的数据只能在SCL为低电平期间变化

三、IIC总线的数据传输格式

发送到SDA线上的每个字节必须是8位的,每次传输可以发送的字节数量不受限制。首先传输的是数据的最高位(MSB)。

启动一个传输时,主机先发送S信号,然后发出8位数据。这8位数据中前7位为从机的地址,第8位表示传输的方向(0表示写操作,1表示读操作)。从机收到后会发出一个ACK信号.

注意:主机接收器在接收到最后一个字节后,也不会发出ACK信号。于是,从机发送器释放SDA线,以允许主机发出P信号结束传输.

四、光环境传感器硬件原理图分析

五、GPIO模拟IIC时序

1.初始化管脚工作模式

1 //GPIO口模拟IIC的延时函数

2 static void IIC_delay(int time)

3 {

4 int i;

5

6 for(i = 0;i < 50 * time;i ++)

7 {

8

9 }

10

11 return;

12 }

13

14 void software_iic_init()

15 {

16 //设置管脚为GPIO功能

17 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO28 &= ~(0xf << 0);//SCL

18 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO28 |= (0x5 << 0);

19

20 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO29 &= ~(0xf << 0);//SDA

21 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO29 |= (0x5 << 0);

22

23 IIC_delay(1);

24

25 return;

26 }

2.管脚输入输出电平控制

1 #define SDA_OUT_MODE() do{GPIO1->GDIR |= (1 << 29);}while(0)

2 #define SCL_OUT_MODE() do{GPIO1->GDIR |= (1 << 28);}while(0)

3 #define SDA_IN_MODE() do{GPIO1->GDIR &= ~(1 << 29);}while(0)

4

5 #define SDA_INPUT_LEVEL() ((GPIO1->DR & (1 << 29)) ? 1 : 0)

6

7 #define SDA_OUTPUT_LEVEL(LEVEL)\

8 do{GPIO1->DR &= ~(1 << 29);GPIO1->DR |= (LEVEL << 29);}while(0)

9

10 #define SCL_OUTPUT_LEVEL(LEVEL)\

11 do{GPIO1->DR &= ~(1 << 28);GPIO1->DR |= (LEVEL << 28);}while(0)

12

13 #define HIGH 1

14 #define LOW 0

3.产生IIC开始信号

1 /IIC START:SCL = 1,SDA = 1->0/

2 void software_iic_start()

3 {

4 //SDA/SCL 输出模式

5 SDA_OUT_MODE();

6 SCL_OUT_MODE();

7

8 //开始的时候,SDA和SCL都是高电平状态

9 SDA_OUTPUT_LEVEL(HIGH);

10 SCL_OUTPUT_LEVEL(HIGH);

11

12 IIC_delay(1);

13

14 //在SCL为高电平状态时,SDA从高变成低,产生开始信号

15 SDA_OUTPUT_LEVEL(LOW);

16 IIC_delay(1);

17

18 return;

19 }

4.产生IIC停止信号

1 /IIC STOP:SCL = 1,SDA = 0->1/

2 void software_iic_stop()

3 {

4 //SDA/SCL 输出模式

5 SDA_OUT_MODE();

6 SCL_OUT_MODE();

7

8 //此时将SCL拉低,让为了让SDA可以改变电平状态,产生结束信号

9 SCL_OUTPUT_LEVEL(LOW);

10 SDA_OUTPUT_LEVEL(LOW);

11 IIC_delay(1);

12

13 //SCL为高电平时,SDA从低到高,产生结束信号

14 SCL_OUTPUT_LEVEL(HIGH);

15 IIC_delay(1);

16 SDA_OUTPUT_LEVEL(HIGH);

17 IIC_delay(1);

18

19 return;

20 }

5.IIC总线写数据

1 /Write 1 Byte to IIC/

2 void software_iic_write_byte(uint8 data)

3 {

4 int level;

5 uint8 loop;

6

7 //SDA为输出模式

8 SDA_OUT_MODE();

9

10 //SCL 为低电平,以便改变SDA上面的数据

11 SCL_OUTPUT_LEVEL(LOW);

12

13 for(loop = 8;loop > 0;loop --)

14 {

15 //先发送最高位,在SCL高电平时,SDA必须保持稳定

16 level = (data >> 7) & 1;

17 SDA_OUTPUT_LEVEL(level);

18 SCL_OUTPUT_LEVEL(HIGH);

19 IIC_delay(1);

20

21 //SCL为低电平时,SDA可以任意改变

22 SCL_OUTPUT_LEVEL(LOW);

23 //低位向高位移动

24 data <<= 1;//data = data << 1

25 IIC_delay(1);

26 }

27

28 return;

29 }

6.IIC总线读数据

1 /Read 1 byte from IIC/

2 uint8 software_iic_read_byte()

3 {

4 uint8 loop;

5 uint8 value = 0;

6

7 //SDA为输入模式

8 SDA_IN_MODE();

9

10 //SCL 为低电平,以便改变SDA上面的数据

11 SCL_OUTPUT_LEVEL(LOW);

12 IIC_delay(1);

13

14 for(loop = 8; loop > 0;loop --)

15 {

16 SCL_OUTPUT_LEVEL(HIGH);

17 IIC_delay(1);

18

19 value <<= 1;

20 //读取1位数据

21 value |= SDA_INPUT_LEVEL();

22

23 SCL_OUTPUT_LEVEL(LOW);

24 IIC_delay(1);

25 }

26

27 return value;

28 }

7.主机向从机发送ACK

1 /主机向从机发送ACK/

2 void software_iic_send_ack()

3 {

4 SDA_OUT_MODE();

5

6 //SCL为低电平期间,数据允许改变

7 SCL_OUTPUT_LEVEL(LOW);

8 //拉低SDA线,产生ACK信号

9 SDA_OUTPUT_LEVEL(LOW);

10 IIC_delay(1);

11

12 //SCL高电平期间,SDA保持稳定,从机读取SDA线上的状态

13 SCL_OUTPUT_LEVEL(HIGH);

14 IIC_delay(1);

15

16 return;

17 }

8.主机向从机发送NACK

1 void software_iic_send_nack(void)

2 {

3 SDA_OUT_MODE();

4

5 SCL_OUTPUT_LEVEL(LOW);

6 SDA_OUTPUT_LEVEL(HIGH);

7 IIC_delay(1);

8

9 //SCL为高电平期间,SDA也为高,此时主机不向从机发送ACK

10 //,此时从机就知道,主机是不想接受数据了

11 SCL_OUTPUT_LEVEL(HIGH);

12 IIC_delay(1);

13

14 return;

15 }

9.等待从机给主机的应答信号

1 /*等待从机给主机的应答信号

2 *

3 *0 : 成功

4 *-1 : 超时,失败

5 */

6 uint8 software_iic_wait_ack()

7 {

8 uint8 ret;

9 uint8 time_out = 0;

10

11 //SDA设为输入模式

12 SDA_IN_MODE();

13

14 SCL_OUTPUT_LEVEL(LOW);

15 IIC_delay(1);

16

17 //SCL为高电平期间,读取SDA的值

18 SCL_OUTPUT_LEVEL(HIGH);

19 IIC_delay(1);

20

21 do{

22 if(time_out >50)

23 {

24 software_iic_stop();

25 return -1;

26 }

27

28 //读取SDA状态

29 ret = SDA_INPUT_LEVEL();

30 IIC_delay(1);

31 time_out ++;

32 }while(ret);

33

34 return 0;

35 }

六、LTR-553ALS-WA光环境传感器

The LTR-553ALS-WA is an integrated low voltage I2Cdigital light sensor [ALS]andproximity sensor [PS]with built-in emitter, in a single miniature chipled lead-free surface mount package. This sensor converts light intensity to a digital output signal capable of direct I2C interface.

LTR-553ALS-WA是一个集成的低压I2C数字光传感器[ALS]和接近传感器[PS],内置发射器,在单个微型芯片无铅表面贴装封装中。该传感器将光强转换为能够直接I2C接口的数字输出信号。

It provides a linear response over a wide dynamic range from 0.01 lux to 64k lux and is well suited to applications under high ambient brightness. With built-in proximity sensor (emitter and detector), LTR-553ALS-WA offers the feature to detect object at a user configurable distance.

LTR-553ALS-WA在0.01勒克斯到64k勒克斯的宽动态范围内提供线性响应,非常适合高环境亮度下的应用。凭借内置的接近传感器(发射器和检测器),LTR-553ALS-WA提供了在用户可配置距离内检测物体的功能。

The sensor supports an interrupt feature that removes the need to poll the sensor for a reading which improves system efficiency. The sensor also supports several features that help to minimize the occurrence of false triggering. This CMOS design and factory-set one time trimming capability ensure minimal sensor-to-sensor variations for ease of manufacturability to the end customers.

该传感器支持中断功能,无需轮询传感器以获取读数,从而提高系统效率。该传感器还支持有助于最大限度地减少误触发发生的几个功能。这种CMOS(互补式金属氧化物半导体)设计和工厂设置的一次性微调能力确保了最小的传感器到传感器的变化,以便于最终客户的制造。

2.从机地址

The 7 bits slave address for this sensor is 0x23H. A read/write bit should be appended to the slave address by the master device to properly communicate with the sensor.

该传感器的7位从属地址为0x23H。主设备应将读/写位附加到从属地址以与传感器正确通信。

3.操作时序分析

(1)读寄存器

(2)写寄存器

4.重点寄存器分析

(1)MANUFAC_ID Register (0x87)

(2)PS_CONTR Register (0x81)

The PS_CONTR register controls the PS operation modes. The PS sensor can be set to either standby mode or active mode. At either of these modes, the I2C circuitry is always active. The default mode after power up is standby mode.During standby mode, there is no PS measurement performedbut I2C communication is allowed to enable read/write to all the registers.

PS_CONTR寄存器控制PS操作模式。PS传感器可以设置为待机模式或活动模式。在这两种模式中的任何一种下,I2C电路始终处于活动状态。上电后的默认模式是待机模式。在待机模式下,不执行PS测量,但允许I2C通信启用对所有寄存器的读/写。

PS Gain controls the gain setting for the PS sensor. PS Saturation Indicator Enable bit is used for enabling the saturation indicator in Bit 7 of PS_DATA register (0x8E)

PS Gain控制PS传感器的增益设置。PS饱和指示器启用位用于启用PS_DATA寄存器(0x8E)第7位中的饱和指示器

(3)PS_DATA_0 Register/PS_DATA_1 (0x8D / 0x8E)

The PS ADC channel data are expressed as a 11-bit data spread over two registers. The PS_DATA_0 and PS_DATA_1 registers provide the lower and upper byte respectively. When the I2C read operation starts, both the registers are locked until the I2C read operation is completed. This will ensure that the data in the registers is from the same measurement even if an additional integration cycle ends during the read operation. New measurement data is stored into temporary registers and the PS_DATA registers are updated as soon as there is no on-going I2C read operation.

PS ADC通道数据表示为分布在两个寄存器上的11位数据。PS_DATA_0和PS_DATA_1寄存器分别提供下字节和上字节。当I2C读取操作开始时,两个寄存器都被锁定,直到I2C读取操作完成。这将确保寄存器中的数据来自相同的测量,即使在读取操作期间额外的积分周期结束。新的测量数据存储到临时寄存器中,一旦没有正在进行的I2C读取操作,PS_DATA寄存器就会更新。

PS Saturation Flag is used for monitoring the internal IC saturation. It will be flagged when the IC has reached saturation and not able to perform any further PS measurement. The PS Saturation Indicator Enable bit in PS_CONTR Register (0x81) has to be enabled in order to use this feature. If it is not enable, the flag will always be indicated as 0

PS饱和度标志用于监控内部IC的饱和度。当IC达到饱和度并且无法执行任何进一步的PS测量时,它将被标记。PS_CONTR寄存器(0x81)中的PS饱和度指示器启用位必须启用才能使用此功能。如果不启用,该标志将始终指示为0

(4)ALS_CONTR Register (0x80)

The ALS_CONTR register controls the ALS Gain setting, ALS operation modes and software (SW) reset for the sensor. The ALS sensor can be set to either standby mode or active mode. At either of these modes, the I2C circuitry is always active.The default mode after power up is standby mode. During standby mode, there is no ALS measurement performedbut I2C communication is allowed to enable read/write to all the registers.

ALS_CONTR寄存器控制ALS增益设置、ALS操作模式和传感器的软件(SW)复位。ALS传感器可以设置为待机模式或活动模式。在这两种模式中的任何一种,I2C电路始终处于活动状态。上电后的默认模式是待机模式。在待机模式下,不执行ALS测量,但允许I2C通信启用对所有寄存器的读/写。

(5)ALS_DATA_CH1 Register (0x88 / 0x89)

The ALS_DATA registers should be read as a group, with the lower address read back first (i.e. read 0x88 first, then read 0x89).These two registers should also be read before reading channel-0 data(from registers 0x8A, 0x8B).

ALS_DATA寄存器应作为一组读取,较低的地址先读回(即先读0x88,然后读0x89)。在读取通道-0数据(来自寄存器0x8A、0x8B)之前,也应读取这两个寄存器。

When the I2C read operation starts, all four ALS data registers are locked until the I2C read operation of register 0x8B is completed. This will ensure that the data in the registers is from the same measurement even if an additional integration cycle ends during the read operation. New measurement data is stored into temporary registers and the ALS_DATA registers are updated as soon as there is no on-going I2C read operation.

当I2C读取操作开始时,所有四个ALS数据寄存器都被锁定,直到寄存器0x8B的I2C读取操作完成。这将确保寄存器中的数据来自相同的测量,即使在读取操作期间额外的积分周期结束。新的测量数据被存储到临时寄存器中,一旦没有正在进行的I2C读取操作,ALS_DATA寄存器就会更新。

The ALS ADC channel-1 data is expressed as a 16-bit data spread over two registers. The ALS_DATA_CH1_0 and ALS_DATA_CH1_1 registers provide the lower and upper byte respectively.