STM32/软件I2C和硬件I2C

目录

1 I2C协议

1.1 I2C协议

1.2 两线传输

1.3 主从设备

1.4 仲裁机制

1.4.1 触发条件

1.4.2 判断条件

1.4.3 仲裁原理

1.5 上拉电阻的作用

1.6 传输速率

2 I2C协议的基本操作

2.1 数据传输

2.1.1 读数据

2.1.2 写数据

2.2 起始/停止信号(含时序图)

2.3 数据的有效性(含时序图)

2.4 应答/非应答信号(含时序图)

3 软/硬件I2C

3.1 软件I2C

3.2 硬件I2C

3.3 I2C初始化

3.3.1 软件I2C初始化

3.3.2 硬件I2C初始化

3.3.2.1 模式选择

3.3.2.2 时钟速度

3.3.2.3 时钟占空比

3.3.2.4 应答使能

3.3.2.5 地址模式

3.3.2.6 自身地址

3.4 起始/停止信号

3.4.1 软件I2C

3.4.2 硬件I2C

3.5 发送一个字节

3.5.1 软件I2C

3.5.2 硬件I2C

3.6 接收一个字节

3.6.1 软件I2C

3.6.2 硬件I2C

3.7 发送应答位

3.7.1 软件I2C

3.7.2 硬件I2C

3.8 接收应答位

3.8.1 软件I2C

3.8.2 硬件I2C


1 I2C协议

1.1 I2C协议

一种用于连接微控制器和外围设备的两线串行总线协议,适用于短距离低速设备间通信,通信方式有同步、串行和半双工等。

1.2 两线传输

SCL:时钟线,用于同步数据传输。

SDA:数据线,用于传输数据。

1.3 主从设备

在总线上,可以有多个主设备和多个从设备,但在通信时只能有一个主设备控制总线(主设备的选择由仲裁机制决定),总线上每个设备都有一个唯一的地址(7位或10位)。

1.4 仲裁机制

1.4.1 触发条件

两个或多个主设备同时发起传输。

1.4.2 判断条件

主设备在发送高低电平时同时检查总线状态,当主设备输出高电平时检测到有其它设备在拉低电平,则触发机制。

1.4.3 仲裁原理

“线与”逻辑:

1. 任一设备输出低电平(拉低SDA),总线即为低电平。

2. 所有设备输出高电平(释放SDA),总线才为高电平。

示例:

主设备1发送10101010

主设备2发送10101011

前7位“1010101”两个设备发送数据相同;到第8位时主设备1输出低电平拉低SDA,主设备2输出高电平拉高SDA但检测到总线状态与自身冲突,则主设备2退出,主设备1继续传输

1.5 上拉电阻的作用

1. I²C设备的数据线SDA和时钟线SCL均为开漏输出;只能主动拉低,无法主动输出高电平,当所有设备释放总线(不拉低)时,可以通过上拉电阻将总线拉至高电平。

2. 防止上升沿时间过长导致时序错误。

1.6 传输速率

标准模式(最高100kHz)、快速模式(最高400kHz)和高速模式(最高3.4MHz需设备支持)。

2 I2C协议的基本操作

2.1 数据传输

数据以字节为单位传输,主机每写一个字节后都要等待从机的应答信号ACK或非应答信号NACK主机每读一个字节后都要向从机发送应答信号ACK或非应答信号NACK;只有在接收到应答信号后,才会继续读/写字节。

2.1.1 读数据

主机通过从机地址向指定从机发送读数据操作,指定从机向主机返回应答信号,主机收到应答信号后,从机主动控制SDA向主机返回8个位的数据;主机在第9个时钟周期向从机发送应答信号,从机继续控制SDA向主机返回8个位的数据,直到主机向从机发送非应答信号时从机便停止数据传输。

2.1.2 写数据

主机通过从机地址向指定从机发送写数据操作,指定从机向主机返回应答信号,主机收到应答信号后,主机控制SDA向从机传输8个位的数据;从机在第9个时钟周期向主机返回应答信号,主机继续控制SDA向从机传输8个位的数据,直到从机向主机返回非应答信号时主机便停止数据传输。

2.2 起始/停止信号(含时序图)

起始信号:SCL为高电平期间,SDA从高电平跳变至低电平

停止信号:SCL为高电平期间,SDA从低电平跳变至高电平

2.3 数据的有效性(含时序图)

SCL为高电平时,SDA数据有效(SDA为高电平时数据为1,低电平时数据为0);当SCL为低电平时,SDA跳变为下一次传输的数据

2.4 应答/非应答信号(含时序图)

以发送0100 1101为例,时序图如下所示:

3 软/硬件I2C

3.1 软件I2C

GPIO模拟时序,通过代码控制SCL和SDA电平变化来实现通信,可以任意配置引脚(具体需查看MCU引脚分配)。

优点:灵活性高、成本低,可用于非I2C标准设备。

缺点:占用CPU时间CPU持续工作、速度较低通常不高于100KHZ、时序精度低依赖软件延时、需要手动实现仲裁、功耗高。

3.2 硬件I2C

使用单片机内置的I2C外设、硬件自动生成时序、占用硬件资源。

优点:解放CPU、速度快、时序精度稳定、硬件处理仲裁、直接调用库函数简化开发、功耗低。

缺点:成本高、引脚固定。

3.3 I2C初始化

3.3.1 软件I2C初始化

void Model_I2C_Init(void){
    /*开启时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    /*GPIO初始化*/
    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);

    /*设置默认电平为高电平*/
    GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}

3.3.2 硬件I2C初始化

void Model_I2C_Init(void){
    /*开启时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

    /*GPIO初始化*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /*I2C初始化*/
    I2C_InitTypeDef I2C_InitStructure;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_ClockSpeed = 100000;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_Init(I2C2, &I2C_InitStructure);

    /*I2C使能*/
    I2C_Cmd(I2C2, ENABLE);
}
3.3.2.1 模式选择

I2C_Mode

I2C_Mode_I2C‌:标准I2C模式,适用于主/从设备通信。

I2C_Mode_SMBusDevice/I2C_Mode_SMBusHost‌:仅需在兼容SMBus协议时使用。


3.3.2.2 时钟速度

I2C_ClockSpeed

时钟速度可自定义,但需低于400kHz。


3.3.2.3 时钟占空比

‌I2C_DutyCycle

‌I2C_DutyCycle_2‌:低电平时间是高电平的2倍(2/1)。                       

I2C_DutyCycle_16_9‌:高速模式下可选,低电平时间是高电平的1.78倍(16/9)。


3.3.2.4 应答使能

‌I2C_Ack

‌I2C_Ack_Enable‌:主模式使能用于接收从设备ACK。

‌I2C_Ack_Disable‌:特殊场景(如广播地址)可能禁用。


3.3.2.5 地址模式

‌I2C_AcknowledgedAddress

‌I2C_AcknowledgedAddress_7bit‌:7位地址。

‌I2C_AcknowledgedAddress_10bit‌:10位地址。


3.3.2.6 自身地址

‌I2C_OwnAddress1

‌主模式‌:设为0x00(无效)。

‌从模式‌:需配置唯一地址

3.4 起始/停止信号

3.4.1 软件I2C

#define Model_I2C_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)(x))
#define Model_I2C_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(x))

/*起始信号*/
void Model_I2C_Start(void){
    Model_W_SDA(1); //SDA为高电平
    Model_I2C_W_SCL(1); //SCL为高电平
    Model_I2C_W_SDA(0); //在SCL高电平期间,拉低SDA
    Model_I2C_W_SCL(0); //起始后把SCL也拉低,占用总线
}

/*停止信号*/
void Model_I2C_Stop(void){
    Model_I2C_W_SDA(0); //拉低SDA为低电平
    Model_I2C_W_SCL(1); //拉高SCL为高电平
    Model_I2CW_SDA(1); //在SCL高电平期间,拉高SDA
}

3.4.2 硬件I2C

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

/*停止信号*/
I2C_GenerateSTOP(I2C1, ENABLE);

3.5 发送一个字节

3.5.1 软件I2C

void Model_I2C_SendByte(uint8_t Byte){

uint8_t i;

for (i = 0; i < 8; i ++){
    Model_I2C_W_SDA(Byte & (0x80 >> i));
    Model_I2C_W_SCL(1);
    Model_I2C_W_SCL(0);
    }
}

3.5.2 硬件I2C

I2C_SendData(I2C2, Byte);

3.6 接收一个字节

3.6.1 软件I2C

uint8_t Model_I2C_ReceiveByte(void){

    uint8_t i, Byte = 0x00;

    Model_I2C_W_SDA(1)
    for (i = 0; i < 8; i ++) {
        Model_I2C_W_SCL(1);
        if (Model_I2C_R_SDA()){
            Byte |= (0x80 >> i);
            }
        Model_I2C_W_SCL(0);
    }
    return Byte;
}

3.6.2 硬件I2C

I2C_ReceiveData(I2C2);

3.7 发送应答位

3.7.1 软件I2C

void Model_I2C_SendAck(uint8_t Ack){
    Model_I2C_W_SDA(Ack);
    Model_I2C_W_SCL(1);
    Model_I2C_W_SCL(0);
}

3.7.2 硬件I2C

I2C_AcknowledgeConfig(I2C2, ENABLE);// 应答:ENABLE  非应答:DISABLE

3.8 接收应答位

3.8.1 软件I2C

uint8_t Model_I2C_ReceiveAck(void){

    uint8_t Ack; 

    Model_I2C_W_SDA(1); 
    Model_I2C_W_SCL(1); 
    Ack = Model_I2C_R_SDA(); 
    Model_I2C_W_SCL(0); 

    return Ack; 
}

3.8.2 硬件I2C

I2C_CheckEvent(I2C2, uint32_t I2C_EVENT);//I2C_EVENT为EVx事件

注:本篇文章涉及位操作和结构体内容如不明白可阅读往期内容。

注:本篇文章主要讲解了什么是I2C和软/硬件I2C等理论及少部分实操,后续会继续发表关于I2C的具体应用。

注:以上内容仅个人理解,不具备唯一性和绝对正确性,仅供参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别卷了,累了就睡会吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值