【STM32】标准库与HAL库对照学习教程特别篇--IIC通信原理讲解

一、前言

IIC通信作为单片机经常使用的通信协议,有着十分重要的地位,我们经常使用IIC通信驱动各种外设。IIC在使用上有软件IIC硬件IIC
软件IIC是指用单片机的两个引脚模拟出来的IIC,通过程序控制引脚状态。
硬件IIC是指芯片上的IIC外设,有专门的电路与控制寄存器,对应引脚也是专用的。
硬件IIC的效率要远高于软件IIC,但引脚固定且数量有限,软件IIC不受引脚限制。
本章我们使用软件IIC。

二、IIC总线介绍

I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。

I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL

三、IIC物理层

IIC通信的连接方式
在这里插入图片描述
说明:

  • SCL总线时钟线,由主设备提供SDA总线是数据线,用于数据的传输。
  • 总线上同一时间只能由一个主设备使用,当多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  • 每个连接到总线的从设备都有一个独立的地址,主设备可以利用这个地址进行不同设备之间的访问。
  • IIC通信属于半双工通信,同一时间的设备只能接收数据或者发射数据。(因为只有一根数据线)
  • 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,由上拉电阻把总线拉成高电平。
  • 常见两种传输模式:标准模式传输速率100kbit/s快速模式400kbit/s
  • 连接设备数量受最大电容400pF的限制。

四、IIC协议层

1、通信大致流程:

  • 主设备首先发射一个起始信号,开始通信。
  • 然后,主设备会发射需要通信的某一个从设备的地址
  • 对应地址的从设备接收到地址信号后会返回一个应答信号,当主设备接收到应答信号时,开始进行数据传输。
  • 每当 接收或者发送 数据都会 接收或者发送 一个应答信号,当不需要传输数据时,需要提供一个非应答信号结束数据传输
  • 数据传输完毕时,主设备会发射一个停止信号结束通信。

2、传输过程

(1)主机向从机发送数据
在这里插入图片描述
(2)主机读取从设备的数据
在这里插入图片描述
(3)主机在发送数据过程中,转为读取数据。
在这里插入图片描述
S:起始信号, 0:写数据, 1:读数据, A:应答信号, A非:非应答信号, P:停止信号
数据传输一帧数据有8位,地址的数据一般为7位加上1位读写位,正好一帧数据。(10位的地址一般检测头7位)

3、信号要求

(1)起始和停止信号
在这里插入图片描述
(2)应答与非应答信号
在这里插入图片描述
(3)数据有效性规定
在这里插入图片描述
数据电平变化必须在SCL低电平的时候。

五、使用C语言实现IIC

根据信号要求,可以用C语言写出对应传输程序。

1、起始信号与停止信号

(1)起始信号

/*************************************************
*函数名:     IIC_start
*函数功能:   IIC起始信号
*输入:       无
*返回值:     无
**************************************************/
void IIC_start()
{
	IIC_OUT();    //SDA变为输出状态
	SCL = 1;
	SDA_out = 1;
	Delay_us(5);
	SDA_out = 0;
	Delay_us(5);
}

(2)终止信号

/*************************************************
*函数名:     IIC_end
*函数功能:   IIC停止信号
*输入:       无
*返回值:     无 
**************************************************/
void IIC_end()
{
	IIC_OUT();    //SDA变为输出状态
	SCL = 0;
	SDA_out = 1;
	SDA_out = 0;
	Delay_us(5);
	SDA_out = 1;
	Delay_us(5);
}

2、应答信号、非应答信号与等待应答信号

(1)应答信号

/*************************************************
*函数名:      IIC_ACK
*函数功能:    IIC主机发出应答信号
*输入:        无
*返回值:      无
**************************************************/
void IIC_ACK()
{
	IIC_OUT();    //SDA变为输出状态
	SCL = 0;
	SDA_out = 0;
	Delay_us(2);
	SCL = 1;
	Delay_us(5);
	SCL = 0;
}

(2)非应答信号

/*************************************************
*函数名:       IIC_NACK
*函数功能:     IIC主机发出非应答信号
*输入:         无
*返回值:       无
**************************************************/
void IIC_NACK()
{
	IIC_OUT();   //SDA变为输出状态
	SCL = 0;
	SDA_out = 1;
	Delay_us(2);
	SCL = 1;
	Delay_us(5);
	SCL = 0;
}

(3)等待应答信号

/*************************************************
*函数名:       IIC_Wait_ACK
*函数功能:     主机等待应答信号
*输入:         无
*返回值:       1:接收到应答信号,0:非应答或者未接收到应答信号
**************************************************/
u8 IIC_Wait_ACK()
{
	u8 i;
	IIC_IN();   //SDA变为输入状态
	SCL = 1;
	while(SDA_in)
	{
		i++;
		if(i > 250)
		{
			IIC_end();
			return 0;
		}
	}
  	SCL=0;  
	return 1;
}

3、发送一个字节数据与接收一个字节的数据

(1)发送一个字节数据

/*************************************************
*函数名:       IIC_Write_byte
*函数功能:     IIC写一个字节函数
*输入:         bit:写入的数据
*返回值:       无
**************************************************/
void IIC_Write_byte(u8 bit)
{
	u8 i;
	IIC_OUT();  //SDA变为输出状态
	SCL = 0;
	for(i = 0;i < 8;i++)
	{
		if(bit & 0x80)
			SDA_out = 1;
		else
			SDA_out = 0;
		bit <<= 1;
		Delay_us(2);
		SCL = 1;
		Delay_us(2);
		SCL = 0;
		Delay_us(2);
	}
}

(2)接收一个字节的数据

/*************************************************
*函数名:       IIC_Read_byte
*函数功能:     IIC读取一个字节的数据
*输入:         ACK:1-接收后给应答信号,0-接收后给非应答信号
*返回值:       BIt:读取的值
**************************************************/
u8 IIC_Read_byte(u8 ACK)
{
	u8 i,Bit;
	IIC_IN();   //SCL变为输入状态
	for(i = 0;i < 8;i++)  //判断最高位,0x80 = 1000 0000
	{
		SCL = 0;
		Delay_us(2);
		SCL = 1;
		Bit <<= 1;
		if(SDA_in)
			Bit++;
	}
	if(ACK)
		IIC_ACK();
	else
		IIC_NACK();
	return Bit;
}

六、设备间使用IIC的大致流程

1、发送数据

  • 主机发送起始信号
  • 主机发送从机地址+写信号
  • 主机接收到应答信号,发送从设备写入数据的地址
  • 主机接收到应答信号,主机开始发送数据,每发送一字节数据,都要接收一次应答信号。
  • 数据发送完毕,主机发送停止信号,通信结束。

2、接收数据

  • 主机发送起始信号
  • 主机发送从机地址+读信号
  • 主机接收到应答信号,发送从设备读取数据的地址
  • 主机接收到应答信号,从设备开始发送数据,主机每接送一字节数据,都要发送一次应答信号
  • 主机不在想接收数据时,发送非应答信号,,结束数据传输。
  • 主机发送停止信号,通信结束。

到这里就结束啦!
在这里插入图片描述

版权声明:本文为CSDN博主「修成真」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51447215/article/details/121778136

生成海报
点赞 0

修成真

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里