首页 > 评测 > NXP i.MX7D与AndroidThings系列之四:GPIO及点灯

NXP i.MX7D与AndroidThings系列之四:GPIO及点灯

NXP   i.MX7D   AndroidThings   GPIO   点灯   
  • 作者:SATURN
  • 来源:21ic
  • [导读]
  • 终于到点灯了! 有人早就不耐烦了,不就点个灯,多大点事!在MCUer的眼里,点灯就屁大点事,虽然说在AndroidThings的世界里,点灯也就屁大点事。不过有些事得交待清楚才行! 第一个问题就是GPIO命名的事,像Arduino直接用编号,例如常见的13号就代表USER LED,ST的MCU有自己的命名规则,NXP也有自己的规格,当然AndroidThings也有自己的命名规则。

 终于到点灯了!

有人早就不耐烦了,不就点个灯,多大点事!在MCUer的眼里,点灯就屁大点事,虽然说在AndroidThings的世界里,点灯也就屁大点事。不过有些事得交待清楚才行!

欢迎加入Android Things交流群:452863046

第一个问题就是GPIO命名的事,像Arduino直接用编号,例如常见的13号就代表USER LEDSTMCU有自己的命名规则,NXP也有自己的规格,当然AndroidThings也有自己的命名规则。

AndroidThings使用字符串来命名GPIO,先看下i.MX7DGPIO引脚图 

rId21.png

i.MX7D中,纯粹用于GPIO的一共是12个引脚,命名形式采用GPIOx_IOxx形式,其中x代表的是数字,例如GPIO6_IO12就是编号为18的引脚。

其实是APP的权限设置问题,要使用GPIO外设,需要打开相关的权限,代码如下

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

 

AndroidThings使用PeripheralManager类来管理外设,不管是GPIO也好,I2C也好,统统都通过该类来进行管理,该类提供了getGpioList()方法来获取平台提供的GPIO引脚,另外openGpio()方法则用来打开指定的GPIO端口,该方法返回一个Gpio对象,Gpio类提供了所有与GPIO操作相关的方法,如读取/写入/关闭等操作。

另外还值得一提的是外设操作都有可能抛出异常,所以一般的外设操作都封装在

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名称,PeripheralManagerGpio等。

onCreate()函数中,我们使用了如下代码来获取GPIO列表

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

对应的输出如下

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中打印出来的内容,i.MX7D中所有可用的GPIO都列出来了,和官方给出的GPIO接口标注是一致的,至于具体的位置就只能参考官方的GPIO标注了。

下面一段代码的作用是打开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来打个一个端口,接下来的mGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)是设置GPIO的方向,OUT就是输出,后面的LOW指定初始化为低,mGpio.setActiveType(Gpio.ACTIVE_HIGH)的作用主要用来读取值,即高电平代表真,否则为假,如果这个地方指定Gpio.ACTIVE_LOW,则读取到高电平返回假,否则返加真。这段话读起来有点拗口,但是一定要搞清楚。

最后要注意的是这些GPIO操作都放在try...catch...块内,用来处理可能抛出的异常。

接下来的onDestroy()方法,这里执行资源释放相关问题。

一旦Activity被销毁,则要将申请的外设资源释放。虽然在AndroidThings中,Activity被销毁的情况相对来说比较少,但做为良好的编程习惯,还是要将这些代码添加进来。

至于代码中与Handler相关的操作,这是用来定时的,即控制LED灯闪烁。

Handlerpost()方法是立即执行相关的代码,这里指定的是Runnable对象,而后面的postDelay()方法则在延迟指定的时间段(单位为毫秒)后开始执行Runnable对象。这样就实现了一般MCU中的定时操作。

GpiogetValue()setValue()用来读取及写入GPIO商品状态值,这些值是布尔类型,具体的含义则与Gpio.setActiveType()中指定的值息息相关。

编译、上传代码至开发板,LED灯开始闪烁

 rId22.jpg

点灯完毕。

不过还有些事值得讨论,这里只说了GPIO的输出,GPIO也可以配置为输入,可以读取按键状态等信息,下面的代码片断演示了如何将GPIO配置为输入模式并使用中断来处理相关事件

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类定义了回调相关操作,用来处理不同的状态。

下面的代码则演示了如何来注册及注销相关的回调

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);
    }
}

补充一点,GPIO使用的是只是简单的状态检测,在处理按键时,有一个问题可能要考虑到,那就是抖动问题,如果没有硬件消抖,则需要用户使用代码来消除抖动。AndroidThings的三方库中包括一个button组件,可以直接使用,详情请参考https://github.com/androidthings/contrib-drivers

GPIO库使用起来非常舒服,不止如此,只要掌握了GPIO的运行模式,后面的PWMI2C等操作,基本模式是一致的。

下一节来点个1602屏。

 

  • 本文系21ic原创,未经许可禁止转载!

网友评论