首頁 > 評(píng)測(cè) > NXP i.MX7D與AndroidThings系列之四:GPIO及點(diǎn)燈
NXP i.MX7D與AndroidThings系列之四:GPIO及點(diǎn)燈
- [導(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,ST的MCU有自己的命名規(guī)則,NXP也有自己的規(guī)格,當(dāng)然AndroidThings也有自己的命名規(guī)則。
AndroidThings使用字符串來命名GPIO,先看下i.MX7D的GPIO引腳圖
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燈閃爍。
Handler的post()方法是立即執(zhí)行相關(guān)的代碼,這里指定的是Runnable對(duì)象,而后面的postDelay()方法則在延遲指定的時(shí)間段(單位為毫秒)后開始執(zhí)行Runnable對(duì)象。這樣就實(shí)現(xiàn)了一般MCU中的定時(shí)操作。
Gpio的getValue()及setValue()用來讀取及寫入GPIO商品狀態(tài)值,這些值是布爾類型,具體的含義則與Gpio.setActiveType()中指定的值息息相關(guān)。
編譯、上傳代碼至開發(fā)板,LED燈開始閃爍
點(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)行模式,后面的PWM、I2C等操作,基本模式是一致的。
下一節(jié)來點(diǎn)個(gè)1602屏。
- 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!
網(wǎng)友評(píng)論
- 聯(lián)系人:巧克力娃娃
- 郵箱:board@21ic.com
- 我要投稿
-
歡迎入駐,開放投稿
- NRF52810藍(lán)牙數(shù)字耳機(jī)找人定制
預(yù)算:¥30005天前
- 125KW模塊式PCS軟硬件外包開發(fā)
預(yù)算:¥1100000015小時(shí)前
- 12V汽車啟動(dòng)電源項(xiàng)目BMS設(shè)計(jì)
預(yù)算:¥50000023小時(shí)前
- 數(shù)據(jù)可視化軟件 開發(fā)
預(yù)算:¥5000023小時(shí)前
- PLC項(xiàng)目調(diào)試修改
預(yù)算:¥100001天前
- 起動(dòng)電機(jī)控制器開發(fā)
預(yù)算:¥1100001天前