Android Things 外設(shè)I/O-GPIO

寫在前面的話:由于外設(shè)I/O涉及到GPIO、PWM、和串行通信三部分,而串行通信有講了I2C(IIC)、SPI、UART,這樣導(dǎo)致本文的篇幅過長(zhǎng)不便于閱讀,特此將本文分成幾部分來方便閱讀

  1. Android Things 外設(shè)I/O-GPIO
  2. Android Things 外設(shè)I/O-PWM
  3. Android Things 外設(shè)I/O-I2C(IIC)
  4. Android Things 外設(shè)I/O-SPI
  5. Android Things 外設(shè)I/O-UART

Android Things提供了外設(shè)I/O API,使用行業(yè)標(biāo)準(zhǔn)協(xié)議和接口與傳感器和執(zhí)行器進(jìn)行通信。

通用輸入/輸出(GPIO)


將此API用于簡(jiǎn)單傳感器,例如運(yùn)動(dòng)探測(cè)器、接近探測(cè)器和電平開關(guān),它們將當(dāng)前狀態(tài)報(bào)告為二進(jìn)制值高或低。

通用輸入/輸出(GPIO)引腳提供了一個(gè)可編程接口,用于讀取二進(jìn)制輸入設(shè)備(例如按鈕開關(guān))的狀態(tài)或控制二進(jìn)制輸出設(shè)備(例如LED)的開/關(guān)狀態(tài)。

您可以將GPIO引腳配置為具有高或低狀態(tài)的輸入或輸出。 作為輸入時(shí),當(dāng)外部源狀態(tài)確定,您的應(yīng)用程序就可以讀取當(dāng)前值,或者對(duì)狀態(tài)更改做出相應(yīng)反應(yīng)。 作為輸出時(shí),您的應(yīng)用程序可以配置引腳的狀態(tài)。

注意:為避免損壞GPIO引腳,請(qǐng)?jiān)谶B線之前檢查硬件的輸入和輸出限制。 請(qǐng)參閱硬件基礎(chǔ)并查閱硬件的文檔。

管理連接

為了打開到GPIO端口的連接,您需要知道唯一的端口名稱。 在開發(fā)的初始階段或?qū)?yīng)用程序移植到新硬件時(shí),通過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)閉連接,請(qǐng)使用端口的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作為輸入端的端口:

  1. 使用mode DIRECTION_IN的setDirection()將其配置為輸入。
  2. 通過使用ACTIVE_HIGH或ACTIVE_LOW調(diào)用setActiveType(),將高電平(接近IOREF)或低電平(接近零)電壓信號(hào)配置為真(活動(dòng))。
  3. 使用getValue()方法訪問當(dāng)前狀態(tài)。

以下代碼顯示如何設(shè)置具有與高電壓電平相關(guān)聯(lián)的活動(dòng)狀態(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)在高和低之間變化時(shí)通知應(yīng)用程序。 要注冊(cè)這些更改事件:

  1. 將GpioCallback附加到活動(dòng)端口連接。
  2. 使用setEdgeTriggerType()方法聲明觸發(fā)中斷事件的狀態(tài)更改。 邊沿觸發(fā)支持以下四種類型:
  • EDGE_NONE:無中斷事件。 這是默認(rèn)值。
  • EDGE_RISING:從低到高的轉(zhuǎn)換時(shí)中斷
  • EDGE_FALLING:從高到低的轉(zhuǎn)換時(shí)中斷
  • EDGE_BOTH:所有狀態(tài)轉(zhuǎn)換的中斷
  1. 從onGpioEdge()內(nèi)返回true以指示偵聽器應(yīng)繼續(xù)接收每個(gè)端口狀態(tài)更改的事件。
    以下代碼為給定輸入端口上的所有狀態(tài)更改注冊(cè)了一個(gè)中斷偵聽器:
public void configureInput(Gpio gpio) throws IOException {
    // 將引腳初始化為輸入狀態(tài)
    gpio.setDirection(Gpio.DIRECTION_IN);
    // 設(shè)置低電平狀態(tài)有效
    gpio.setActiveType(Gpio.ACTIVE_LOW);

    // 注冊(cè)所有狀態(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);
    }
};
  1. 當(dāng)您的應(yīng)用程序不再監(jiān)聽傳入事件時(shí),取消注冊(cè)所有中斷處理程序:
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):

  1. 使用setDirection()將其配置為輸出,模式為DIRECTION_OUT_INITIALLY_HIGH或DIRECTION_OUT_INITIALLY_LOW。 這些模式確保端口的初始狀態(tài)也在配置時(shí)正確設(shè)置。
  2. 通過使用ACTIVE_HIGH或ACTIVE_LOW調(diào)用setActiveType(),將高電平(接近IOREF)或低電平(接近零)電壓信號(hào)配置為真(活動(dòng))。
  3. 使用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);

    ...

    // 將值切換為L(zhǎng)OW
    gpio.setValue(true);
}

參考文獻(xiàn) https://developer.android.google.cn/things/sdk

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容