本文我將使用BBB的I2C1讀取氣壓傳感器芯片BMP085和三軸陀螺儀L3G4200D的值。
在c語言中實現讀取i2c設備的方法請見《使用Beaglebone Black的I2C(二)》
前言
首先說明,我使用的硬件外設是一個九軸氣壓傳感器模塊,包括一個三軸陀螺儀芯片,一個三軸磁場傳感器芯片,一個三軸加速度計芯片和一個氣壓傳感器芯片。這4個芯片使用同一個I2C與BBB通信,下面記錄一下它的使用方法。
I2C是一種串行通訊方法,它只需要兩根線就能實現通訊,一根時鐘線SCL,一根數據線SDA。一般情況下這兩根線都使用上拉電阻,同時把芯片的管腳設置成開漏輸出(簡單理解開漏輸出的含義就是:讓它輸出低電平時,它能輸出低電平;而讓它輸出高電平時,它就斷路,什麼也不輸出,由外接電平決定這個引腳的電平)。如果芯片內部帶有上拉電阻(比如BBB的芯片就自帶上拉電阻),那不外接上拉也可以。
BBB系統自帶了一個Linux下的I2C工具i2c-tools,非常好用,下文以i2c開頭的命令都是這個工具包裏的,如果你的系統裏沒有的話,可以搜索並下載i2c-tools工具包。
BBB上有兩個可用的I2C,i2c-0和i2c-1,分別對應header上的I2C1和I2C2(總是這麼混亂= =)。我們這裏使用i2c-1,對應的header是P9_19和P9_20。我怎麼知道它有兩個可用的I2C呢?使用命令 i2cdetect -l 就可以看到
i2c-0 i2c OMAP I2C adapter I2C adapter
i2c-1 i2c OMAP I2C adapter I2C adapter
OK,下面開始操作。
檢查引腳功能配置
首先確認一下i2c-1對應的IO口複用功能是否正確(BBB默認就是正確的,所以無需進行配置)。查表得,P9_19和P9_20分別對應95和94號引腳。(在新頁面打開圖片可看到完整圖)
輸入命令
# cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep 97c
上述命令把pins這個文件中包含97c的內容輸出(97c是表中看到的引腳地址),得到95號引腳的功能和複用寄存器值
pin 95 (44e1097c) 00000073 pinctrl-single
95號引腳的功能寄存器值是0x00000073,化成2進制是1110011,其含義是:啓用功能3(即I2C2_SCL),使能上下拉,開啓上拉(所以我們可以不必外接上拉電阻了),使能輸入,高速模式。同樣可以檢查94號引腳,也是0x00000073。
查找i2c設備的地址
(此時我們還沒有插入設備)使用命令# i2cdetect -y -r 1 ,可以查看i2c設備地址。其中 -y 選項用來屏蔽討厭的確認環節,-r 是因爲AM3359不支持一種叫做Quick Write的東東,1 代表我們要查看i2c-1總線上的設備(也就是P9_19和P9_20上插着的設備)。輸出如下
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
這裏的地址都是16進製表示的。--代表該地址沒有設備,UU代表這個地址正忙(也許被內部資源佔用了,見圖中的0x54到0x57這4個地址)。下面我把i2c設備插上以後再執行命令,輸出變成了
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- 53 UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
會發現多出了4個地址:0x1e,0x53,0x69和0x77。因爲我接入的模塊上包含4個芯片,所以這個總線上顯示了4個地址。通過讀芯片手冊得知氣壓計對應的是0x77這個地址。這一步就完成了。
需要補充說明的是,這裏顯示的是i2c設備的地址(1110111b=0x77),i2c的設備地址只有7位,最高位當做0。而讀/寫地址則在最低位增加一個1/0(11101111b / 11101110b),這使得讀寫地址與設備地址看起來很不相同。
查看和修改設備的寄存器值
輸入命令# i2cdump -y 1 0x77,我們可以查看設備的寄存器值,其中 -y 還是屏蔽確認環節,1 還是代表查看i2c-1總線,0x77是要查詢的設備地址。
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: a5 94 4d 19 b3 27 38 43 8a 2a 1e 05 fb af c7 6e ??M??'8C?*?????n
90: 84 df 5f b0 56 5a 15 7a 00 3a 80 00 d4 bd 09 80 ??_?VZ?z.:?.????
a0: a5 94 4d 19 b3 27 38 43 8a 2a 1e 05 fb af c7 6e ??M??'8C?*?????n
b0: 84 df 5f b0 56 5a 15 7a 00 3a 80 00 d4 bd 09 80 ??_?VZ?z.:?.????
c0: 00 00 bc 33 00 00 00 00 00 00 00 10 00 00 00 03 ..?3.......?...?
d0: 55 02 06 00 00 00 00 00 00 00 00 00 00 00 00 00 U??.............
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 ......?.........
這裏用16進制顯示了每個寄存器的值,具體哪個寄存器是幹嘛的,就得查閱芯片的數據手冊了。
如果想取出某個特定寄存器的值,比如0x80寄存器,可以使用命令 i2cget -y 1 0x77 0x80實現。如果想向某個寄存器寫入值,可使用命令 i2cset -y 1 0x69 0x20 0x0f實現。(向i2c-1總線上,設備地址爲0x69,寄存器地址爲0x20處寫入值0x0f)
使用BMP085驅動讀取氣壓值
很巧的是,BBB自帶了BMP085氣壓芯片的驅動,所以我們可以更方便地讀取氣壓值。輸入命令
# echo bmp085 0x77 > /sys/class/i2c-adapter/i2c-1/new_device
加載成功後使用如下命令就可以讀取氣壓值了
# cat sys/bus/i2c/drivers/bmp085/1-0077/pressure0_input
使用完畢以後,我們可以用如下命令從驅動中卸載這個i2c設備
# echo 0x77 > /sys/class/i2c-adapter/i2c-1/delete_device
想查看加載或卸載是否成功的話,可以輸入如下命令
# dmesg | grep bmp
你應該會看到類似下面的輸出
[ 6428.602566] i2c i2c-1: new_device: Instantiated device bmp085 at 0x77
[ 6428.633419] bmp085 1-0077: Successfully initialized bmp085!
[ 6436.479407] i2c i2c-1: delete_device: Deleting device bmp085 at 0x77
問題
但是BBB沒有帶其他芯片的驅動,我暫時還不知道如何自己寫驅動。(見最後更新)更奇怪的是我查看其他設備地址的寄存器,得到很詭異的輸出。
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
10: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
20: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
30: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
40: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
50: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
60: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
70: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
80: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
90: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
a0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
b0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
c0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
d0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
e0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
f0: c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 c4 ????????????????
更新解答上面的問題
是輸出模式的原因。# i2cdump -y 1 0x69 c 命令中的c代表連續字節輸出。把它去掉,用默認的字節輸出模式就可以了。 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: c4 66 a5 cc 4c d0 89 c1 c2 e0 24 18 3b 87 00 d3 ?f??L?????$?;?.?
10: 44 b5 22 04 0c 80 40 60 1a 11 ee 90 83 01 85 83 D?"???@`????????
20: 07 00 00 00 00 00 00 00 00 f0 fb 06 ce fc 00 20 ?........?????.
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: c4 66 a5 cc 4c d0 89 c1 c2 e0 24 18 3b 87 00 d3 ?f??L?????$?;?.?
90: 44 b5 22 04 0c 80 40 60 1a 11 ee 90 83 01 85 83 D?"???@`????????
a0: 07 00 00 00 00 00 00 00 00 f0 fb 06 ce fc 00 20 ?........?????.
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
再多說兩句,這個設備是L3G4200D三軸陀螺儀,通過查芯片手冊得知,0x20寄存器的第4位是芯片使能,現在0x20寄存器的值是0x07,即00000111b,我要把它變成00001111b,即0x0f,輸入命令# i2cset -y 1 0x69 0x20 0x0f
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: c4 66 a5 cc 4c d0 89 c1 c2 e0 24 18 3b 87 00 d3 ?f??L?????$?;?.?
10: 44 b5 22 04 0c 80 40 60 1a 11 ee 90 83 01 85 83 D?"???@`????????
20: 0f 00 00 00 00 00 1d ff 33 00 d5 ff fc ff 00 20 ?.....?.3.?.?..
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: c4 66 a5 cc 4c d0 89 c1 c2 e0 24 18 3b 87 00 d3 ?f??L?????$?;?.?
90: 44 b5 22 04 0c 80 40 60 1a 11 ee 90 83 01 85 83 D?"???@`????????
a0: 0f 00 00 00 00 00 1d ff 52 00 f7 ff 24 00 00 20 ?.....?.R.?.$..
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............….
就成功使能陀螺儀了。根據芯片手冊,0x28到0x2d這6個寄存器存放的是三軸角速度的值,所以我們比較上面兩次i2cdump的結果會發現,這幾個寄存器是有變化的,說明芯片正常工作了。
再次更新:其實BBB帶了其他芯片驅動的……
# insmod /lib/modules/3.8.13/kernel/drivers/iio/gyro/st_gyro.ko
# echo l3g4200d 0x69 > /sys/bus/i2c/devices/i2c-1/new_device
# insmod /lib/modules/3.8.13/kernel/drivers/input/misc/adxl34x.ko
# insmod /lib/modules/3.8.13/kernel/drivers/input/misc/adxl34x-i2c.ko
但是在執行下面命令之後,# echo adxl34x 0x1e > /sys/bus/i2c/devices/i2c-1/new_device
雖然在/sys/bus/i2c/devices目錄下多了一個 1-001e 目錄,但是該目錄下沒有出現想要的有關加速度計的內容。經過# dmesg | grep adxl34x | tail -5
顯示記錄,發現給出了一個錯誤提示:[ 6960.709459] adxl34x 1-001e: no IRQ?
這是驅動源碼給出的錯誤信息。但如何解決就不清楚了,因爲還不太瞭解驅動的工作原理。在 /sys 目錄下有 block, bus, class, dev, devices, firmware, fs, kernel, module, power 這些子目錄。
devices目錄是這裏面最重要的目錄,這是內核對系統中所有設備的分層次表達模型。
block、bus、class、dev這4個目錄分別是所有的塊設備、按總線分類、按類別分類和按主次設備號分類的設備列表。實際上這4個目錄的內容最後都是指向devices目錄裏相應設備的鏈接。相當於給我們提供了幾種不同的方式找到想要找的設備。
其他目錄的內容如下:
module目錄裏顯示着幾乎所有已經加載的驅動模塊的信息,包括以內聯方式編譯到內核映像文件中的模塊和外部模塊(ko文件)。
kernel目錄是內核所有可調整參數的位置,目前只有幾項較新的設計在使用它,其它內核可調整參數仍然位於 sysctl (/proc/sys/kernel) 接口中。
fs目錄按照設計是用於描述系統中所有文件系統,但目前只有少數文件系統支持 sysfs 接口,一些傳統的虛擬文件系統(VFS)層次控制參數仍然在 sysctl (/proc/sys/fs) 接口中。
firmware目錄是系統加載固件機制的對用戶空間的接口。
power目錄是系統中電源選項,這個目錄下有幾個屬性文件可以用於控制整個機器的電源狀態,如可以向其中寫入控制命令讓機器關機、重啓等。