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.通讯过程

主机向从机写入数据
在这里插入图片描述大致分为以下几步

  1. 起始信号
  2. 从机地址
  3. 响应信号
  4. 所需要的写入从机的数据
  5. 响应信号
  6. 停止信号

主机向从机读取数据
在这里插入图片描述与上面向从机写入数据步骤类似

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编辑  收藏  举报  来源

导航