STM32入门教程:I2C通信

I2C (Inter-Integrated Circuit) 是一种串行通信协议,常用于连接微控制器和外部设备。在本教程中,我们将介绍如何在STM32微控制器上使用I2C协议进行通信。

在开始之前,我们需要确保我们的开发环境已经设置好了。我们需要安装STM32CubeMX和Keil MDK开发工具,并配置好STM32微控制器的项目。

在本教程中,我们将使用STM32F407微控制器作为示例来演示I2C通信。首先,让我们开始配置I2C控制器。

  1. 打开STM32CubeMX并创建一个新的项目。
  2. 选择我们的微控制器型号 "STM32F407VG"。
  3. 在 "Pinout & Configuration" 标签页中,选择合适的引脚来连接I2C总线上的SDA和SCL线。这些引脚的选择取决于你的硬件连接。在本教程中,我们将使用PB6引脚作为SDA线,PB7引脚作为SCL线。
  4. 在 "Configuration" 标签页中,找到 "I2C1" 配置项,并启用它。
  5. 在 "Mode" 选项中选择 "I2C"。
  6. 配置 "I2C Speed" 为适当的速度。常见的速度有100kHz、400kHz等。在本教程中,我们将选择100kHz。
  7. 配置合适的 "I2C Own Address",这是我们的微控制器的地址。
  8. 确认配置并生成代码。

一旦代码生成完毕,我们就可以开始编写我们的I2C通信代码。

在Keil MDK中打开生成的项目,我们将需要在主函数中添加以下代码来初始化和使用I2C控制器。

首先,我们需要包含相关的头文件。

#include "stm32f4xx.h"

接下来,我们将定义一些宏来配置I2C控制器。

#define I2C_SPEED 100000 // I2C通信速度为100kHz
#define I2C_OWN_ADDRESS 0x50 // I2C通信的从机地址

然后,我们将定义一个函数来初始化I2C控制器。

void I2C_Init(void)
{
    // 使能I2C1时钟和复位I2C1控制器
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST;
    RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;

    // 配置GPIOB引脚用作I2C1总线
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
    GPIOB->MODER &= ~(GPIO_MODER_MODE6 | GPIO_MODER_MODE7);
    GPIOB->MODER |= (GPIO_MODER_MODE6_1 | GPIO_MODER_MODE7_1);
    GPIOB->OTYPER |= (GPIO_OTYPER_OT6 | GPIO_OTYPER_OT7);
    GPIOB->OSPEEDR |= (GPIO_OSPEEDR_OSPEED6 | GPIO_OSPEEDR_OSPEED7);
    GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD6 | GPIO_PUPDR_PUPD7);
    GPIOB->PUPDR |= (GPIO_PUPDR_PUPD6_0 | GPIO_PUPDR_PUPD7_0);
    GPIOB->AFR[0] |= (4 << GPIO_AFRL_AFRL6_Pos) | (4 << GPIO_AFRL_AFRL7_Pos);

    // 配置I2C1控制器
    I2C1->CR1 = 0;
    I2C1->CR2 = (42 << I2C_CR2_FREQ_Pos);
    I2C1->CCR = (I2C_SPEED <= 100000) ? 0x50 : (I2C_SPEED <= 400000) ? 0x14 : 0x0D;
    I2C1->TRISE = (I2C_SPEED <= 100000) ? 0x13 : (I2C_SPEED <= 400000) ? 0x02 : 0x00;
    I2C1->OAR1 = (I2C_OWN_ADDRESS << I2C_OAR1_ADD1_Pos) | I2C_OAR1_OA1EN;
    I2C1->CR1 |= I2C_CR1_PE;
}

接下来,我们将定义一些函数来发送和接收I2C数据。

void I2C_WriteData(uint8_t address, uint8_t *data, uint8_t length)
{
    // 等待I2C总线空闲
    while ((I2C1->SR2 & I2C_SR2_BUSY) != 0);

    // 发送START信号
    I2C1->CR1 |= I2C_CR1_START;
    while ((I2C1->SR1 & I2C_SR1_SB) == 0);

    // 发送从机地址和写操作
    I2C1->DR = (address << 1) & ~I2C_OAR1_ADD1;
    while ((I2C1->SR1 & I2C_SR1_ADDR) == 0);
    (void)I2C1->SR2;

    // 发送数据
    for (uint8_t i = 0; i < length; i++)
    {
        I2C1->DR = data[i];
        while ((I2C1->SR1 & I2C_SR1_TXE) == 0);
    }

    // 发送STOP信号
    I2C1->CR1 |= I2C_CR1_STOP;
}

void I2C_ReadData(uint8_t address, uint8_t *data, uint8_t length)
{
    // 等待I2C总线空闲
    while ((I2C1->SR2 & I2C_SR2_BUSY) != 0);

    // 发送START信号
    I2C1->CR1 |= I2C_CR1_START;
    while ((I2C1->SR1 & I2C_SR1_SB) == 0);

    // 发送从机地址和读操作
    I2C1->DR = (address << 1) | I2C_OAR1_ADD1;
    while ((I2C1->SR1 & I2C_SR1_ADDR) == 0);
    (void)I2C1->SR2;

    // 读取数据
    for (uint8_t i = 0; i < length; i++)
    {
        while ((I2C1->SR1 & I2C_SR1_RXNE) == 0);
        data[i] = I2C1->DR;
    }

    // 发送STOP信号
    I2C1->CR1 |= I2C_CR1_STOP;
}

现在我们可以在主函数中使用上述的I2C函数来进行数据收发。

int main(void)
{
    // 初始化I2C控制器
    I2C_Init();

    // 发送数据示例
    uint8_t dataToSend[] = {0xA5, 0x5A, 0xAA};
    I2C_WriteData(0x55, dataToSend, sizeof(dataToSend));

    // 接收数据示例
    uint8_t dataToReceive[3];
    I2C_ReadData(0x55, dataToReceive, sizeof(dataToReceive));

    while (1)
    {
        // 主循环
    }
}

这样,我们就完成了STM32微控制器上使用I2C协议进行通信的入门教程。希望对你有所帮助!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值