AndroidThings系列之四:GPIO及点灯

epeppanda
发布于 2021-2-20 09:48
浏览
0收藏

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

 

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

AndroidThings使用字符串来命名GPIO,先看下i.MX7D的GPIO引脚图 AndroidThings系列之四:GPIO及点灯-鸿蒙开发者社区

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名称,PeripheralManager、Gpio等。

在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灯闪烁。

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

 

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

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

AndroidThings系列之四:GPIO及点灯-鸿蒙开发者社区

点灯完毕。

 

不过还有些事值得讨论,这里只说了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的运行模式,后面的PWM、I2C等操作,基本模式是一致的。

下一节来点个1602屏。

分类
已于2021-2-20 09:48:52修改
收藏
回复
举报
回复
    相关推荐