video: https://mp.weixin.qq.com/mp/readtemplate?t=pages/video_player_tmpl&action=mpvideo&auto=0&vid=wxv_3732492162420817931
IIC(Inter-Integrated Circuit 集成电路总线),又称为I2C或I2C,这种总线类型是由原飞利浦公司(现恩智浦公司)在80年代初设计出来的一种简单、双向、二线制、同步串行总线。1 I2C通信原理I2C总线是一种用于IC器件之间连接的2线制串行扩展总线,它通过2根信号线(SDA,串行数据线;SCL,串行时钟线)在连接到总线上的器件之间传送数据,所有连接在总线的I2C器件都可以工作于发送方式或接收方式。1.1 I2C串行总线概述如图1所示,I2C总线的SDA和SCL是双向I/O线,必须通过上拉电阻接到正电源,当总线空闲时,2线都是“高”。所有连接在I2C总线上的器件引脚必须是开漏或集电极开路输出,即具有“线与”功能。所有挂在总线上器件的I2C引脚接口也应该是双向的;SDA输出电路用于总线上发数据,而SDA输入电路用于接收总线上的数据;主机通过SCL输出电路发送时钟信号,同时其本身的接收电路要检测总线上SCL电平,以决定下一步的动作,从机的SCL输入电路接收总线时钟,并在SCL控制下向SDA发出或从SDA上接收数据,另外也可以通过拉低SCL(输出)来延长总线周期。
图1 I2C总线结构1.2 I2C总线的数据传送1.数据位的有效性规定如图2所示,I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
图2 I2C总线数据有效性规定2.起始和终止信号如图3所示,SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
图3 I2C总线起始和终止信号3.数据传送格式(1)字节传送与应答在I2C总线的数据传输过程中,发送到SDA信号线上的数据以字节为单位,每个字节必须为8位,而且是高位(MSB)在前,低位(LSB)在后,每次发送数据的字节数量不受限制。但在这个数据传输过程中需要着重强调的是,当发送方发送完每一字节后,都必须等待接收方返回一个应答响应信号,如图4所示。响应信号宽度为1位,紧跟在8个数据位后面,所以发送1字节的数据需要9个SCL时钟脉冲。响应时钟脉冲也是由主机产生的,主机在响应时钟脉冲期间释放SDA线,使其处在高电平。而在响应时钟脉冲期间,接收方需要将SDA拉低,使SDA在响应时钟脉冲高电平期间保持稳定的低电平,即为有效应答信号(ACK或A),表示接收器已经成功地接收了该字节数据。如果在响应时钟脉冲期间,接收方没有将SDA线拉低,使SDA在响应时钟脉冲高电平期间保持稳定的高电平,即为非应答信号(NAK或/A),表示接收器接收该字节没有成功。
图4 I2C总线字节传送与应答 (2)总线的寻址挂在I2C总线上的器件可以很多,但相互间只有两根线连接(数据线和时钟线),如何进行识别寻址呢?具有I2C总线结构的器件在其出厂时已经给定了器件的地址编码。I2C总线器件地址SLA(以7位为例)格式如图5所示。
图5 I2C总线器件地址格式1)DA3~DA0:4位器件地址是I2C总线器件固有的地址编码,器件出厂时就已给定,用户不能自行设置。例如I2C总线器件E2PROM AT24CXX的器件地址为1010。2)A2~A0:3位引脚地址用于相同地址器件的识别。若I2C总线上挂有相同地址的器件,或同时挂有多片相同器件时,可用硬件连接方式对3位引脚A2~A0接Vcc或接地,形成地址数据。3)
:数据传送方向。
=1时,主机接收(读);
=0,主机发送(写)。主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,并根据
位将自己确定为发送器或接收器。(3)数据帧格式I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。在总线的一次数据传送过程中,可以有以下几种组合方式:a)主机向从机写数据主机向从机写n个字节数据,数据传送方向在整个传送过程中不变。I2C的数据线SDA上的数据流如图6所示。有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A表示应答,
表示非应答(高电平)。S表示起始信号,P表示终止信号。
图6 主机向从机写数据SDA数据流b)主机从从机读数据主机从从机读n个字节数据时,I2C的数据线SDA上的数据流如图7所示。其中,阴影框表示数据由主机传输到从机,无阴影部分表示数据流由从机传输到主机。
图7 主机从从机读数据时SDA上的数据流c) 主机和从机双向数据传送在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相。I2C的数据线SDA上的数据流如图8所示。
图8 主机和从机双向数据传送SDA上的数据流主机和从机双向数据传送的数据传送过程是主机向从机写数据和主机由从机读数据的组合,故不再赘述。4.传输速率I2C的标准传输速率为100kb/s,快速传输可达400kb/s。目前还增加了高速模式,最高传输速率可达3.4Mb/s。2 EEPROM存储芯片24C02EEPROM是指带电可擦可编程只读存储器,是一种掉电后数据不丢失的存储芯片。EEPROM可以在计算机上或专用设备上擦除已有信息,重新编程。其具有即插即用、可读可写、断电数据不丢失等特点,在嵌入式系统中主要用于保存系统配置信息或间歇采集数据等。 本书配套开发板上有一个I2C接口的EEPROM芯片AT24C02,是ATMEL公司的产品。还有其他一些厂家的芯片与AT24C02引脚和功能完全兼容,本书将这一类芯片简称为24C02。开发板上24C02电路连接如图9所示,由图可知,24C02芯片使用STM32F407微控制器的I2C1接口,SCL引脚连接至MCU的I2C1_SCL引脚PB8,SDA引脚连接至MCU的I2C1_SDA引脚PB9。WP是写保护引脚,WP接地时,对24C02芯片可读可写。
图9 EEPROM存储器电路图在I2C总线上面,每个器件都会有一个器件地址,而24C02的器件地址编址方式如图5所示,由图可知,从机地址高四位1010是24Cxx系列的固定器件地址,引脚地址A2、A1、A0是根据器件连接来决定,由图9可知,3个引脚均接地,所以是000。
为是选择读还是写,1的时候是读,0的时候是写。所以24C02存储器的写地址为0xA0,读地址为0xA1。需要指出的是在使用HAL库数据传输函数时,从设备的地址只需要给出芯片写地址即可,驱动函数内部会根据读写操作类型,自动使用写操作地址或读操作地址。而使用MCU普通GPIO模拟I2C接口时序时需要用户根据读写指令送出读写操作地址。3 EEPROM存储复位次数项目 EEPROM存储器可读可写、断电数据不丢失,用于存储系统的设置信息或重要数据常量是很合适的。3.1 项目分析本项目实现一个简单功能,即开发板每次开机,系统复位次数加1,同时在调试阶段可对复位次数清零。由于EEPROM存储器具有断电数据不丢失,可随机读写等优点,所以本例选用EEPROM存储器AT24C02存储系统复位次数,其与微控制器采用硬件I2C接口。具体实施方法为,系统每次上电复位时从AT24C02芯片指定单元读出复位次数,将其加1后在LCD右上角显示,并将新的数值再写入AT24C02相应存储单元。为使系统在调试阶段能够清零复位次数,项目采用条件编译方式处理,当系统调试时定义某一标识符,编译相应清零代码,当系统正常运行时将该宏定义注释即可。3.2 项目实施1.复制工程文件复制第12章创建的工程模板文件夹1202 Chinese Show到桌面,并将文件夹重命名为1301 I2C EEPROM。2.CubeMX配置打开工程模板文件夹里面的Template.ioc文件,启动CubeMX配置软件,在左侧配置类别Categories下面的Connectivity列表中的找到I2C1接口,打开其配置对话框,操作界面如图10所示。在模式设置中,设置接口类型为I2C。
图10 I2C1模式与参数配置I2C1的参数设置分为两组,分别为Master Features和Slave Features两个类别。(1)Master Features组,主设备参数
I2C Speed Mode:速度模式,可选Standard Mode(标准模式)或Fast Mode(快速模式)。
I2C Clock Speed (Hz):I2C时钟速度,标准模式最大值为100kHz,快速模式最大值为400kHz。
Fast Mode Duty Cycle:快速模式占空比,选择快速模式后这个参数会出现。
本例中I2C Speed Mode选择Standard Mode,I2C Clock Speed会自动设置为100kHz,同时Fast Mode Duty Cycle选项不会出现。(2)Slave Features组,从设备参数
Clock No Stretch Mode:禁止时钟延长,设置为Disabled表示允许时钟延长。
Primary Address Length selection:设备主地址长度,可选7-bit或10-bit,此处选择7-bit。
Dual Address Acknowledged:双地址确认,从设备可以有两个地址,此处选择Disable。
Primary slave address:从设备主地址,接口设备作为I2C从设备使用时才需要设置。
General Call address detection:广播呼叫检测,此处选择Disable。
| 启用I2C1接口后,CubeMX自动分配的引脚可能是PB6和PB7,而不是开发板上实际使用的PB8和PB9。在引脚视图上直接将PB8设置为I2C1_SCL,将PB9设置为I2C1_SDA,PB6和PB7的引脚配置就会自动取消。 | I2C1的GPIO引脚设置结果如图11所示,工作模式自动设置为复用功能开漏。
图11 I2C1的GPIO配置在开发板上,STM32F407是I2C主设备,所以无须设置从设备地址;24C02是I2C从设备,其从设备写操作地址是0xA0。由于I2C通信是一种应答式的通信,与其他外设的轮询操作类似,本例不开启I2C1的全局中断。3.I2C初始化代码分析打开MDK-RAM文件夹下面的工程文件Template.uvprojx,将生成工程编译一下,没有错误和警告之后开始初始化代码分析。I2C接口初始化程序位于CubeMX自动生成的i2c.c文件当中。函数MX_I2C1_Init()用于完成I2C1接口的初始化,其主要工作是对I2C结构体变量hi2c1各成员变量赋值,各赋值语句与CubeMX中的设置是对应的。完成hi2c1的赋值后,调用I2C初始化函数对I2C1接口进行初始化。函数HAL_I2C_MspInit()是I2C接口的MSP函数,在函数HAL_I2C_Init()中被调用,其主要功能是对I2C1接口的复用引脚PB8和PB9进行GPIO初始化并使能I2C1外设时钟。 4.用户程序编写为实现项目功能还需要编写用户程序,程序主要存放于main.c文件当中,其中省略了部分与以往章节相同功能代码。
/* ---------------------------------------Source File main.c--------------------------------------------- */
//#define DEBUG //调试时使用该宏定义
#include "main.h"
#include "i2c.h"
#include "spi.h"
#include "gpio.h"
#include "fsmc.h"
#include "lcd.h"
#include "flash.h"
#include "stdio.h"
uint8_t StartValue=0,ResetTimes=0;
void SystemClock_Config(void);
uint8_t KeyScan(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_FSMC_Init();
MX_SPI1_Init();
MX_I2C1_Init();
#ifdef DEBUG
HAL_I2C_Mem_Write(&hi2c1,0xA0,0,I2C_MEMADD_SIZE_8BIT,&StartValue,1,400);
#endif
HAL_I2C_Mem_Read(&hi2c1,0xA0,0,I2C_MEMADD_SIZE_8BIT,&ResetTimes,1,400);
LCD_Init();
LCD_Clear(BLUE);
ResetTimes++;
HAL_I2C_Mem_Write(&hi2c1,0xA0,0,I2C_MEMADD_SIZE_8BIT,&ResetTimes,1,400);
LCD_ShowIntNum(319-32,0,ResetTimes,2,WHITE,BLUE,32);
while (1)
{
}
}上述代码较为简单,主要使用HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()两个函数完成I2C的读写,在上述代码中已作加粗显示。同时为使程序能对I2C存储单元初始化,程序中使用了条件编译格式,当用户需将复位次数清零时,仅需定义DEBUG标识符即可,如果处于正常运行状态时,需要将该宏定义语句注释。 5.下载调试编译工程,直到没有错误为止,下载程序到开发板,复位运行,检查实验效果。4 使用教材
5 教程下载STM32项目实例:I2C接口与24C02访问.docx
|