本應(yīng)用筆記討論了通過I2C兼容接口讀取多字節(jié)數(shù)據(jù)時需要特別注意的地方。介紹了每次讀取一個字節(jié)時容易出現(xiàn)的問題,并給出了幾個具體示例。本文也描述了進行數(shù)據(jù)傳輸?shù)恼_方法。

概述

I2C兼容2線接口是功能強大的總線機制,用于連接微控制器微處理器與低速外設(shè),例如:集成了模/數(shù)轉(zhuǎn)換器(ADC)的外設(shè)。基于該總線的最基本的通信方式(即,寫入/讀取從機寄存器的一個字節(jié))非常直觀。但是,如果因為這種方法簡單而掉以輕心,則會導(dǎo)致嚴重的系統(tǒng)錯誤。

?

單字節(jié)通道傳送2字節(jié)數(shù)據(jù)

任何連接外設(shè)(尤其是傳感器)的數(shù)字接口,都需要確保從器件的內(nèi)部寄存器正確讀取數(shù)據(jù),尤其是在讀取寄存器的過程中數(shù)據(jù)發(fā)生變化的情況下。數(shù)據(jù)傳輸過程中,如果ADC執(zhí)行轉(zhuǎn)換操作并更新寄存器的內(nèi)容,數(shù)據(jù)則會發(fā)生改變。許多器件帶有內(nèi)部緩存器(通常不能從外部訪問),用來存放最新轉(zhuǎn)換結(jié)果。當I2C總線處于空閑狀態(tài)時,更新所謂的“用戶可訪問”寄存器內(nèi)容。

I2C協(xié)議每次只傳送1個字節(jié)的數(shù)據(jù)。因此,如果有效數(shù)據(jù)字長超過8位,并且沒有合理處置傳輸操作,則會引發(fā)問題。比如,MAX44000環(huán)境光傳感器(ALS)的數(shù)據(jù)寄存器具有多達14位的數(shù)據(jù)(另有1位作為溢出標志,表示需要增加計數(shù)/亮度設(shè)置)。

表1. MAX44000 ALS數(shù)據(jù)寄存器

REGISTER B7 B6 B5 B4 B3 B2 B1 B0 REGISTER ADDRESS
ADC High Byte (ALS) ? OFL
ALSDATA[13:8]
0x04
ADC Low Byte (ALS)
ALSDATA[7:0]
0x05

我們不能通過I2C直接讀取所有數(shù)據(jù)ALSDATA[13:0],需要首先讀取寄存器0x04的內(nèi)容,然后讀取寄存器0x05的內(nèi)容,再把這些數(shù)據(jù)合并到一個至少16位的寄存器內(nèi)。因此,在讀取這些數(shù)據(jù)時需要特別謹慎。通過兩次簡單的單字節(jié)讀操作(利用STOP (P)條件終止)完成數(shù)據(jù)讀取,如圖1所示。

圖1. 單字節(jié)讀操作
圖1. 單字節(jié)讀操作

這種方法存在致命缺陷,確切地說,向器件發(fā)送STOP條件,返回“用戶可見”的寄存器內(nèi)容。由此,從寄存器0x04讀取數(shù)據(jù)后,實際的14位數(shù)據(jù)可能在讀取0x05寄存器之前已經(jīng)更新。幾種情形下,這種缺陷可能導(dǎo)致嚴重錯誤。

例如,當MAX44000環(huán)境光傳感器處于10位、12位或14位模式時,亮度處于相對穩(wěn)定狀態(tài),假設(shè)亮度在小范圍波動,或許亮度正在緩慢上升,或周圍存在少量噪聲,使得0x04和0x05寄存器的14位數(shù)據(jù)計數(shù)值為255或256,考慮表2中的三種情形。

表2. 誤差圖示說明

State of Registers During
First Byte Read (Read 0x04 Only)
State of Registers During
Second Byte Read (Read 0x05 Only)
Result (14 Bit)
Illustration of the Glitch Illustration of the Glitch Illustration of the Glitch
Illustration of the Glitch Illustration of the Glitch Illustration of the Glitch
Illustration of the Glitch Illustration of the Glitch Illustration of the Glitch

在后兩種情形下,我們可能讀到0或511,而不是讀255或256,這是一個很嚴重的錯誤。發(fā)生這已錯誤的原因在于,第一次和第二次讀操作之間,發(fā)出STOP狀態(tài)后,寄存器0x04和0x05中的數(shù)據(jù)被更新。第一種出現(xiàn)問題情形下,第一個字節(jié)可以正確讀出,但在讀第二個字節(jié)時,總數(shù)為256的數(shù)據(jù)對應(yīng)的最低位為零,因而,我們從器件中得到讀數(shù)0;第二種出現(xiàn)問題的情形下,數(shù)據(jù)總計數(shù)值為256,由于在STOP狀態(tài)發(fā)出后,第二個字節(jié)的數(shù)據(jù)在讀取之前減少了1,所以顯示為511,圖2給出了多次讀取數(shù)據(jù)時,這種故障的抽樣情況。

圖2. 多次采樣時,實際讀取單字節(jié)的數(shù)值
圖2. 多次采樣時,實際讀取單字節(jié)的數(shù)值

這個問題很容易通過一次讀取2字節(jié)數(shù)據(jù)來避免,如圖3所示。具體操作是,讀取第一個數(shù)據(jù)字節(jié)后,發(fā)送REPEATED START (而不是STOP)進行操作,操作非常簡單。通過讀取2個字節(jié),盡管在兩個器件之間發(fā)送完全相同的位數(shù),卻可避免器件不恰當?shù)馗翴2C寄存器的內(nèi)容。

圖3. 2字節(jié)讀操作示意圖
圖3. 2字節(jié)讀操作示意圖

上述示例適用于MAX44000和MAX44009,進行多次讀操作時不會自動遞增寄存器指針。器件功能各有差異,但工作原理相同。也可以將其很容易地擴展到N字節(jié)讀取操作。應(yīng)用筆記AN3588:“MAXQ2000微控制器軟件I2C驅(qū)動”一文給出了幾個C程序示例。

非常好我支持^.^

(11) 73.3%

不好我反對

(4) 26.7%