首頁 > 評(píng)測(cè) > NXP i.MX7D與AndroidThings系列之四:GPIO及點(diǎn)燈

NXP i.MX7D與AndroidThings系列之四:GPIO及點(diǎn)燈

NXP   i.MX7D   AndroidThings   GPIO   點(diǎn)燈   
  • 作者:SATURN
  • 來源:21ic
  • [導(dǎo)讀]
  • 終于到點(diǎn)燈了! 有人早就不耐煩了,不就點(diǎn)個(gè)燈,多大點(diǎn)事!在MCUer的眼里,點(diǎn)燈就屁大點(diǎn)事,雖然說在AndroidThings的世界里,點(diǎn)燈也就屁大點(diǎn)事。不過有些事得交待清楚才行! 第一個(gè)問題就是GPIO命名的事,像Arduino直接用編號(hào),例如常見的13號(hào)就代表USER LED,ST的MCU有自己的命名規(guī)則,NXP也有自己的規(guī)格,當(dāng)然AndroidThings也有自己的命名規(guī)則。

 終于到點(diǎn)燈了!

有人早就不耐煩了,不就點(diǎn)個(gè)燈,多大點(diǎn)事!在MCUer的眼里,點(diǎn)燈就屁大點(diǎn)事,雖然說在AndroidThings的世界里,點(diǎn)燈也就屁大點(diǎn)事。不過有些事得交待清楚才行!

歡迎加入Android Things交流群:452863046

第一個(gè)問題就是GPIO命名的事,像Arduino直接用編號(hào),例如常見的13號(hào)就代表USER LED,STMCU有自己的命名規(guī)則,NXP也有自己的規(guī)格,當(dāng)然AndroidThings也有自己的命名規(guī)則。

AndroidThings使用字符串來命名GPIO,先看下i.MX7DGPIO引腳圖 

rId21.png

i.MX7D中,純粹用于GPIO的一共是12個(gè)引腳,命名形式采用GPIOx_IOxx形式,其中x代表的是數(shù)字,例如GPIO6_IO12就是編號(hào)為18的引腳。

其實(shí)是APP的權(quán)限設(shè)置問題,要使用GPIO外設(shè),需要打開相關(guān)的權(quán)限,代碼如下

<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />

 

AndroidThings使用PeripheralManager類來管理外設(shè),不管是GPIO也好,I2C也好,統(tǒng)統(tǒng)都通過該類來進(jìn)行管理,該類提供了getGpioList()方法來獲取平臺(tái)提供的GPIO引腳,另外openGpio()方法則用來打開指定的GPIO端口,該方法返回一個(gè)Gpio對(duì)象,Gpio類提供了所有與GPIO操作相關(guān)的方法,如讀取/寫入/關(guān)閉等操作。

另外還值得一提的是外設(shè)操作都有可能拋出異常,所以一般的外設(shè)操作都封裝在

try {
    ...
} catch

塊中。

使用的LED燈連接到GPIO6_IO12引腳上,下面是完整的代碼

public class MainActivity extends Activity {
    private static final String TAG = "TAG";
    private static final String LED_NAME = "GPIO6_IO12";
 
    private PeripheralManager mPeripheralManager;
    private Gpio mGpio;
    private Handler mHandler = new Handler();
 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mPeripheralManager = PeripheralManager.getInstance();
        Log.d(TAG, "onCreate: " + mPeripheralManager.getGpioList());
        try {
            mGpio = mPeripheralManager.openGpio(LED_NAME);
            mGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
            mGpio.setActiveType(Gpio.ACTIVE_HIGH);
 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        mHandler.post(new Runnable() {
            @Override 
            public void run() {
                if(mGpio == null) {
                    return;
                }
 
                try {
                    mGpio.setValue(!mGpio.getValue());
                    //Log.d(TAG, "run: " + mGpio.getValue());
                } catch (IOException e) {
                    e.printStackTrace();
                }
 
                mHandler.postDelayed(this, 500);
 
            }
        });
    }
 
    @Override 
    protected void onDestroy() {
        super.onDestroy();
        if(mGpio != null) {
            try {
                mGpio.close();
                mGpio = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

代碼2~7行是一些常量及變量的聲明,如GPIO名稱,PeripheralManager、Gpio等。

onCreate()函數(shù)中,我們使用了如下代碼來獲取GPIO列表

Log.d(TAG, "onCreate: " + mPeripheralManager.getGpioList());

對(duì)應(yīng)的輸出如下

onCreate: [GPIO1_IO10, GPIO2_IO00, GPIO2_IO01, GPIO2_IO02, GPIO2_IO03, GPIO2_IO05, GPIO2_IO07, GPIO5_IO00, GPIO6_IO12, GPIO6_IO13, GPIO6_IO14, GPIO6_IO15]

這是Logcat中打印出來的內(nèi)容,i.MX7D中所有可用的GPIO都列出來了,和官方給出的GPIO接口標(biāo)注是一致的,至于具體的位置就只能參考官方的GPIO標(biāo)注了。

下面一段代碼的作用是打開GPIO端口并做初始化配置

        try {
            mGpio = mPeripheralManager.openGpio(LED_NAME);
            mGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
            mGpio.setActiveType(Gpio.ACTIVE_HIGH);
 
        } catch (IOException e) {
            e.printStackTrace();
        }

首先使用PeripheralManager來打個(gè)一個(gè)端口,接下來的mGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)是設(shè)置GPIO的方向,OUT就是輸出,后面的LOW指定初始化為低,mGpio.setActiveType(Gpio.ACTIVE_HIGH)的作用主要用來讀取值,即高電平代表真,否則為假,如果這個(gè)地方指定Gpio.ACTIVE_LOW,則讀取到高電平返回假,否則返加真。這段話讀起來有點(diǎn)拗口,但是一定要搞清楚。

最后要注意的是這些GPIO操作都放在try...catch...塊內(nèi),用來處理可能拋出的異常。

接下來的onDestroy()方法,這里執(zhí)行資源釋放相關(guān)問題。

一旦Activity被銷毀,則要將申請(qǐng)的外設(shè)資源釋放。雖然在AndroidThings中,Activity被銷毀的情況相對(duì)來說比較少,但做為良好的編程習(xí)慣,還是要將這些代碼添加進(jìn)來。

至于代碼中與Handler相關(guān)的操作,這是用來定時(shí)的,即控制LED燈閃爍。

Handlerpost()方法是立即執(zhí)行相關(guān)的代碼,這里指定的是Runnable對(duì)象,而后面的postDelay()方法則在延遲指定的時(shí)間段(單位為毫秒)后開始執(zhí)行Runnable對(duì)象。這樣就實(shí)現(xiàn)了一般MCU中的定時(shí)操作。

GpiogetValue()setValue()用來讀取及寫入GPIO商品狀態(tài)值,這些值是布爾類型,具體的含義則與Gpio.setActiveType()中指定的值息息相關(guān)。

編譯、上傳代碼至開發(fā)板,LED燈開始閃爍

 rId22.jpg

點(diǎn)燈完畢。

不過還有些事值得討論,這里只說了GPIO的輸出,GPIO也可以配置為輸入,可以讀取按鍵狀態(tài)等信息,下面的代碼片斷演示了如何將GPIO配置為輸入模式并使用中斷來處理相關(guān)事件

public void configureInput(Gpio gpio) throws IOException {
    // Initialize the pin as an input
    gpio.setDirection(Gpio.DIRECTION_IN);
    // Low voltage is considered active
    gpio.setActiveType(Gpio.ACTIVE_LOW);
 
    // Register for all state changes
    gpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
    gpio.registerGpioCallback(mGpioCallback);
}
 
private GpioCallback mGpioCallback = new GpioCallback() {
    @Override 
    public boolean onGpioEdge(Gpio gpio) {
        // Read the active low pin state
        if (gpio.getValue()) {
            // Pin is LOW
        } else {
            // Pin is HIGH
        }
 
        // Continue listening for more interrupts
        return true;
    }
 
    @Override 
    public void onGpioError(Gpio gpio, int error) {
        Log.w(TAG, gpio + ": Error event " + error);
    }
};

GpioCallback類定義了回調(diào)相關(guān)操作,用來處理不同的狀態(tài)。

下面的代碼則演示了如何來注冊(cè)及注銷相關(guān)的回調(diào)

public class HomeActivity extends Activity {
    private Gpio mGpio;
    ...
 
    @Override 
    protected void onStart() {
        super.onStart();
 
        // Begin listening for interrupt events
        mGpio.registerGpioCallback(mGpioCallback);
    }
 
    @Override 
    protected void onStop() {
        super.onStop();
        // Interrupt events no longer necessary
        mGpio.unregisterGpioCallback(mGpioCallback);
    }
}

補(bǔ)充一點(diǎn),GPIO使用的是只是簡(jiǎn)單的狀態(tài)檢測(cè),在處理按鍵時(shí),有一個(gè)問題可能要考慮到,那就是抖動(dòng)問題,如果沒有硬件消抖,則需要用戶使用代碼來消除抖動(dòng)。AndroidThings的三方庫中包括一個(gè)button組件,可以直接使用,詳情請(qǐng)參考https://github.com/androidthings/contrib-drivers。

GPIO庫使用起來非常舒服,不止如此,只要掌握了GPIO的運(yùn)行模式,后面的PWMI2C等操作,基本模式是一致的。

下一節(jié)來點(diǎn)個(gè)1602屏。

 

  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評(píng)論

  • 聯(lián)系人:巧克力娃娃
  • 郵箱:board@21ic.com
  • 我要投稿
  • 歡迎入駐,開放投稿

熱門標(biāo)簽
項(xiàng)目外包 more+