STM32_5:I2C

目录

1.IIC协议

1、什么是IIC通信?

2、IIC硬件电路

3、IIC软件协议

start起始条件

stop终止条件

发送一个字节

接收一个字节

发送应答信号ack

接收应答信号ack

2.IIC的时序

1、IIC指定地址写时序

2、IIC指定地址读时序

3.硬件IIC和软件IIC

1、硬件IIC

2、软件IIC

[4.IIC 外设框图](#4.IIC 外设框图)

1.I2C架构

1.通讯引脚

2.时钟控制逻辑

计算时钟频率

3.数据控制逻辑

2、发送数据

3、接收数据

5.硬件IIC配置

1、结构体

1.I2C_ClockSpeed

2.I2C_Mode

3.I2C_DutyCycle

4.I2C_OwnAddress1

5.I2C_Ack_Enable

6.I2C_AcknowledgeAddress

6.软件IIC配置

1、起始信号函数

7.滴答定时器

1.系统定时器-SysTick

2.计算

3.结构体

4.SysTick中断优先级


1.IIC协议

1、什么是IIC通信?

两个芯片之间应该如何通信?常见的通信协议比如IIC、SPI、usart,这些通信协议就是规范数据传输与交换的规则,IIC(全称Inter -integrated Circuit)是一种串行通信总线协议,目的是用于连接集成电路(IC)之间的通信。IIC由飞利浦公司,也就是现在的NXP半导体开发,是一种双向通信协议,需要两根线,时钟线(SCL)和数据线(SDA),其中 SCL时钟线是由主设备提供时钟信号来同步数据传输,SDA用来传输数据(双向)。

2、IIC硬件电路

  • 硬件规定包含:硬件连接、端口输入输出模式等
  • 主机对SCL线:任何时候都完全控制,从机任何时候都不能控制SCL线
  • 主机对SDA线:空闲状态下,主机可以发起对SDA数据线的控制,只有从机发送数据与从机应答的时候,主机才会转交SDA数据线的控制权给从机。
  • 所有设备的SCL和SDA连在一起
  • SCL和SDA各添加一个上拉电阻,阻值一般为4.7kΩ
  • 设备的SCL和SDA均要配置为开漏输出模式,再通过上拉电阻实现弱上拉
  • 开漏加弱上拉模式,同时具备了输出与输入的功能。如果想要输入数据,观察电平变化
  • 在开漏模式下,输出高电平就相当于断开引脚
  • 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备直接的访问。
  • 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定哪个设备占用总线。
  • 具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达3.4M/s,但目前大多IIC设备尚不支持高速模式。

IIC高阻态

  • 漏极开路(Open Drain)即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻
  • 高阻状态:高阻状态是三态门电路的一种状态。逻辑门的输出除有高、低电平两种状 态外,还有第三种状态------高阻状态的门电路。电路分析时高阻态可做开路理解。
  • 我们知道IIC的所有设备是接在一根总线上的,那么我们进行通信的时候往往只是几个设备进行通信,那么这时候其余的空闲设备可能会受到总线干扰,或者干扰到总线, 怎么办呢?
  • 为了避免总线信号的混乱,IIC的空闲状态只能有外部上拉, 而此时空闲设备被拉到了高阻态,也就是相当于断路, 整个IIC总线只有开启了的设备才会正常进行通信, 而不会干扰到其他设备。

3、IIC软件协议

软件规定包括:时序的定义、字节的传输、高位或低位先行、一个完整的时序由以下部分组成

IIC时序的基本单元

start起始条件

SCL高电平期间,SDA从高电平切换为低电平,即SCL不动,SDA被拽下来,产生一个下降沿,当从机捕获到SCL高电平,SDA下降沿时,就会自动进行自身的复位,等待主机召唤。

起始信号:当SCL为高电平期间,SDA有高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。

停止信号:当SCL为高电平期间,SDA由低到高的跳变;停止信号也是一种高电平跳变时序信号,而不是一个电平信号

起始信号和停止信号一般由主机产生

stop终止条件

SCL高电平期间,SDA从低电平切换为高电平,一个完整的数据帧总是以起始信号开始,终止信号结束,起始信号与终止信号都是由从机产生,在空闲状态下,从机必须双手放开。

发送一个字节

SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL, 从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许由有数据变化,依次循环这个过程8次,即可发送一个字节。 总结:(SCL)低电平切换(放)数据,高电平读取(读)数据

接收一个字节

SCL低电平期间,从机数据依次放到SDA线上(高位先行),然后主机释放SCL, 主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程八次,即可接收一个字节(主机在接收之前,需要释放 SDA).

数据的有效性

IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在SCL的每个时钟周期传输一位数据。

即:数据在SCL的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定

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

发送应答信号ack

主机在接收一个完整字节之后,在下一个时钟发送一位数据。规则:数据0表示应答,数据1 表示非应答。发送应答信号是为了告诉从机,主机是否还要数据 (命令从机发不发数据)。

目的是为了通知从机是否继续发送数据。

接收应答信号ack

主机在接收一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前需要释放SDA)。规则:数据 0表示应答,数据1表示非应答。

从机告诉主机接收到了主机传递的数据了,主机刚发送一个字节,就立刻说有没有人收到数据(SDA高),如果有接收数据就会立马回应(SDA拉低)。

目的:判断从机是否接收到了主机发送的数据

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位)表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。

如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

2.IIC的时序

1、IIC指定地址写时序

slave address:设备地址 reg address:寄存器地址, 时序:

  • 开始条件
  • 七位从机地址+1位RW(读:1,写:0)
  • 接受从机的应答位(Receive ACK,RA)
  • 发送寄存器地址
  • 接收从机应答
  • 发送一个字节的数据
  • 从机应答
  • 结束

S:数据由主机传输至从机 P:数据传输结束 SLAVE ADDRESS : 从机地址

起始信号产生后,所有从机就开始接收广播的从机地址信号。IIC总线,每个设备的地址都是唯一的,当主机广播的地址与某个设备的地址相同时,这个设备就被选中了,没被选中的设备讲会忽略之后的数据信号。根据IIC协议,这个从机地址可以是7位或10位。

地址位之后,传输方向选择位,为0:表示数据传输方向是由主机传输至从机,即主机向从机写数据。为1:则相反。从机接收传输方向选择位后,主机或从机会返回一个应答(ACK)或非应答(NACK)信号,只有接收到应答信号后,主机才能继续发送或接收数据。

2、IIC指定地址读时序

  • 开始条件
  • 七位从机地址+1位RW(读:1,写:0)
  • 从机应答
  • 发送寄存器地址
  • 从机应答
  • 当主机收到应答信号后,主机要改变通信模式(主机将由发送变为接收,从机将由接收变为发送)所以主机重新发送一个开始start信号,然后紧跟着发送一个从机地址,注 意此时该地址的第8位为1,表明将主机设置成接收模式开始读取数据
  • 从机应答
  • 读取一个字节
  • 主机发送非应答
  • 结束

配置方向传输位为"读数据"方向。广播完地址后,接收到应答信号后,从机开始向主机返回数据(DATA),数据包大小也为8位,从机每发送完一个数,都会等待主机的应答信号(ACK),重复这个过程,可以返回N个数据,N没有限制大小。当主机希望停止接收数据时,就向从机返回一个非应答信号(NCAK),则从机自动停止数据传输。

通讯复合格式,该传输过程有两次起始信号(S),在第一次传输过程中,主机通过SLAVE_ADDRESS寻找到从设备后,发送一段"数据",这段数据通常用于表示从设备内部的寄存器或存储器地址;第二次传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。

3.硬件IIC和软件IIC

1、硬件IIC

硬件IIC是由STM32内部的硬件模块实现的,使用CPU的时钟信号来控制数据传输和时序, 通信速度较快,可以达到几十MHz的速度。硬件IIC的实现相对简单,无需编写复杂的代码,因此在实现IIC通信时,硬件IIC通常是首选的方式。硬件IIC的主要优点有:

  1. 速度快、可以实现高速通信
  2. 实现简单、无需编写复杂时序代码
  3. 稳定性好、不容易出现通信错误

2、软件IIC

软件IIC是由CPU的GPIO模拟实现的,通过CPU的软件来控制时序和数据传输,通信速度相对较慢,一般在几十kHz到几百kHz之间。软件IIC的实现相对复杂,需要编写复杂的代码, 因此在实现IIC通信时,软件IIC通常是在硬件IIC无法满足需求时才采用的方式。软件IIC的主要优点有:

  1. 可以实现多路IIC通信,硬件IIC一般只能实现单路通信
  2. 可以在STM32的任何GPIO上实现IIC通信,相对灵活
  3. 可以实现任意时序,更加灵活

总的来说,硬件IIC和软件IIC各有优缺点,选择哪种方式要根据具体的应用需求进行选择。如果需要高速通信,建议选择硬件IIC;如果需要多路通信或者灵活的时序控制,建议选择软件IIC。

4.IIC 外设框图

1.I2C架构

通讯引脚-时钟控制逻辑-数据控制逻辑-整体控制逻辑

1.通讯引脚

STM32芯片有多个IIC外设,它们的IIC通讯信号引出到不同的GPIO引脚上,使用时必须配置这些指定的引脚。

2.时钟控制逻辑

SCL线的时钟信号,由IIC接口根据时钟控制寄存器(CCR)控制,控制的参数主要为时钟频率。

  • 可选择IIC通讯的"标准/快速"模式,这两个模式分别对应100/400Kbits/s的通讯速率。

  • 在快速模式下可选择SCL时钟的占空比,可选T(low)/T(high) = 2或T(low)/T(high)=16/9模式。

  • CCR寄存器中12位的配置因子CCR,它与IIC外设的输入时钟源共用作用,产生SCL时钟。STM32的IIC外设输入时钟源位PCKL1

计算时钟频率

标准模式

T high = CCR *T pckl1,T low= CCR*Tpclk1

快速模式中 Tlow/Tlow =2时:

Thigh = CCR*Tpckl1,T low = 2*low*Tpckl1

快速模式中 Tlow/Tlow =16/9时:

Thigh = 9*CCR*Tpckl1,T low = 16*low*Tpckl1

PCLK1 = 36MHz,想要配置400Kbits/s 方法:

PCLK时钟周期: TPCLK1 = 1/36 000 000

目标SCL时钟周期: TSCL = 1/400 000

SCL时钟周期内的高电平时间: Thigh = TSCL/3

SCL时钟周期内的低电平时间: Tlow = 2*TSCL/3

计算CCR的值 : CCR = THIGH/TPCLK1 = 30

计算出来的值写入到寄存器即可

3.数据控制逻辑

IIC的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。

当向外发送数据的时候,数据移位寄存器以"数据寄存器"为数据源,把数据一位一位地通过SDA信号线发送出去。

当从外部接收数据的时候,数据移位寄存器把SDA信号线采样到的数据一位一位地存储到"数据寄存器"中。

发送数据和接收数据的核心部分是数据寄存器和数据移位寄存器

2、发送数据

当我们发送数据时,可以把一个字节的数据写到数据寄存器DR中,当数据移位寄存器没有数据移位时,这个数据寄存器的值会进一步转到移位寄存器里,在移位的过程中,我们就可以直接把下一个数据放到数据寄存器中里等着,一旦前一个数据移位完成,下一个数据就可以无缝衔接继续发送,当数据由数据寄存器转移到数据移位寄存器时,置状态寄存器 TXE(TX empty)位为1,表示发送寄存器为空。

主发送器通讯过程

1.控制产生起始信号(S),当发生起始信号后,它产生事件"EV5",并会对SR1寄存器的 SB 位置1,表示起始信号已经发生。

2.发生设备地址并等待应答信号,若有从机应答,则产生事件 EV6 及 EV8 ,这时SR1寄存器的 ADDR位及 TXE位被置1,ADDR位1 表示地址已经发送,TEX表示数据寄存器为空。

3.往IIC的数据寄存器DR写入要发送的数据,这时TXE位会被置0,表示数据寄存器非空,IIC外设通过SDA信号线一位位把数据发送出去后,又会产生EV8事件,即TXE被置1,重复这个过程,可发送多个字节。

4.发送数据完成后,控制IIC设备产生一个停止信号P,这个时候产生EV2事件,SR1的TEX位及BTF位被置1,表示通讯结束。、

注:SR1(Status Register 1)是I2C主设备(或当前作为主控制器角色的设备)内部的状态寄存器,用于告诉CPU"I2C硬件模块当前正在发生什么事件"。

  • 物理主设备:I2C硬件模块
  • 逻辑控制者:CPU(执行软件)
  • 通信状态:记录在I2C模块的SR1寄存器中,供CPU查询

3、接收数据

输入的数据一位一位的从引脚移入到移位寄存器里,当一个字节的数据收齐之后,数据就会整体从移位寄存器转到数据寄存器,同时置标志位RXNE(RX not empty)为1,表示接收寄存器非空,这时就可以把数据从数据寄存器读出来。在IIC中数据收发是用一组数据寄存器与数据移位寄存器。通过控制寄存器的对应位控制什么时候收什么时候发。

5.硬件IIC配置

1、结构体

cs 复制代码
typedef struct {
    uint32_t I2C_ClockSpeed;   /*!< 设置SCL时钟频率,此值要低于400000*/
    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;

1.I2C_ClockSpeed

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

2.I2C_Mode

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

3.I2C_DutyCycle

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

4.I2C_OwnAddress1

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

5.I2C_Ack_Enable

本成员是关于I2C应答设置,设置为使能则可以发送响应信号。本实验配置为允许应答 (I2C_Ack_Enable), 这是绝大多数遵循I2C标准的设备的通讯要求,改为禁止应答 (I2C_Ack_Disable)往往会导致通讯错误。

6.I2C_AcknowledgeAddress

本成员选择I2C的寻址模式是7位还是10位地址。这需要根据实际连接到I2C总线上设备的地址进行选择,这个成员的配置也影响到I2C_OwnAddress1成员, 只有这里设置成10位模式时,I2C_OwnAddress1才支持10位地址。 配置完这些结构体成员值,调用库函数I2C_Init即可把结构体的配置写入到寄存器中

6.软件IIC配置

1、起始信号函数

void My_IIC_Start(void)

{

MyI2C_W_SDA(1); //释放数据线

MyI2C_W_SCL(1); //释放时钟线

MyI2C_W_SDA(0); //下拉数据线

MyI2C_W_SCL(0); //下拉时钟线

}

2、停止信号函数

void My_IIC_Stop(void)

{

MyI2C_W_SDA(0); //下拉数据线

MyI2C_W_SCL(1); //释放时钟线

MyI2C_W_SDA(1); //释放数据线

}

3、IIC发送一个字节函数

void MyI2C_SendByte(uint8_t Byte)

{

uint8_t i;

for (i = 0; i < 8; i++) //循环发送8次,完成一个字节的发送

{

MyI2C_W_SDA(Byte & (0x80 >> i)); //循环发送8次,完成一个字节的发送

MyI2C_W_SCL(1); //释放时钟线

MyI2C_W_SCL(0); //释放时钟线

}

}

4、IIC接收一个字节函数

5、IIC发送应答信号函数

6、IIC接收应答信号函数

7.滴答定时器

1.系统定时器-SysTick

SysTick : 24位系统定时器,只能递减,存在于内核嵌套在NVIC中。所有的Cortex-M中都有这个系统定时器。

重装载值reload 递减,当递减到0会触发中断并且会有置位countflag标志,VAL表示当前值。

然后reload继续从预设值开始递减,周而复始。

2.计算

T : 一个计数循环的时间,跟reload和 CLK有关

CLK : 72M 或者9 M, 由CTRL寄存器配置

reload : 24位,用户自己配置

T = reload * (1/ CLK)

CLK= 72M, 1us = (72 )* (1/ 72 000 000)

CLK= 72M, 1ms = (72 000 )* (1/ 72 000 000)

时间单位换算: 1s = 1000ms = 1000 000 us = 1000 000 000 ns

3.结构体

typedef struct

{

__IO uint32_t CTRL; //控制及状态寄存器

__IO uint32_t LOAD; //重装载寄存器

__IO uint32_t VAL; //重装载寄存器

__I uint32_t CALIB; //校准寄存器

} SysTick_Type;

4.SysTick中断优先级

①system tick 属于内核的外设,它的中断优先级与片上外设的中断优先级高

②systick 中断优先级配置的是scb->shprx寄存器

外设中断优先级配置的是nvic-> iprx寄存器

有优先级分组

①STM32的外设(内核还是片上)都是使用4个二进制来表示中断优先级

②中断优先级的分组对内核和外设同样适用,只需要将中断优先级的四个位按外设优先级来分组即可,人为的进行分出抢占优先级和子优先级。例举:

1<<4 -1=16 -1= 15 (1 1 1 1 )

前面两位表示抢占优先级 后面两位表示子优先级

3 3

① 编写一个us延时的函数

②编写一个ms延时的函数

cs 复制代码
#include "stm32f10x.h"
#include "systick.h"



void us_delay( uint32_t us)
{
	uint32_t i;
	
	SysTick_Config(72);
	for(i = 0;i < us;i++)
	{
		while(  !((SysTick->CTRL) & (1<<16) )  );
	}
	
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}	


void ms_delay( uint32_t ms)
{
	uint32_t i;
	
	SysTick_Config(72000);
	for(i = 0;i < ms;i++)
	{
		while(  !((SysTick->CTRL) & (1<<16) )  );
	}
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
	
}	

注:SysTick_Config()设置自动重装载寄存器的值

SysTick_Config(72);即完成一次循环为1us,完成多少次循环就延时多少秒,通过判断COUNT_FLAG的值来判断一次计数是否完成,完成后,失能系统时钟

相关推荐
我先去打把游戏先12 小时前
TCP、TLS、HTTP、HTTPS、MQTT、MQTTS几种网络协议的对比与解释
嵌入式硬件·mcu·物联网·网络协议·tcp/ip·http·aws
IT方大同12 小时前
实时时钟RTC
嵌入式硬件·实时音视频
点灯小铭12 小时前
基于单片机的社区医院小型高压蒸汽灭菌自动控制器设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
youcans_12 小时前
【动手学STM32G4】(3)STM32G431之定时器
stm32·单片机·嵌入式硬件·定时器
悠哉悠哉愿意12 小时前
【嵌入式学习笔记】AD/DA
笔记·单片机·嵌入式硬件·学习
松涛和鸣13 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html
阿凉070213 小时前
新版本JLink安装目录中缺失JLinkDevices.xml添加方法
xml·嵌入式硬件
范纹杉想快点毕业13 小时前
《嵌入式通信与数据管理:从状态机到环形队列的完整实战指南》
单片机·嵌入式硬件
硬汉嵌入式13 小时前
ST最新推出的CMSIS-Driver,一套驱动完成对所有STM32系列的驱动支持
stm32·st·cmsis-driver
点灯小铭13 小时前
基于单片机的硫化氢、氨气、甲烷、一氧化碳气体多种有害气体检测与声光报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业