单片机C语言I2C总线:解锁嵌入式系统通信的5大要点
发布时间: 2024-07-06 15:48:36 阅读量: 49 订阅数: 21
![单片机的c语言程序设计](https://img-blog.csdnimg.cn/img_convert/7bccd48cc923d795c1895b27b8100291.png)
# 1. 单片机C语言I2C总线简介**
I2C总线是一种串行通信协议,广泛应用于嵌入式系统中。它使用两条线(SDA和SCL)进行数据传输,具有低成本、低功耗、易于实现的特点。
在单片机C语言编程中,I2C总线通常使用HAL库进行操作。HAL库提供了丰富的API函数,简化了I2C总线通信的开发。
本节将介绍I2C总线的基本概念、拓扑结构和通信协议,为后续的编程操作打下基础。
# 2. I2C总线通信原理
### 2.1 I2C总线拓扑结构
I2C总线是一种多主从结构的串行通信总线,由两条双向信号线组成:
- **SCL(串行时钟线)**:由主设备控制,为所有设备提供同步时钟信号。
- **SDA(串行数据线)**:用于数据传输,由主设备和从设备共享。
设备通过唯一地址进行寻址,每个设备都有一个7位或10位的地址。总线拓扑结构如下所示:
```mermaid
graph LR
subgraph 主设备
A[主设备]
end
subgraph 从设备
B[从设备 1]
C[从设备 2]
D[从设备 3]
end
A --> B
A --> C
A --> D
```
### 2.2 I2C总线通信协议
I2C总线通信协议遵循以下规则:
- **起始条件**:主设备将SDA从高电平拉低,同时保持SCL为高电平。
- **从设备地址**:主设备发送从设备的7位或10位地址,并指定读/写操作。
- **从设备应答**:从设备在地址后发送一个应答位(低电平),表示已收到地址。
- **数据传输**:主设备和从设备在SCL时钟信号的控制下交换数据。
- **停止条件**:主设备将SDA从低电平拉高,同时保持SCL为高电平。
### 2.3 I2C总线时序图
下图展示了I2C总线通信的一个典型时序图:
```mermaid
sequenceDiagram
participant 主设备 as A
participant 从设备 as B
A->B: Start
B->A: ACK
A->B: Device Address
B->A: ACK
A->B: Data
B->A: ACK
A->B: Stop
```
**时序图说明:**
- **起始条件**:主设备发送起始条件,从设备应答。
- **地址和读/写位**:主设备发送从设备地址和读/写位,从设备应答。
- **数据传输**:主设备和从设备交换数据,每个数据字节后都有一个应答位。
- **停止条件**:主设备发送停止条件,结束通信。
# 3. 单片机C语言I2C总线编程
### 3.1 I2C总线初始化
在使用I2C总线之前,需要对总线进行初始化,包括配置时钟频率、设置引脚功能和使能I2C模块。
```c
// I2C总线初始化函数
void I2C_Init(uint32_t baudrate)
{
// 1. 配置时钟频率
I2C_SetClock(baudrate);
// 2. 设置引脚功能
GPIO_SetPinFunction(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_FUNC_I2C);
GPIO_SetPinFunction(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_FUNC_I2C);
// 3. 使能I2C模块
I2C_Enable(I2C_MODULE);
}
```
**参数说明:**
* `baudrate`: I2C总线时钟频率,单位为Hz。
**代码逻辑分析:**
* 第1步:调用`I2C_SetClock`函数配置I2C总线时钟频率。
* 第2步:调用`GPIO_SetPinFunction`函数设置I2C总线引脚的功能为I2C。
* 第3步:调用`I2C_Enable`函数使能I2C模块。
### 3.2 I2C总线读写操作
I2C总线读写操作包括发送起始位、发送从机地址、发送数据、接收数据和发送停止位。
```c
// I2C总线写操作函数
int I2C_Write(uint8_t slave_addr, uint8_t *data, uint16_t len)
{
// 1. 发送起始位
I2C_Start();
// 2. 发送从机地址
I2C_WriteData(slave_addr << 1);
// 3. 发送数据
for (uint16_t i = 0; i < len; i++) {
I2C_WriteData(data[i]);
}
// 4. 发送停止位
I2C_Stop();
return 0;
}
// I2C总线读操作函数
int I2C_Read(uint8_t slave_addr, uint8_t *data, uint16_t len)
{
// 1. 发送起始位
I2C_Start();
// 2. 发送从机地址
I2C_WriteData(slave_addr << 1 | 1);
// 3. 接收数据
for (uint16_t i = 0; i < len; i++) {
data[i] = I2C_ReadData(i == len - 1);
}
// 4. 发送停止位
I2C_Stop();
return 0;
}
``
```
0
0