IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> I2C-集成电路总线 -> 正文阅读

[嵌入式]I2C-集成电路总线

一、概述

  1. IIC即Inter-Intergrated Circuit(集成电路总线),I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。
  2. 时钟线必须由主机(通常为微控制器)控制,主机产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。I2C总线上有主机(MCU)和从机(片外外设,如AT24C02)之分,可以有多个主机和多个从机。从机永远不会主动给主机发送数据。
  3. 每个接到I2C总线的设备都有一个唯一的地址,以便于主机寻访。
  4. IIC的通信速度分为三种:标准模式传输速率:100KHZ,快速模式:400KHZ,高速模式:3.4MHZ

二、信号概念

I2C通信,存在几种信号

  1. 起始信号(条件):通知从机做好通信的准备。
  2. 应答信号:有应答和无应答。有应答是低电平,无应答是高电平。
  3. 停止信号(条件):告诉从机通信已经结束。

三、关键时序图

数据位的传输:主机在时钟的上升沿时接收数据,下降沿时发送数据,一次数据的传输就是8位,高位先发

数据的有效性:
在这里插入图片描述
由图可知:时钟线为高电平时,数据线上的数据才稳定;时钟线为低电平时,数据线上的数据改变

起始和停止条件
在这里插入图片描述
1. 起始条件:时钟线处于高电平期间,数据线产生了一个下降沿
2. 停止条件:时钟线处于高电平期间,数据线产生了一个上升沿

应答信号:判断刚刚接收到的数据有没有正常响应,应答位一定是接收方发出来的,发送和接收的时序和普通的一个位传输没有区别。发生在第9个时钟周期。
在这里插入图片描述
3. 主机发送一个应答位:在第9个时钟周期,时钟低电平时,数据引脚输出低电平时是应答,高电平时是无应答。

  1. 主机接收一个应答位:在第9个时钟周期,时钟从低电平到高电平变化时,读取SDA引脚的电平,数据引脚位低电平是时应答,高电平时是无应答。

一个字节的发送和接收
在这里插入图片描述
发送一个字节:和发送一个应答位差不多,for循环8次即可,先发送高位``。
接收一个字节:和接收一个应答位差不多
时钟和数据转换:SDA引脚通常使用外部设备拉高。SDA引脚上的数据可能仅在SCL低时段发生变化。SCL高期间的数据变化将指示定义的起始或停止条件。

I2C的通信步骤

  1. 起始条件
  2. 发送8位的数据(发送器件地址+写/读方向)
  3. 等待应答位
  4. 继续发送相应的字节数据
  5. 停止条件

如何区分是和哪个从机进行通信?
通过IIC器件自带的地址:一般是7bit的硬件地址,加上1bit的读写位
如果是主机发送:器件地址+写方向(0)
如果是主机接收:器件地址+读方向(1)

四、代码实现

主要看时序图编写

模拟I2C初始化,
使用的引脚:PB8–SCL , PB9–SDA
主机通过时钟引脚输出高低电平,故配置为推挽输出
主机有时通过数据引脚输出数据,有时需要从数据引脚中读取数据,故先配置为推挽输出

/*
***************************
函数功能:I2C初始化
函数参数:None
函数返回值:None
函数说明:SCL_PIN--SCL 推挽输出
		SDA_PIN--SDA 推挽输出
***************************
*/
void i2c_init(void)
{
	 GPIO_InitTypeDef  	 GPIO_InitStructure;
	 
	//PB硬件时钟使能
	 RCC_AHB1PeriphClockCmd(GPIO_CLK, ENABLE);
	
	//配置PB8 pB9输出模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = SCL_PIN|SDA_PIN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	
	GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
	
	//看时序图,PB8 PB9会有一个初始电平
	SCL_W = 1;
	SDA_W = 1;
}

数据线输入/输出配置函数
当需要读取SDA引脚上的电平时,设置为输入模式:GPIO_Mode_IN
当需要从SDA引脚上输出数据时,设置为输出模式:GPIO_Mode_OUT

//配置数据线的输入/输出
void sda_pin_mode(GPIOMode_TypeDef pin_mode)
{
	GPIO_InitTypeDef  	 GPIO_InitStructure;
	//配置 pB9输出模式
	GPIO_InitStructure.GPIO_Mode = pin_mode;    //输出或者输入模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = SDA_PIN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
}
/*
**********************************************************************
函数功能:iic起始条件函数
函数形参:u8 delay
函数返回值:None
备注:时钟线高电平期间,数据线产生下降沿
**********************************************************************
*/
void i2c_start(u8 delay)
{
	//保证SDA引脚为输出模式
	sda_pin_mode(GPIO_Mode_OUT);
	
	SCL_W = 1;
	SDA_W = 1;
	delay_us(delay); //起始条件的建立时间
	
	SDA_W = 0;
	delay_us(delay);//起始条件的维持时间
	
	SCL_W = 0;
	delay_us(delay);  //钳住I2C总线,准备发送或接收数据 
}

起始条件和结束条件的时序图
在这里插入图片描述

/*
**********************************************************************
函数功能:iic停止条件函数
函数形参:u8 delay
函数返回值:None
备注:时钟线高电平期间,数据线产生上升沿
**********************************************************************
*/
void i2c_stop(u8 delay)
{
	//保证SDA引脚为输出模式
	sda_pin_mode(GPIO_Mode_OUT);
	
	SCL_W = 1;
	SDA_W = 0;
	delay_us(delay); 
	
	SDA_W = 1;   //发送I2C总线结束信号
	delay_us(delay);
}
/*
**********************************************************************
函数功能:主机发送应答信号
函数形参:u8 ack,u8 delay
函数返回值:None
**********************************************************************
*/
void i2c_send_ack(u8 ack,u8 delay)
{
	//保证SDA引脚为输出模式
	sda_pin_mode(GPIO_Mode_OUT);	
	SCL_W=0;

	//先更改SDA引脚的电平
	if(ack)
	{
		SDA_W = 1;  //无应答
	}
	else
	{
		SDA_W = 0;  //应答
	}
	delay_us(delay);//发送数据需要的时间
	
	SCL_W=1;
	delay_us(delay);//接收数据需要的时间
	
	SCL_W=0;
	delay_us(delay);//保证一个完整的周期
}

发送应答位和接收应答位的时序图
在这里插入图片描述

/*
**********************************************************************
函数功能:主机接收应答信号
函数形参:u8 delay
函数返回值:接收到的应答信号
**********************************************************************
*/
u8 i2c_recv_ack(u8 delay)
{
	u8	ack = 0;
	//保证SDA引脚为输入模式
	sda_pin_mode(GPIO_Mode_IN);
	
	SCL_W = 1;     //时钟线为高电平时,才能读取SDA引脚稳定的电平
	delay_us(delay); 
	//读取SDA引脚的电平
	if(SDA_R)   ack = 1;  //无应答信号
	else 		ack = 0;  //有应答信号
	
	SCL_W = 0;   //总线在忙的状态
	delay_us(delay);
	
	return ack;
}

发送一个字节:和发送一个应答位差不多,for循环8次即可,先发送高位``。

/*
**********************************************************************
函数功能:主机发送一个字节数据,再接收一个应答信号函数
函数形参:待发送的数据,u8 delay
函数返回值:接收到的应答信号
备注:0:应答   1:非应答     8bit   先高后低
**********************************************************************
*/
u8 i2c_send_byte(u8 byte,u8 delay)
{
	u8 ack;
	int i = 0;
	//保证SDA引脚为输出模式
	sda_pin_mode(GPIO_Mode_OUT);
	
	//最高位优先传输,1字节=8位
	for(i=7;i>=0;i--)
	{
		SCL_W = 0;
		//先更改SDA引脚的电平
		if(byte & (1<<i))  //判断bit位为1
		{
			SDA_W = 1;
		}
		else
		{
			SDA_W = 0; 
		}
		delay_us(5);
		
		SCL_W = 1;
		delay_us(5); //保持高电平
		
		SCL_W = 0;  //时钟线为低电平时,才能变更数据,传输下一位数据
		delay_us(5); 		
		
	}
	//SCL_W = 0;
	ack = i2c_recv_ack(delay);
	return ack;	
}
/*
**********************************************************************
函数功能:主机接收一个字节数据,再发送一个应答信号函数
函数形参:待发送的应答,u8 delay
函数返回值:接收到的数据
备注:0:应答   1:非应答     8bit   先高后低
**********************************************************************
*/
u8 i2c_recv_byte(u8 ack,u8 delay)
{
	u8 d = 0;
	int i;
	
	//保证SDA引脚为输入模式
	sda_pin_mode(GPIO_Mode_IN);	
	
	for(i=7; i>=0; i--)
	{
		SCL_W = 1;
		delay_us(delay);
		
		if(SDA_R)
			d|=1<<i;	
		
		SCL_W = 0;	
		delay_us(delay);	
	}
//	SCL_W = 1;//ERR
	i2c_send_ack(ack,delay);
	
	return d;
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 11:06:03  更:2021-10-22 11:07:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:51:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码