主題 | 內容 | 教學目的/擴展視頻 |
---|---|---|
I2C總線 | 電路原理,跳線設置,I2C協議分析。驅動程序與調用。 | 熟悉I2C總線協議,熟練調用。 |
師從洋桃電子,杜洋老師
📑文章目錄
- 引言
- 一、I2C驅動分層架構
- 二、I2C總線驅動代碼精析
- 2.1 初始化配置(i2c.c)
- 2.2 數據發送函數(I2C_SAND_BUFFER)
- 2.3 數據接收函數(I2C_READ_BUFFER)
- 三、總線速度配置原理
- 四、用戶應用實戰(main.c)
- 五、器件驅動開發(LM75A示例)
- 5.1 溫度讀取函數
- 六、常見問題排查指南
- 七、進階優化技巧
- 八、相關資源
- 總結
▲ 回顧上期🔍STM32入門之I2C總線應用詳解(附LM75A溫度傳感器實戰) | 零基礎入門STM32第四十九步
引言
I2C總線是嵌入式系統中廣泛使用的通信協議,具有接線簡單、多設備共享總線等優點。本文將深入解析STM32的I2C驅動開發,通過分層架構設計、代碼逐行分析和實戰案例演示,幫助開發者快速掌握I2C通信的核心技術。
一、I2C驅動分層架構
- 硬件抽象層(HAL)
ST官方提供的固件庫(如stm32f10x_i2c.c
),直接操作寄存器實現基礎功能。 - 總線驅動層
封裝I2C協議的核心操作(發送/接收數據),提供I2C_Configuration()
等接口。 - 器件驅動層
針對具體外設(如LM75A溫度傳感器)的驅動實現。 - 用戶應用層
調用驅動函數實現業務邏輯,如溫度顯示。
二、I2C總線驅動代碼精析
2.1 初始化配置(i2c.c)
void I2C_Configuration(void) {// GPIO配置:SCL=PB6, SDA=PB7GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; // 復用開漏模式GPIO_Init(GPIOB, &GPIO_InitStruct);// I2C參數配置I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz標準模式I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 時鐘占空比I2C_Init(I2C1, &I2C_InitStruct);I2C_Cmd(I2C1, ENABLE); // 使能I2C
}
- 關鍵點:
- GPIO必須配置為復用開漏模式(支持總線仲裁)
- 時鐘速度需匹配從機設備(如LM75A支持400kHz)
2.2 數據發送函數(I2C_SAND_BUFFER)
void I2C_SAND_BUFFER(u8 SlaveAddr, u8 WriteAddr, u8* pBuffer, u16 NumByteToWrite) {I2C_GenerateSTART(I2C1, ENABLE); // 發送起始信號while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // 等待EV5I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Transmitter); // 發送設備地址while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 等待EV6I2C_SendData(I2C1, WriteAddr); // 發送寄存器地址while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 等待EV8while(NumByteToWrite--) { // 循環發送數據I2C_SendData(I2C1, *pBuffer++);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));}I2C_GenerateSTOP(I2C1, ENABLE); // 發送停止信號
}
- 協議流程:
- 起始信號 → 2. 發送地址+寫方向 → 3. 發送寄存器地址 → 4. 發送數據 → 5. 停止信號
2.3 數據接收函數(I2C_READ_BUFFER)
三、總線速度配置原理
在i2c.h
中定義總線速率:
#define BusSpeed 200000 // 200kHz
- 計算公式:
SCL頻率 = APB1時鐘頻率 2 × ( I2C_ClockSpeed + 1 ) \text{SCL頻率} = \frac{\text{APB1時鐘頻率}}{2 \times (\text{I2C\_ClockSpeed} + 1)} SCL頻率=2×(I2C_ClockSpeed+1)APB1時鐘頻率?
- 注意事項:
- APB1時鐘需在初始化時正確配置(默認為36MHz)
- 實際速率可通過示波器測量SCL引腳驗證
四、用戶應用實戰(main.c)
int main(void) {u8 tempData[3];I2C_Configuration(); // 初始化I2CTM1640_Init(); // 初始化顯示模塊while(1) {LM75A_GetTemp(tempData); // 讀取溫度// 顯示溫度值(示例代碼略)delay_ms(200); // 控制采樣頻率}
}
- 調用鏈:
main()
→LM75A_GetTemp()
→I2C_READ_BUFFER()
→ 硬件寄存器操作
五、器件驅動開發(LM75A示例)
5.1 溫度讀取函數
void LM75A_GetTemp(u8 *Tempbuffer) {u8 rawData[2];I2C_READ_BUFFER(LM75A_ADD, 0x00, rawData, 2); // 讀取原始數據// 數據解析(示例)int16_t temp = (rawData[0] << 8) | rawData[1];temp = temp >> 5; // 有效數據為11位*Tempbuffer = temp * 0.125; // 轉換為實際溫度值
}
- 關鍵參數:
LM75A_ADD = 0x9E
(包含R/W位)- 溫度數據為16位(高11位有效)
六、常見問題排查指南
現象 | 可能原因 | 解決方案 |
---|---|---|
總線無響應 | 1. 硬件連接錯誤 | 檢查SCL/SDA上拉電阻(4.7kΩ) |
數據校驗失敗 | 2. 時序不匹配 | 降低時鐘速度或調整延時 |
重復地址沖突 | 3. 從機地址配置錯誤 | 使用I2C掃描工具檢測設備地址 |
七、進階優化技巧
- DMA傳輸
使用DMA減少CPU占用:I2C_DMACmd(I2C1, I2C_DMAReq_Tx | I2C_DMAReq_Rx, ENABLE);
- 錯誤恢復機制
檢測總線忙狀態時自動復位:if(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) {I2C_SoftwareResetCmd(I2C1, ENABLE);I2C_SoftwareResetCmd(I2C1, DISABLE); }
八、相關資源
[1] 洋桃電子B站課程-STM32入門100步
[2] STM32F103xx官方數據手冊
[3] STM32F103X8-B數據手冊(中文)
[4] STM32F103固件函數庫用戶手冊(中文)
[5] I2C總線規范(中文)
[6] LM75(溫度傳感器)數據手冊+編程說明+應用
[7] 溫度傳感器數碼管顯示程序
[8] I2C驅動程序分析.pptx
總結
本文從STM32的I2C驅動架構出發,詳細解析了總線初始化、數據收發和速度配置的實現原理,并結合LM75A溫度傳感器展示了實際應用場景。掌握以下核心要點:
- 分層架構設計提升代碼可維護性
- 嚴格遵循I2C協議時序
- 合理配置總線速率匹配外設
- 善用調試工具(如邏輯分析儀)驗證通信波形
通過理論結合實踐的方式,開發者能夠快速構建穩定可靠的I2C通信系統。
💬 技術討論(請在評論區留言~)
📌 下期預告:下一期將探討LM75A驅動程序分析,歡迎持續關注!
點擊查閱🔍往期【STM32專欄】文章
版權聲明:本文采用[CC BY-NC-SA 4.0]協議,轉載請注明來源
實測開發版:洋桃1號開發版(基于STM32F103C8T6)
更新日志:
- v1.0 初始版本(2025-03-07)