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

概述

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

?

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

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

I2C協(xié)議每次只傳送1個(gè)字節(jié)的數(shù)據(jù)。因此,如果有效數(shù)據(jù)字長(zhǎng)超過8位,并且沒有合理處置傳輸操作,則會(huì)引發(fā)問題。比如,MAX44000環(huán)境光傳感器(ALS)的數(shù)據(jù)寄存器具有多達(dá)14位的數(shù)據(jù)(另有1位作為溢出標(biāo)志,表示需要增加計(jì)數(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ù)合并到一個(gè)至少16位的寄存器內(nèi)。因此,在讀取這些數(shù)據(jù)時(shí)需要特別謹(jǐn)慎。通過兩次簡(jiǎn)單的單字節(jié)讀操作(利用STOP (P)條件終止)完成數(shù)據(jù)讀取,如圖1所示。

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

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

例如,當(dāng)MAX44000環(huán)境光傳感器處于10位、12位或14位模式時(shí),亮度處于相對(duì)穩(wěn)定狀態(tài),假設(shè)亮度在小范圍波動(dòng),或許亮度正在緩慢上升,或周圍存在少量噪聲,使得0x04和0x05寄存器的14位數(shù)據(jù)計(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,這是一個(gè)很嚴(yán)重的錯(cuò)誤。發(fā)生這已錯(cuò)誤的原因在于,第一次和第二次讀操作之間,發(fā)出STOP狀態(tài)后,寄存器0x04和0x05中的數(shù)據(jù)被更新。第一種出現(xiàn)問題情形下,第一個(gè)字節(jié)可以正確讀出,但在讀第二個(gè)字節(jié)時(shí),總數(shù)為256的數(shù)據(jù)對(duì)應(yīng)的最低位為零,因而,我們從器件中得到讀數(shù)0;第二種出現(xiàn)問題的情形下,數(shù)據(jù)總計(jì)數(shù)值為256,由于在STOP狀態(tài)發(fā)出后,第二個(gè)字節(jié)的數(shù)據(jù)在讀取之前減少了1,所以顯示為511,圖2給出了多次讀取數(shù)據(jù)時(shí),這種故障的抽樣情況。

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

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

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

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

非常好我支持^.^

(11) 73.3%

不好我反對(duì)

(4) 26.7%