STM32-IIC

图片均来自江科大STM32教学PPT

IIC

IIC简介

  • I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)
  • 同步,半双工
  • 带数据应答
  • 支持总线挂载多设备(一主多从、多主多从)

硬件电路

  • 所有I2C设备的SCL连在一起,SDA连在一起
  • 设备的SCL和SDA均要配置成开漏输出模式
  • SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右

在这里插入图片描述

IIC时序基本单元

  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平,然后主机要把SCL拽下来(占用SCL总线),也是方便基本时序单元拼接(低电平开始,低电平结束)。
  • 终止条件:SCL先放手回弹至高电平,高电平期间,SDA从低电平切换到高电平,产生一个上升沿,作为终止条件。
  • 起始和终止都是由主机产生,总线空闲状态时,从机始终放手。

在这里插入图片描述


实线代表主机控制,虚线代表从机控制

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

IIC时序

指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)

  • 指定设备(Slave Address):从机地址
  • 指定地址(Reg Address):某个设备内,寄存器地址
  • 指定数据(Data):要在寄存器中写入的数据

在这里插入图片描述

  • 第一个字节:从机地址(7位)+读写位(1位)
  • 接跟着就是接收从机的应答位
  • 最后主机不需要发送数据,就产生停止条件。在停止条件前,先拉低SDA,为后续 SDA的上升沿做准备。然后释放SCL,再释放SDA。这样就产生了SCL高电平期间,SDA产生上升沿。

当前地址读

对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)
在这里插入图片描述

主机发出了“读”的命令,随后数据传输方向就要反过来。从机发,主机读。要把SDA的控制权交给从机,主机调用接收一个字节的时序,进行接收操作。从机在SCL低电平写入SDA,主机在SCL高电平期间读取SDA。

【在读的时序中,IIC协议规定是,主机进行寻址时,一旦读(1)写(0)标志位给1,下一个字节就必须立马转为读的时序,所以主机还来不及指定,要读哪个寄存器,就得开始接收,所以这里就没有指定地址的环节,就需要用到当前地址指针】

指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)

在这里插入图片描述

  • 第二个字节就是用来指定地址,地址指针就指向了这个地址,
  • 紧接着不给发写入数据,而是直接再来个起始条件,重新寻址(从机地址),指定读写标志位(因为时要读,就写1),
  • 接着,主机接收一个字节,这个字节就是地址指针指向的地址下的数据。
  • 指针地址会在读写操作后自增。
  • 如果只读一个字节就停止,就要给从机发个非应答,然后从机就会释放总线,把SDA的控制权交还给主机。
  • 从机发送数据的权利开始于读写标志位为1,结束于主机应答为1。

软件模拟IIC代码示例

IIC.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

//	用于将SCL信号线设置为指定值。GPIOB的Pin10被用来控制SCL信号线
void MyI2C_W_SCL(uint8_t BitValue)
{
   
    GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
    Delay_us(10);
}

//	用于将SDA信号线设置为指定值。GPIOB的Pin11被用来控制SDA信号线。
void MyI2C_W_SDA(uint8_t BitValue)
{
   
    GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
    Delay_us(10);
}

//	用于读取SDA信号线的值。GPIOB的Pin11被用来读取SDA信号线的值
uint8_t MyI2C_R_SDA(void)
{
   
    uint8_t BitValue;
    BitValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
    Delay_us(10);
    return BitValue;
}

//	用于初始化IIC总线
void MyI2C_Init(void)
{
   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    // SCL和SDA都处于高电平,空闲状态
    GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);
}

//	用于发送起始信号
void MyI2C_Start(void)
{
   
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);

    MyI2C_W_SDA(0);
    MyI2C_W_SCL(0)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值