打印
[STM32F1]

基于STM32F103的I2C通信应用与代码示例

[复制链接]
894|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Clyde011|  楼主 | 2024-10-11 08:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

在嵌入式系统开发中,I2C总线因其简单易用、节省引脚的特点,广泛应用于各种传感器和设备的通信。STM32F103作为ST公司的经典MCU系列,具备多个I2C接口,非常适合用于实现I2C通信。在本文中,我们将以STM32F103C8T6为例,展示如何通过STM32的I2C外设与EEPROM芯片进行数据读写。

应用场景在这篇文章中,我们将模拟一个简单的应用场景:通过STM32F103与一颗24C02 EEPROM进行通信。我们将实现以下功能:
  • 通过I2C接口写入数据到EEPROM。
  • 读取EEPROM中的数据并通过串口输出。
  • 实现基本的读写错误检测。

硬件设计硬件连接方面,STM32F103C8T6的I2C1接口使用PB6作为SCL,PB7作为SDA。24C02的SCL和SDA分别连接到STM32的对应引脚,另外需要在I2C总线上拉两个4.7kΩ电阻。

代码实现接下来展示STM32F103使用I2C通信的代码,包括初始化、读写EEPROM数据等。代码采用HAL库进行开发,简化了底层操作。
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "i2c.h"

#define EEPROM_ADDRESS 0xA0 // 24C02的器件地址

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void EEPROM_Write(uint8_t data, uint16_t memAddress);
static uint8_t EEPROM_Read(uint16_t memAddress);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_Init();
   
    // 向EEPROM写入数据
    EEPROM_Write(0x55, 0x0001);
    HAL_Delay(10);
   
    // 从EEPROM读取数据
    uint8_t readData = EEPROM_Read(0x0001);
   
    // 通过串口发送读取到的数据
    char msg[50];
    sprintf(msg, "Read data: 0x%02X\r\n", readData);
    HAL_UART_Transmit(&huart1, (uint8_t *)msg, strlen(msg), HAL_MAX_DELAY);
   
    while (1) {
    }
}

// 写数据到EEPROM
static void EEPROM_Write(uint8_t data, uint16_t memAddress) {
    uint8_t buffer[2];
    buffer[0] = (memAddress >> 8) & 0xFF; // 高地址
    buffer[1] = memAddress & 0xFF;        // 低地址
   
    HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, memAddress, I2C_MEMADD_SIZE_16BIT, &data, 1, HAL_MAX_DELAY);
}

// 从EEPROM读取数据
static uint8_t EEPROM_Read(uint16_t memAddress) {
    uint8_t data = 0;
    HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, memAddress, I2C_MEMADD_SIZE_16BIT, &data, 1, HAL_MAX_DELAY);
    return data;
}

// 系统时钟配置函数
void SystemClock_Config(void) {
    // 此处省略系统时钟配置代码
}

// GPIO初始化
static void MX_GPIO_Init(void) {
    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

代码解析
  • I2C初始化:我们使用STM32的HAL库提供的I2C初始化函数MX_I2C1_Init()来设置I2C接口为主机模式,频率设置为100kHz。
  • EEPROM写入操作:通过HAL_I2C_Mem_Write()函数将数据写入指定的EEPROM地址。该函数封装了I2C协议中的起始条件、地址传输、数据传输及停止条件。
  • EEPROM读取操作:使用HAL_I2C_Mem_Read()函数从指定的EEPROM地址读取数据。
  • 串口通信:通过HAL_UART_Transmit()函数将读取到的数据发送到上位机,方便调试与验证。

代码运行结果程序在运行后会将从EEPROM读取到的数据通过串口输出。我们通过串口调试助手可以看到类似以下输出内容:
Read data: 0x55
表示已经成功从EEPROM地址0x0001处读取到了之前写入的0x55。

总结本文展示了STM32F103 MCU与24C02 EEPROM的I2C通信应用。通过STM32的HAL库,I2C通信的实现变得更加简洁易用。实际应用中,这种方法可以广泛用于各种需要数据存储的场合,如配置参数保存、日志记录等。

使用特权

评论回复
沙发
公羊子丹| | 2024-10-11 08:18 | 只看该作者
这代码太清晰了,直接拿来用就行!

使用特权

评论回复
板凳
周半梅| | 2024-10-11 08:18 | 只看该作者
我也用STM32做过I2C,没想到这么简单。

使用特权

评论回复
地板
帛灿灿| | 2024-10-11 08:18 | 只看该作者
24C02和STM32搭配,太实用了,我正好需要。

使用特权

评论回复
5
童雨竹| | 2024-10-11 08:19 | 只看该作者
请问这个代码支持其他型号的EEPROM吗?

使用特权

评论回复
6
万图| | 2024-10-11 08:19 | 只看该作者
讲得很详细,尤其是I2C通信部分,正是我想要的。

使用特权

评论回复
7
Wordsworth| | 2024-10-11 08:19 | 只看该作者
串口输出数据挺方便的,我可以改成LCD显示吗?

使用特权

评论回复
8
Bblythe| | 2024-10-11 08:19 | 只看该作者
这篇文章解答了我对I2C读写不懂的地方,感谢!

使用特权

评论回复
9
Pulitzer| | 2024-10-11 08:20 | 只看该作者
我之前用裸机写I2C,改用HAL库省了不少功夫。

使用特权

评论回复
10
Uriah| | 2024-10-11 08:20 | 只看该作者
有没有办法让I2C传输速度再快一点?

使用特权

评论回复
11
Stahan| | 2024-10-13 23:19 | 只看该作者
Uriah 发表于 2024-10-11 08:20
有没有办法让I2C传输速度再快一点?

上拉电阻调小点应该会快速点

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

3444

帖子

0

粉丝