软件IIC和硬件IIC的区别————附stm32软件IIC代码

目录

1.IIC总线概述

        a.基本原理

                总线结构

                设备类型

        b.通信协议

2.软件IIC和硬件1IC的区别:

        2.1.实现方式

       2.2. 性能

        2.3. 可靠性

3. 硬件IIC和软件IIC代码示例

        3.1 硬件IIC

1.首先打开外部高速晶振

2.IIC设置 

3. 时钟源设置

        3.2 软件IIC


1.IIC总线概述

        a.基本原理

                总线结构

                IIC总线使用两条线进行通信

  •         SCL(Serial Clock Line,串行时钟线):用于同步数据传输
  •         SDA(Serial Data Line,串行数据线):用于传输数据。
                设备类型

        IIC总线上可以连接多个设备,这些设备分为两种类型:

  • 主设备(Master):控制总线,发起通信,生成时钟信号。
  • 从设备(Slave):响应主设备的请求,根据主设备的指令进行数据的发送和接收

        b.通信协议

  • 起始条件:主设备拉低SDA线,然后拉低SCL线,表示通信开始。
  • 停止条件:主设备拉低SCL线,然后拉高SDA线,表示通信结束。

  • 数据传输:数据在SCL线的上升沿被采样,下降沿被释放。每个数据位传输后,从设备会发送一个应答位(ACK)。

  • 应答位:在每个字节传输后,从设备会发送一个应答位。如果从设备准备好接收下一个字节,它会拉低SDA线;否则,SDA线保持高电平,表示不响应(NACK)。

2.软件IIC和硬件1IC的区别:

        2.1.实现方式

              软件IIC:通过控制GPIO来模拟IIC的SCL和SDA信号来产生IIC的时序

              硬件IIC:MCU内部专用硬件模块(IIC外设)来时许的,软件只负责发出命令

       2.2. 性能

                软件IIC:速度通常比较慢,速度受限于CPU

                硬件IIC:速度就比较快,在高频率下工作,不受CPU的限制

        2.3. 可靠性

                硬件IIC可靠性较高

                软件IIC取决于CPU的运行速度,取决于程序员的代码设计

3. 硬件IIC和软件IIC代码示例

        3.1 硬件IIC

硬件IIC我们可以使用STM32Cubemx生成代码,以下是使用STM32Cubemx步骤:

1.首先打开外部高速晶振

2.IIC设置 

图中第3步保持默认即可 

3. 时钟源设置

 至此STM32Cubemx关于IIC的基础配置已经完成,点击右上角GENERATE CODE即可以生成代码,需要其余操作可以自行编写代码。

        3.2 软件IIC

我们根据IIC的通信时序图即可以模拟出IIC。

.h文件

#ifndef IIC_H
#define IIC_H

#include "stm32f10x.h"

// IIC配置结构体
typedef struct {
    uint32_t I2C_ClockSpeed;  // IIC时钟速度
    uint16_t I2C_Mode;        // IIC模式(I2C_Mode_I2C)
    uint16_t I2C_DutyCycle;   // IIC占空比(I2C_DutyCycle_2)
    uint16_t I2C_OwnAddress1; // IIC自身地址(不常用)
    uint16_t I2C_Ack;         // IIC应答使能(I2C_Ack_Enable 或 I2C_Ack_Disable)
    uint16_t I2C_AcknowledgedAddress; // IIC地址位数(I2C_AcknowledgedAddress_7bit 或 I2C_AcknowledgedAddress_10bit)
} I2C_ConfigTypeDef;

// IIC初始化
void I2C_Init(I2C_TypeDef* I2Cx, I2C_ConfigTypeDef* I2C_Config);

// IIC启动条件
void I2C_Start(I2C_TypeDef* I2Cx);

// IIC停止条件
void I2C_Stop(I2C_TypeDef* I2Cx);

// IIC发送地址
void I2C_SendAddr(I2C_TypeDef* I2Cx, uint8_t Addr, uint8_t Dir);

// IIC发送字节
void I2C_WriteByte(I2C_TypeDef* I2Cx, uint8_t Data);

// IIC读取字节
uint8_t I2C_ReadByte(I2C_TypeDef* I2Cx, uint8_t Ack);

// IIC等待忙状态
void I2C_WaitForEvent(I2C_TypeDef* I2Cx, uint32_t Event, uint32_t Timeout);

#endif // IIC_H

.c文件

#include "iic.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"

// IIC初始化
void I2C_Init(I2C_TypeDef* I2Cx, I2C_ConfigTypeDef* I2C_Config) {
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;

    // 使能I2C和GPIO时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 配置I2C引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PB6 (SCL), PB7 (SDA)
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 配置I2C
    I2C_InitStructure.I2C_ClockSpeed = I2C_Config->I2C_ClockSpeed;
    I2C_InitStructure.I2C_Mode = I2C_Config->I2C_Mode;
    I2C_InitStructure.I2C_DutyCycle = I2C_Config->I2C_DutyCycle;
    I2C_InitStructure.I2C_OwnAddress1 = I2C_Config->I2C_OwnAddress1;
    I2C_InitStructure.I2C_Ack = I2C_Config->I2C_Ack;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_Config->I2C_AcknowledgedAddress;
    I2C_Init(I2Cx, &I2C_InitStructure);

    // 使能I2C
    I2C_Cmd(I2Cx, ENABLE);
}

// IIC启动条件
void I2C_Start(I2C_TypeDef* I2Cx) {
    I2C_GenerateSTART(I2Cx, ENABLE);
    I2C_WaitForEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT, 10000);
}

// IIC停止条件
void I2C_Stop(I2C_TypeDef* I2Cx) {
    I2C_GenerateSTOP(I2Cx, ENABLE);
}

// IIC发送地址
void I2C_SendAddr(I2C_TypeDef* I2Cx, uint8_t Addr, uint8_t Dir) {
    uint8_t I2C_Address = (Addr << 1) | Dir;
    I2C_Send7bitAddress(I2Cx, I2C_Address, I2C_Direction_Transmitter);
    I2C_WaitForEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED, 10000);
}

// IIC发送字节
void I2C_WriteByte(I2C_TypeDef* I2Cx, uint8_t Data) {
    I2C_SendData(I2Cx, Data);
    I2C_WaitForEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED, 10000);
}

// IIC读取字节
uint8_t I2C_ReadByte(I2C_TypeDef* I2Cx, uint8_t Ack) {
    if (Ack == I2C_Ack_Enable) {
        I2C_AcknowledgeConfig(I2Cx, ENABLE);
    } else {
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
    }
    I2C_WaitForEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED, 10000);
    return I2C_ReceiveData(I2Cx);
}

// IIC等待忙状态
void I2C_WaitForEvent(I2C_TypeDef* I2Cx, uint32_t Event, uint32_t Timeout) {
    uint32_t tickstart = HAL_GetTick();

    while (!I2C_CheckEvent(I2Cx, Event)) {
        if ((HAL_GetTick() - tickstart) > Timeout) {
            // 超时处理
            return;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值