第五章 stm32 cubemx 软件I2C实验以及EEPROM的使用理论及实验过程

第五章 stm32 cubemx 软件I2C实验以及EEPROM的使用理论及实验过程

前言

本章将讲解stm32通讯协议中的IIC协议,利用cubeMX完成软件和硬件IIC的实现,并结合实验数据,给人更为深刻的体验。
我们结合IIC的具体协议和逻辑分析仪得到的具体实验数据理解IIC协议。

IIC概述

I2C通讯协议是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。

llC: Inter Integrated Circuit,集成电路总线,是一种同步串行半双工通信总线。其中同步说明这种通信方式需要时钟线;串行说明数据一位一位(一个字节8位即0000 0000)在一个数据线上朝一个方向发送;半双工说明一个时间只能进行接收或者发送;总线就是传输数据的通道,如果有多个设备想使用总线进行传输数据多个都需要挂载在总线上,注意在总线上可以有多个主机,多个从机;协议则是传输数据的规则,首先我们讲解该协议。

IIC物理层

IIC物理层

如图所示,即位IIC的物理层,由图可明显看到所有的设备挂载在,两条l2C总线下,一条双向串行数据线(SDA)用来传递数据,一条串行时钟线(SCL)用于数据收发同步。总线通过上拉电阻接到电源。当I2C设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
要点

  • IIC总线协议是一个支持多设备的总线。在一个l2C通讯总线中,如图,可连接多个I2C通讯设备,支持多个通讯主机及多个通讯从机。
  • 多个设备并不是指无限多个,连接到相同总线的IC数量要受到总线的最大电容400pF限制。
  • 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的通信。
  • 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  • 具有三种传输模式:标准模式传输速率为100kbit/s ,快速模式为400kbit/s,高速模式3.4Mbit/s,但目前大多/2C设备尚不支持高速模式。

IIC协议层

I2C协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。接下来我们将逐个进行实验。

IIC读写概述

主机写入到从机的基本过程,如图所示。由主机发出起始信号表示开始通信,然后发送从机地址及数据传输方向,然后释放总线(总线上有上拉电阻,总线拉高即为释放总线)交给从机,得到从机应答ACK或非应答NACK,紧接着进行数据的接收或者数据传输的终止。
主机写入到从机

实验结果
结果如图所示。
接下来进行具体讲解,各个信号如何产生、代码实现、实验反馈。

起始、停止信号及代码

理论说明
如图所示
总线电平

  • 起始:当SCL线是高电平时,SDA线从高电平向低电平切换。

  • 停止:当SCL是高电平时,SDA线由低电平向高电平切换。

代码实现
代码如下(示例):

void I2C_SCL_1()//SCL电平拉高
{
    HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_SET);
}
void I2C_SCL_0()
{
    HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_RESET);
}
void I2C_SDA_1()
{
    HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_SET);
}
void I2C_SDA_0()
{
    HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_RESET);
}
static void i2c_Delay(void)
{
	uint8_t i;
	for (i = 0; i < 10; i++);
}
void i2c_Start(void)
{
	/* 当SCL线是高电平时,SDA线从高电平向低电平切换。*/
	I2C_SDA_1();
	I2C_SCL_1();
	i2c_Delay();
    
	I2C_SDA_0();
	i2c_Delay();
    
	I2C_SCL_0();
	i2c_Delay();
}
void i2c_Stop(void)
{
	/* 当SCL是高电平时,SDA线由低电平向高电平切换 */
	I2C_SDA_0();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SDA_1();
}

实验验证
在这里插入图片描述

数据有效性及代码

理论说明
如图所示
数据有效段

I2C使用SDA信号线来传输数据,使用SCL信号线进行数据同步。SDA数据线在SCL的每个时钟周期传输一位数据。

SCL为高电平的时候SDA表示的数据有效,即此时的SDA为高电平时表示数据“1”,为低电平时表示数据“0”。
当SCL为低电平时,SDA的数据无效,一般在这个时候SDA进行电平切换,为下一次表示数据做好准备。
代码实现
这个代码函数功能是读取一个字节的数据,利用for循环依次读取8位数据。

#define I2C_SDA_READ   HAL_GPIO_ReadPin(GPIO_PORT_I2C, I2C_SDA_PIN)

uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t value;

	value = 0;
	for (i = 0; i < 8; i++)
	{
		value <<= 1;
		I2C_SCL_1();
		i2c_Delay();
		if (I2C_SDA_READ)
		{
			value++;
		}
		I2C_SCL_0();
		i2c_Delay();
	}
	return value;
}

这个代码函数功能是发送一个字节的数据,利用for循环依次发送8位数据。

void i2c_SendByte(uint8_t oneByte)
{
	uint8_t i;

	/* 数据由高位到低位依次发送 */
	for (i = 0; i < 8; i++)
	{		
		if (oneByte& 0x80)
		{
			I2C_SDA_1();//判断为1发送1
		}
		else
		{
			I2C_SDA_0();
		}
		i2c_Delay();
		I2C_SCL_1();
		i2c_Delay();	
		I2C_SCL_0();
		if (i == 7)
		{
			 I2C_SDA_1(); //发送完成后释放总线等待应答
		}
		oneByte<<= 1;	/* 左移做下一次判断*/
		i2c_Delay();
	}
}

实验验证
在这里插入图片描述

响应ACK及代码

理论说明
I2C的数据和地址传输都带响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据。
应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答。应答信号为低电平时,规定为有效应答(ACK),表示已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),表示接收该字节失败。

传输时主机产生时钟,在第9个时钟时,数据发送端会释放SDA的控制权,由数据接收端控制SDA,若SDA为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)。
产生应答信号

代码实现
该代码实现包括三个函数,第一个函数为产生应答信号,第二函数为产生非应答信号,第三个函数为判断应答。第一、二个函数如上述所示,第三个函数需要注意在读取ACK/NACK信号时先进行释放总线,即将SDA总线拉高交给其他需要响应的设备控制。

void i2c_Ack(void)
{
	I2C_SDA_0();
	i2c_Delay();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();//应答信号为低电平时,规定为有效应答(ACK)
	I2C_SDA_1();
}
void i2c_NAck(void)
{
	I2C_SDA_1();
	i2c_Delay();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();	
}
uint8_t i2c_WaitAck(uint16_t timeout)
{
	uint8_t re,ucErrTime=0;

	I2C_SDA_1();//释放SDA总线
	i2c_Delay();
	I2C_SCL_1();
	i2c_Delay();
    while(I2C_SDA_READ)//等待ACK//NACK
    {
        re = 0;
        ucErrTime++;
        if(ucErrTime>timeout)
        {
            return re;
        }
        else re = 1;
    }
	I2C_SCL_0();
	i2c_Delay();
	return re;
}

实验验证
在这里插入图片描述

地址及数据方向

I2C总线上的每个设备都有自己的独立地址,主机发起通讯时,通过SDA信号线发送设备地址(SLAVE_ADDRESS)来查找从机。设备地址可以是7位或10位。
紧跟设备地址的一个数据位R/W用来表示数据传输方向,数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
以EEPROM 24C01为例,其地址如图所示。
在这里插入图片描述
在这里插入图片描述

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值