寫在前面的話:由于外設(shè)I/O涉及到GPIO狞洋、PWM窖维、和串行通信三部分榆综,而串行通信有講了I2C(IIC)、SPI铸史、UART鼻疮,這樣導(dǎo)致本文的篇幅過長不便于閱讀,特此將本文分成幾部分來方便閱讀
- Android Things 外設(shè)I/O-GPIO
- Android Things 外設(shè)I/O-PWM
- Android Things 外設(shè)I/O-I2C(IIC)
- Android Things 外設(shè)I/O-SPI
- Android Things 外設(shè)I/O-UART
Android Things提供了外設(shè)I/O API琳轿,使用行業(yè)標(biāo)準(zhǔn)協(xié)議和接口與傳感器和執(zhí)行器進(jìn)行通信判沟。
通用輸入/輸出(GPIO)
將此API用于簡單傳感器,例如運(yùn)動探測器崭篡、接近探測器和電平開關(guān)挪哄,它們將當(dāng)前狀態(tài)報告為二進(jìn)制值高或低。
通用輸入/輸出(GPIO)引腳提供了一個可編程接口琉闪,用于讀取二進(jìn)制輸入設(shè)備(例如按鈕開關(guān))的狀態(tài)或控制二進(jìn)制輸出設(shè)備(例如LED)的開/關(guān)狀態(tài)迹炼。
您可以將GPIO引腳配置為具有高或低狀態(tài)的輸入或輸出。 作為輸入時塘偎,當(dāng)外部源狀態(tài)確定疗涉,您的應(yīng)用程序就可以讀取當(dāng)前值拿霉,或者對狀態(tài)更改做出相應(yīng)反應(yīng)吟秩。 作為輸出時,您的應(yīng)用程序可以配置引腳的狀態(tài)绽淘。
注意:為避免損壞GPIO引腳涵防,請?jiān)谶B線之前檢查硬件的輸入和輸出限制。 請參閱硬件基礎(chǔ)并查閱硬件的文檔沪铭。
管理連接
為了打開到GPIO端口的連接壮池,您需要知道唯一的端口名稱。 在開發(fā)的初始階段或?qū)?yīng)用程序移植到新硬件時杀怠,通過getGpioList()
從PeripheralManagerService
找到所有可用的端口名稱很有幫助:
PeripheralManagerService manager = new PeripheralManagerService();
List<String> portList = manager.getGpioList();
if (portList.isEmpty()) {
Log.i(TAG, "No GPIO port available on this device.");
} else {
Log.i(TAG, "List of available ports: " + portList);
}
知道端口名稱后椰憋,就可以使用PeripheralManagerService
連接到該端口。 當(dāng)您完成與GPIO端口的通信后赔退,記得關(guān)閉連接以釋放資源橙依。 此外证舟,在現(xiàn)有連接關(guān)閉之前,無法打開與同一端口的新連接窗骑。 要關(guān)閉連接女责,請使用端口的close()
方法。
public class HomeActivity extends Activity {
// GPIO引腳名稱
private static final String GPIO_NAME = ...;
private Gpio mGpio;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 嘗試訪問GPIO
try {
PeripheralManagerService manager = new PeripheralManagerService();
mGpio = manager.openGpio(GPIO_NAME);
} catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mGpio != null) {
try {
mGpio.close();
mGpio = null;
} catch (IOException e) {
Log.w(TAG, "Unable to close GPIO", e);
}
}
}
}
從輸入端讀取
要讀取GPIO作為輸入端的端口:
- 使用mode DIRECTION_IN的setDirection()將其配置為輸入创译。
- 通過使用ACTIVE_HIGH或ACTIVE_LOW調(diào)用setActiveType()抵知,將高電平(接近IOREF)或低電平(接近零)電壓信號配置為真(活動)。
- 使用getValue()方法訪問當(dāng)前狀態(tài)软族。
以下代碼顯示如何設(shè)置具有與高電壓電平相關(guān)聯(lián)的活動狀態(tài)的輸入:
public void configureInput(Gpio gpio) throws IOException {
// 將引腳初始化為輸入
gpio.setDirection(Gpio.DIRECTION_IN);
// 高電平有效
gpio.setActiveType(Gpio.ACTIVE_HIGH);
...
// 讀取有效的高引腳狀態(tài)
if (gpio.getValue()) {
// 引腳為高電平
} else {
// 引腳為低電平
}
}
監(jiān)聽輸入狀態(tài)變化
配置為輸入的GPIO端口可以在其狀態(tài)在高和低之間變化時通知應(yīng)用程序刷喜。 要注冊這些更改事件:
- 將GpioCallback附加到活動端口連接。
- 使用setEdgeTriggerType()方法聲明觸發(fā)中斷事件的狀態(tài)更改互订。 邊沿觸發(fā)支持以下四種類型:
- EDGE_NONE:無中斷事件吱肌。 這是默認(rèn)值。
- EDGE_RISING:從低到高的轉(zhuǎn)換時中斷
- EDGE_FALLING:從高到低的轉(zhuǎn)換時中斷
- EDGE_BOTH:所有狀態(tài)轉(zhuǎn)換的中斷
- 從onGpioEdge()內(nèi)返回true以指示偵聽器應(yīng)繼續(xù)接收每個端口狀態(tài)更改的事件仰禽。
以下代碼為給定輸入端口上的所有狀態(tài)更改注冊了一個中斷偵聽器:
public void configureInput(Gpio gpio) throws IOException {
// 將引腳初始化為輸入狀態(tài)
gpio.setDirection(Gpio.DIRECTION_IN);
// 設(shè)置低電平狀態(tài)有效
gpio.setActiveType(Gpio.ACTIVE_LOW);
// 注冊所有狀態(tài)更改
gpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
gpio.registerGpioCallback(mGpioCallback);
}
private GpioCallback mGpioCallback = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
// 讀取低電平有效的低電平狀態(tài)
if (mDevice.getValue()) {
// 引腳為低電平
} else {
// 引腳為高電平
}
// 繼續(xù)監(jiān)聽更多中斷
return true;
}
@Override
public void onGpioError(Gpio gpio, int error) {
Log.w(TAG, gpio + ": Error event " + error);
}
};
- 當(dāng)您的應(yīng)用程序不再監(jiān)聽傳入事件時氮墨,取消注冊所有中斷處理程序:
public class HomeActivity extends Activity {
private Gpio mGpio;
...
@Override
protected void onStart() {
super.onStart();
// 開始監(jiān)聽中斷事件
mGpio.registerGpioCallback(mGpioCallback);
}
@Override
protected void onStop() {
super.onStop();
// 中斷事件不再需要
mGpio.unregisterGpioCallback(mGpioCallback);
}
}
寫入輸出端口
以編程方式控制GPIO端口的狀態(tài):
- 使用setDirection()將其配置為輸出,模式為DIRECTION_OUT_INITIALLY_HIGH或DIRECTION_OUT_INITIALLY_LOW吐葵。 這些模式確保端口的初始狀態(tài)也在配置時正確設(shè)置规揪。
- 通過使用ACTIVE_HIGH或ACTIVE_LOW調(diào)用setActiveType(),將高電平(接近IOREF)或低電平(接近零)電壓信號配置為真(活動)温峭。
- 使用setValue()方法設(shè)置當(dāng)前狀態(tài)猛铅。
以下代碼顯示如何將輸出設(shè)置為初始為高,然后使用setValue()方法將其狀態(tài)切換為低:
public void configureOutput(Gpio gpio) throws IOException {
// 將引腳初始化為高電平輸出
gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH);
// 低電平有效
gpio.setActiveType(Gpio.ACTIVE_LOW);
...
// 將值切換為LOW
gpio.setValue(true);
}