单片机的I2C总线通信实例

前端开发者说 2022-07-07 ⋅ 17 阅读

引言

I2C(Inter-Integrated Circuit)是一种串行通信协议,常用于在多个电子设备之间进行通信。在单片机中,I2C通信常用于连接传感器、存储器、显示屏等外部设备。本文将介绍单片机中使用I2C总线进行通信的实例。

I2C通信原理

I2C总线由两根线组成:SCL(时钟线)和SDA(数据线)。SCL由主设备产生和控制,用于同步数据传输。SDA用于双向传输数据。每个设备在总线上都有唯一的地址,可以让主设备通过地址选择要与之通信的设备。

I2C库函数的使用

许多单片机厂商都提供了用于配置和控制I2C总线通信的库函数。以STMicroelectronics的STM32微控制器为例,使用其标准固件库(StdPeriph Library)中的I2C库函数可以轻松实现I2C通信。

步骤1:初始化I2C总线

首先需要初始化I2C总线,设置通信速率、配置GPIO引脚等。

#include "stm32f10x.h"
#include "stm32f10x_i2c.h"

void I2C_Configuration()
{
    I2C_InitTypeDef I2C_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);  // 使能I2C1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟

    // 配置I2C GPIO引脚
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 配置I2C通信参数
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;
    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStruct.I2C_ClockSpeed = 100000;
    I2C_Init(I2C1, &I2C_InitStruct);

    I2C_Cmd(I2C1, ENABLE); // 使能I2C1
}

步骤2:发送数据

使用库函数I2C_SendData()发送数据。以下是一个简单的发送数据的示例:

void I2C_SendData(uint8_t data)
{
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    I2C_SendData(I2C1, data);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTOP(I2C1, ENABLE);
}

步骤3:接收数据

使用库函数I2C_ReceiveData()接收数据。以下是一个简单的接收数据的示例:

uint8_t I2C_ReceiveData()
{
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

    uint8_t data = I2C_ReceiveData(I2C1);

    I2C_GenerateSTOP(I2C1, ENABLE);

    return data;
}

I2C通信实例:读取温度传感器数据

现在我们使用I2C总线通信的例子,读取连接在单片机上的温度传感器(例如LM75)的数据。

首先,需要查看传感器的数据手册,找到其I2C地址。假设传感器的地址是0x90。

然后,编写代码读取温度传感器的数据:

#include "stdio.h"

uint8_t slave_address = 0x90; // 温度传感器的地址

float read_temperature()
{
    // 向温度传感器发送读取数据的命令
    I2C_SendData(0x00); // 发送命令寄存器地址

    // 接收温度传感器的数据
    uint8_t high_byte, low_byte;
    high_byte = I2C_ReceiveData();
    low_byte = I2C_ReceiveData();

    // 计算温度值
    int16_t temperature_raw = (high_byte << 8) | low_byte;
    float temperature = temperature_raw / 256.0;

    return temperature;
}

int main()
{
    I2C_Configuration();

    float temperature = read_temperature();
    printf("当前温度:%.2f℃\n", temperature);

    return 0;
}

结论

本文介绍了单片机中使用I2C总线通信的实例。通过配置和控制I2C总线,我们可以轻松实现与各种外部设备的通信,如传感器、存储器等。希望本文对初学者理解和应用I2C通信有所帮助。


全部评论: 0

    我有话说: