0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

IIC串行总线的基本介绍与代码详解

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-05-16 11:53 次阅读

一. IIC的基本介绍

1.1IIC的简介

IIC是双线(不算地线)半双工的一种通讯方式(可以双向通讯,但不可以在同一时间双向数据传输).

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

poYBAGKByhiAGQdtAADmKEORS68800.png 图1 IIC拓扑网络

pYYBAGKB8UyADBK8AABsZuZeD2Q629.png图2 IIC时序图

1.2地址问题

IIC设备地址

协议格式中第一个字节(为slave address)由7位地址和一位R/W读写位组成的,这字节是个器件地址。

常用IIC接口通用器件的器件地址是由种类型号,及寻址码组成的,共7位。

如格式如下:

D7 D6 D5 D4 D3 D2 D1 D0

(1)、器件类型:D7-D4共4位决定的。这是由半导公司生产时就已固定此类型的了,也就是说这4位已是固定的。

(2)、用户自定义地址码:D3-D1共3位。这是由用户自己设置的,通常的作法如EEPROM这些器件是由外部IC的3个引脚所组合电平决定的(用常用的名字如A0,A1,A2)。这也就是寻址码。所以为什么同一IIC总线上同一型号的IC只能最多共挂8片同种类芯片的原因了。

(3)、最低一位就是R/W位,,“0”表示写,“1”表示读(通常读写信号中写上面有一横线,表示低电平)。所以IIC设备通常有两个地址,即读地址和写地址。

IIC 设备的7 位地址是就当前IIC总线而言的,是“相对地址”。不同的IIC总线上的设备可以使用相同的7 位地址,但是它们所在的i2c 总线不同。所以在系统中一个IIC设备的“绝对地址”由二元组(IIC适配器的ID 和设备在该总线上的7 位地址)表示。”,所以这个函数的作用主要是排除同一IIC总线上出现多个地址相同的设备。

1.3 IIC协议

IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。

pYYBAGKB8UyADBK8AABsZuZeD2Q629.png图2 IIC时序图

(1)空闲状态
当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

(2)起始信号与停止信号
起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;
停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

pYYBAGKB8qGAWwckAADQB9ng-r4474.png


(3) 应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。

应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。

pYYBAGKB8raAJG_fAAEXXyIFq2U865.png

(4)数据有效性
IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

poYBAGKB8tiAFBznAADZhgCofoM576.png

(5)数据的传达
在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

pYYBAGKB8uaAHOhbAAGvGCs9a88042.png

二.代码

关于IIC代码部分的内容这里主要讲解HAL块部分的内容。这里HAL初始化的三个部分包括:引脚配置初始化,写数据函数,读数据函数。

在引脚配置的 IICInit 中对IIC的两个 引脚(SCL,SDA)进行引脚的配置,并对IIC相关的库函数进行配置,其中引脚的配置这里不再进行讲解,需要注意的是GPIO的模式要配置成GPIO_MODE_AF_OD 复用开漏输出或者GPIO_Mode_Out_PP数据寄存器输出。

关于IIC的配置,IIC的模式,自身地址,

typedef struct
{
  uint32_t I2C_ClockSpeed;             /*设置SCL时钟频,此值不低于40000*/
  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;

• I2C_ClockSpeed 设置I2C的传输速率,在调用初始化函数时,函数会根据我们输入的数值经过运算后把时钟因子写入到I2C的时钟控制寄存器CCR。而我们写入的这个参数值不得高于400KHz。实际上由于CCR寄存器不能写入小数类型的时钟因子,影响到 SCL的实际频率可能会低于本成员设置的参数值,这时除了通讯稍慢一点以外,不会对I2C的标准通讯造成其它影响。

• I2C_Mode 选择I2C的使用方式,有I2C模式(I2C_Mode_I2C )和SMBus主、从模式(I2C_Mode_SMBusHost、 I2C_Mode_SMBusDevice ) 。 I2C不需要在此处区分主从模式,直接设置I2C_Mode_I2C即可。

• I2C_DutyCycle 设置I 2C的SCL线时钟的占空比。该配置有两个选择,分别为低电平时间比高电平时间为2:1 ( I2C_DutyCycle_2)和16:9 (I2C_DutyCycle_16_9)。其实这两个模式的比例差别并不大,一般要求都不会如此严格,这里随便选就可以了。

• I2C_OwnAddress1 配置STM32的I2C设备自己的地址,每个连接到I2C总线上的设备都要有一个自己的地址,作为主机也不例外。地址可设置为7位或10位(受下面 I2C_AcknowledgeAddress成员决定),只要该地址是I2C总线上唯一的即可。 STM32的I2C外设可同时使用两个地址,即同时对两个地址作出响应,这个结构成员I2C_OwnAddress1配置的是默认的、OAR1寄存器存储的地址,若需要设置第二个地址寄存器OAR2,可使用 I2C_OwnAddress2Config函数来配置,OAR2不支持10位地址。

• I2C_Ack_Enable 配置I 2C应答是否使能,设置为使能则可以发送响应信号。一般配置为允许应答(I2C_Ack_Enable),这是绝大多数遵循I 2C标准的设备的通讯要求,改为禁止应答(I2C_Ack_Disable)往往会导致通讯错误。

• I2C_AcknowledgeAddress 选择I2C的寻址模式是7位还是10位地址。这需要根据实际连接到I2C总线上设备的地址进行选择,这个成员的配置也影响到 I2C_OwnAddress1成员,只有这里设置成10位模式时, I2C_OwnAddress1才支持10位地址。

利用库函数版本编写HAL代码部分如下:

void IICInit(void)
{
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	/* 配置硬件IIC需要的变量 */ 
	I2C_InitTypeDef I2C_InitStructure; 

	/* 使能与 I2C1 有关的时钟 */
	RCC_APB2PeriphClockCmd  (RCC_APB2Periph_GPIOB,ENABLE ); 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);  

	/* PB6-I2C1_SCL、PB7-I2C1_SDA*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 
	GPIO_Init(GPIOB, &GPIO_InitStructure); 

	/*IIC外设初始化*/

	/* I2C 配置 */
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;     //配置为普通IIC模式
	//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; 
	//I2C_InitStructure.I2C_OwnAddress1 = SlaveAddress; 
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;  //使能自动应答   
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 
	I2C_InitStructure.I2C_ClockSpeed = 50000;   //5K的速度?


	/* I2C1 初始化 */
	I2C_Init(I2C1, &I2C_InitStructure);	   

	/* 使能 I2C1 */
	I2C_Cmd  (I2C1,ENABLE); 
	/*允许应答模式*/
	I2C_AcknowledgeConfig(I2C1, ENABLE);   
}

void ByteWrite(u8 addr,u8 dataValue)
{
	I2C_GenerateSTART(I2C1,ENABLE);

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));

	I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1,addr);

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_SendData(I2C1,dataValue);

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_GenerateSTOP(I2C1,ENABLE);

}

u8 ByteRead(u8 addr)
{
	u8 dataValue;

	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));

	I2C_GenerateSTART(I2C1,ENABLE);//起始信号

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));

	I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);//发送设备地址+写信号

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//

	I2C_Cmd(I2C1,ENABLE);

	I2C_SendData(I2C1,addr);//发送存储单元地址,从0开始

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_GenerateSTART(I2C1,ENABLE);//起始信号

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));

	I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Receiver);//发送设备地址+读信号

	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	I2C_AcknowledgeConfig(I2C1,DISABLE);

	I2C_GenerateSTOP(I2C1,ENABLE);

	while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)));

	dataValue=I2C_ReceiveData(I2C1);//读出寄存器数据

	return dataValue;
}

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • IIC
    IIC
    +关注

    关注

    11

    文章

    300

    浏览量

    38265
  • 串行总线
    +关注

    关注

    1

    文章

    181

    浏览量

    30596
  • 代码
    +关注

    关注

    30

    文章

    4741

    浏览量

    68321
收藏 人收藏

    评论

    相关推荐

    一文详解IIC总线

    IIC(Inter-Integrated Circuit)集成电路总线,它是一种两线式串行通信总线,又叫I2C,使用多主从架构,由飞利浦公司在1980年推出的。多用于主控制器和从器件间
    发表于 06-07 15:38 9629次阅读
    一文<b class='flag-5'>详解</b><b class='flag-5'>IIC</b><b class='flag-5'>总线</b>

    一文详解IIC总线

    IIC(Inter-Integrated Circuit)是一个多主从的串行总线,又叫I2C,是由飞利浦公司发明的通讯总线,属于半双工同步传输类型
    发表于 09-12 11:15 2066次阅读
    一文<b class='flag-5'>详解</b><b class='flag-5'>IIC</b><b class='flag-5'>总线</b>

    介绍IIC总线仲裁

    IIC总线
    电子电器
    发布于 :2023年02月07日 11:24:43

    IIC总线串行技术

    IIC总线串行技术的电子书
    发表于 02-19 16:32

    IIC总线和SPI总线通信详解

    IIC总线和SPI总线通信介绍
    发表于 12-23 07:02

    IIC总线介绍

    1.IIC总线介绍第一:I2C(IIC,Inter-Integrated Circuit),两线式串行
    发表于 08-18 06:03

    串行通信中的IIC总线工作原理是什么

    串行通信中的IIC总线工作原理51本身不带IIC总线 ,使用程序模拟IIC通信协议常用的
    发表于 12-08 07:52

    IIC串行总线的组成及工作原理

    **EEPROM芯片:**掉电不会丢失数据,可以保存数据。IIC串行总线的组成及工作原理:
    发表于 02-23 06:53

    IIC总线的相关资料推荐

    本文是本人对于IIC总线一知半解的陈述,后续在习得知识内容后会进行不断更新,若文章中有错误的地方,希望各位读者及时指正一.IIC物理层面的简要介绍
    发表于 02-28 12:40

    IIC总线接口学习

    在多主设备IIC 总线模式下,多个S3C2440A 微处理器可以从从属设备接收或发送串行数据。主设备S3C2440A 可以初始化和终止一个基于IIC
    发表于 04-27 15:31 61次下载
    <b class='flag-5'>IIC</b><b class='flag-5'>总线</b>接口学习

    IIC总线时序详解

    AT24C02是由ATMEL公司提供的,IIC总线串行EEPROM(electronic eraser programmer read only memory),其容量为2kbit(256B),工作电压在2.7v“5.5v之间,
    发表于 11-16 14:29 1.2w次阅读
    <b class='flag-5'>IIC</b><b class='flag-5'>总线</b>时序<b class='flag-5'>详解</b>

    IIC总线初始化基本驱动参考程序应用代码免费下载

    本文档的主要内容详细介绍的是IIC总线初始化基本驱动参考程序应用代码免费下载。程序功能:为IIC总线
    发表于 01-16 08:00 5次下载
    <b class='flag-5'>IIC</b><b class='flag-5'>总线</b>初始化基本驱动参考程序应用<b class='flag-5'>代码</b>免费下载

    详解串行总线中的SATA协议

    书接上回-《串行总线技术(一)-串行总线结构(以PCIe为例)》《串行总线技术(二)-
    的头像 发表于 11-01 10:53 9894次阅读

    STM32----IIC详解

    一.IIC简介1.IIC总线概述IIC总线是飞利浦公司研发的两线制串行通信
    发表于 11-23 18:21 11次下载
    STM32----<b class='flag-5'>IIC</b><b class='flag-5'>详解</b>

    AXI IIC总线接口介绍

    LogiCORE™IPAXI IIC总线接口连接到AMBA®AXI规范,提供低速、两线串行总线接口,可连接大量流行的设备。
    的头像 发表于 09-28 15:56 5181次阅读