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

[复制链接]
4222|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库进行开发,简化了底层操作。
  1. #include "stm32f1xx_hal.h"
  2. #include "usart.h"
  3. #include "i2c.h"

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

  5. void SystemClock_Config(void);
  6. static void MX_GPIO_Init(void);
  7. static void EEPROM_Write(uint8_t data, uint16_t memAddress);
  8. static uint8_t EEPROM_Read(uint16_t memAddress);

  9. int main(void) {
  10.     HAL_Init();
  11.     SystemClock_Config();
  12.     MX_GPIO_Init();
  13.     MX_USART1_UART_Init();
  14.     MX_I2C1_Init();
  15.    
  16.     // 向EEPROM写入数据
  17.     EEPROM_Write(0x55, 0x0001);
  18.     HAL_Delay(10);
  19.    
  20.     // 从EEPROM读取数据
  21.     uint8_t readData = EEPROM_Read(0x0001);
  22.    
  23.     // 通过串口发送读取到的数据
  24.     char msg[50];
  25.     sprintf(msg, "Read data: 0x%02X\r\n", readData);
  26.     HAL_UART_Transmit(&huart1, (uint8_t *)msg, strlen(msg), HAL_MAX_DELAY);
  27.    
  28.     while (1) {
  29.     }
  30. }

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

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

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

  49. // GPIO初始化
  50. static void MX_GPIO_Init(void) {
  51.     __HAL_RCC_GPIOB_CLK_ENABLE();
  52.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  53.     GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
  54.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  55.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  56.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  57. }

代码解析
  • 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读取到的数据通过串口输出。我们通过串口调试助手可以看到类似以下输出内容:
  1. 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搭配,太实用了,我正好需要。
童雨竹 发表于 2024-10-11 08:19 | 显示全部楼层
请问这个代码支持其他型号的EEPROM吗?
万图 发表于 2024-10-11 08:19 | 显示全部楼层
讲得很详细,尤其是I2C通信部分,正是我想要的。
Wordsworth 发表于 2024-10-11 08:19 | 显示全部楼层
串口输出数据挺方便的,我可以改成LCD显示吗?
Bblythe 发表于 2024-10-11 08:19 | 显示全部楼层
这篇文章解答了我对I2C读写不懂的地方,感谢!
Pulitzer 发表于 2024-10-11 08:20 | 显示全部楼层
我之前用裸机写I2C,改用HAL库省了不少功夫。
Uriah 发表于 2024-10-11 08:20 | 显示全部楼层
有没有办法让I2C传输速度再快一点?
Stahan 发表于 2024-10-13 23:19 | 显示全部楼层
Uriah 发表于 2024-10-11 08:20
有没有办法让I2C传输速度再快一点?

上拉电阻调小点应该会快速点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

163

主题

5960

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部