I2C学习笔记
I2C协议
概念
I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
支持串行数据线 (SDA)和串行时钟线(SCL)在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别(无论是微控制器、 LCD驱动器、存储器或键盘接口),而且都可以作为一个发送器或接收器(由器件的功能决定)。很明显 LCD驱动器只是一个接收器,而存储器则既可以接收又可以发送数据 除了发送器和接收器外,器件在执行数据传输时也可以被看作是主机或从机,主机是初始化总线的数据传输并产生允许传输的时钟信号的器件。此时,任何被寻址的器件都被认为是从机。
协议
1.起始和停止条件
2.数据传输
从机地址以及读写方向
发送到SDA线上的每个字节必须为8位。每次传输可以发送的字节数不受限制,但是每个字节后面必须跟一个响应位。主机向从机传输数据需要先发送7位从机地址+读写数据位(1读就是向从机读取数据,0写就是向从机写入数据),紧接着在收到响应之后判断是否可以开始发送数据,每发送一个数据之后都要接一个响应位来判断数据传输状态。
比如HTU21D温湿度传感器的地址为0X40,转换为二进制也就是1000000,加上读/写位之后就是
HTDU21D_ADDRESS_WR 0x80
HTDU21D_ADDRESS_RD 0x81
响应
数据传输必须带响应,相关的响应时钟脉冲由主机产生,在响应的时钟脉冲期间 发送器释放SDA线。
在响应的时钟脉冲期间,接收器必须将 SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。
应答ACK、非应答NACK
/*
*********************************************************************************************************
* 函 数 名: i2c_Ack
* 功能说明: CPU产生一个ACK信号
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
I2C_SDA_0(); /* CPU驱动SDA = 0 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生1个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1(); /* CPU释放SDA总线 */
}
/*
*********************************************************************************************************
* 函 数 名: i2c_NAck
* 功能说明: CPU产生1个NACK信号
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
I2C_SDA_1(); /* CPU驱动SDA = 1 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生1个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
3.通讯过程
主机向从机写入数据
大致分为以下几步
- 起始信号
- 从机地址
- 响应信号
- 所需要的写入从机的数据
- 响应信号
- 停止信号
主机向从机读取数据
与上面向从机写入数据步骤类似
4.I2C初始化结构体
typedef struct
{
uint32_t I2C_ClockSpeed; /*!< 设置 SCL 时钟频率,此值要低于 400000*/
uint16_t I2C_Mode; /*!< 指定工作模式,可选 I2C 模式及 SMBUS 模式 */
uint16_t I2C_DutyCycle; /*指定时钟占空比,可选 low/high = 2:1 及 16:9 模式*/
uint16_t I2C_OwnAddress1; /*!< 指定自身的 I2C 设备地址 */
uint16_t I2C_Ack; /*!< 使能或关闭响应(一般都要使能) */
uint16_t I2C_AcknowledgedAddress; /*!< 指定地址的长度,可为 7 位及 10 位 */
} I2C_InitTypeDef;
4.I2CGPIO初始化
void i2c_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); /* 打开GPIO时钟 */
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出 */
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
}
可以通过调试穿看起模块巩固对I2C协议的理解,软件模拟I2C和硬件模拟I2C都可以吗了解一下,个人认为硬件I2C更容易理解,但是软件I2C操作起来舒服一点。以下是我自己根据网上相关资料调试的HTU21D传感器博客以及源代码
参考
posted on 2024-07-25 17:26 naive156 阅读(14) 评论(0) 编辑 收藏 举报 来源