STM32 教學系列 第 8 節:I2C 通訊 + DMA
🎯 學習目標
- 理解 I2C 協定 - 掌握時序與尋址方式
- I2C 從設備通訊 - 實現感測器讀寫
- I2C + DMA - 高效率資料轉移
🎓 I2C 基礎
I2C 特性
- 序列通訊協定:採用時鐘線 (SCL) 和資料線 (SDA)
- 開路集電極輸出:需上拉電阻
- 多主多從:支援多設備連接
- 速度:標準 100 kHz、快速 400 kHz
I2C 信號線
| 訊號 | GPIO | 功能 |
|---|---|---|
| SCL | PB6 | 時鐘線(串列時脈) |
| SDA | PB7 | 資料線(序列資料) |
I2C 尋址
I2C 使用 7 位或 10 位地址識別設備。常見感測器地址示例:
- MPU6050:0x68(加速度計+陀螺儀)
- BMP280:0x77(氣壓計)
- EEPROM:0x50~0x57
🛠️ 硬體連接
| 組件 | 接腳 | 連接 |
|---|---|---|
| SCL | PB6 | I2C1_SCL(4.7kΩ 上拉至 3.3V) |
| SDA | PB7 | I2C1_SDA(4.7kΩ 上拉至 3.3V) |
| VCC | 3.3V | 電源 |
| GND | GND | 地線 |
⚙️ CubeMX 配置
步驟 1:啟用 I2C1
- Connectivity → I2C1
- 模式設為 I2C
步驟 2:配置 I2C 參數
- Speed Mode:Fast (400 kHz)
- Addressing Mode:7-bit
步驟 3:啟用中斷
NVIC Settings 中勾選 I2C1 event interrupt 和 I2C1 error interrupt
💻 完整程式碼
/* STM32 Lesson 08 - I2C Communication */
#include "main.h"
#include "i2c.h"
#include "usart.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
/* I2C 寫入函數 */
HAL_StatusTypeDef I2C_Write(uint8_t addr, uint8_t reg, uint8_t data)
{
uint8_t buffer[2] = {reg, data};
return HAL_I2C_Master_Transmit(&hi2c1, addr << 1, buffer, 2, 1000);
}
/* I2C 讀取函數 */
HAL_StatusTypeDef I2C_Read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t size)
{
HAL_I2C_Master_Transmit(&hi2c1, addr << 1, ®, 1, 1000);
return HAL_I2C_Master_Receive(&hi2c1, addr << 1, data, size, 1000);
}
void UART_Print(const char *format, ...);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_I2C1_Init();
MX_USART1_UART_Init();
UART_Print("\r\n=== I2C Test ===\r\n");
/* 掃描 I2C 上的設備 */
for (uint8_t addr = 0x08; addr < 0x78; addr++)
{
if (HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 1, 100) == HAL_OK)
{
UART_Print("Device found at 0x%X\r\n", addr);
}
}
while (1)
{
/* I2C 讀寫操作 */
}
}
✨ I2C 通訊完成!🚀