目录
一、I2C 初始化
初始化步骤如下:
- 时钟源配置。PERCLK_CLK_ROOT 的时钟源是 66MHz
- 关闭 I2C。在配置 I2C 相关寄存器时,我们需要先将 I2C 关闭
- 分频。分频的目的是控制 I2C 的传输速率(如果要控制 I2C 的速率为 100K,可以640 分频)
- 开启 I2C。
/* i2c 初始化 */
void i2c_init()
{
// 时钟源的初始化放到了时钟初始化(CCM_init)
// 关闭I2C
I2C1_I2CR &= ~(1 << 7);
// 设置分频值(分频值为 640)
I2C1_IFDR = 0x15;
// 打开I2C
I2C1_I2CR |= (1 << 7);
}
二、产生开始 / 停止信号
1、开始信号
当总线空闲时,总线上的设备可以发送开始信号来占用总线。如果存在多个设备同时占用总线,此时就会发生冲裁。
- 判断总线是否空闲
- 设为主机模式,设为发送模式
- 发送要通信的设备地址和通信方向
/* 产生开始信号 */
i2c_status_t i2c_master_start(unsigned char address, i2c_direction direction)
{
/* 总线是否被占用 */
if (is_bus_busy())
{
return Status_I2C_Busy;
}
/*
* 发送开始信号
* bit 5: 1 主机
* bit 4: 1 发送
*/
I2C1_I2CR |= ((1 << 4) | (1 << 5));
/* 发送通信地址和通信方向 */
I2C1_I2DR = (((unsigned int)address << 1) | (direction == I2C_Read ? 1 : 0));
return Status_I2C_Success;
}
2、重复开始信号
当某个设备在通信时,可能会需要临时改变通信方向,此时就可以发送一个重复开始信号来改变通信方向。发送重复开始信号要求总线空闲,且当前设备是主机,只要有一者不满足,就会发送失败
- 判断主机是否空闲,且当前设备是否为主机模式
- 发送一个重复开始信号
- 发送通信地址和通信方向
/* 重复产生开始信号(可能是修改通信方向、通信设备的地址) */
i2c_status_t i2c_master_repeated_start(unsigned char address, i2c_direction direction)
{
/*
* 总线是否被占用
* - 如果是其他设备占用总线,直接返回
* - 如果是当前设备占用总线,发送一个重复的开始信号
*/
if (is_bus_busy() && is_master() == 0)
{
return Status_I2C_Busy;
}
/* 产生一个重复开始信号 */
I2C1_I2CR |= ((1 << 2) | (1 << 4));
/* 发送通信地址和通信方向 */
I2C1_I2DR = (((unsigned int)address << 1U) | (direction & 0x01));
return Status_I2C_Success;
}
3、停止信号
当主机打算继续通信时,可以发送一个停止信号来结束通信;如果从机不想继续通信,可以选择不回应主机表示想结束通信。
-
<
I2C总线通信:初始化与数据读写实现

该文详细介绍了I2C总线的初始化步骤,包括设置时钟源和分频,以及如何产生开始、重复开始和停止信号。接着,文中阐述了在阻塞模式下向总线发送和从总线读取数据的实现方法,涉及中断处理和错误检测。最后,提供了一个统一的数据传输接口,该接口支持读写操作并涵盖了整个通信流程。
最低0.47元/天 解锁文章
1072





