【HarmonyOS HiSpark Wi-Fi IoT 套件试用连载】更加优雅的使用OLED板的按键 - HarmonyOS技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

杜潇泊 关注 私信
[文章]

【HarmonyOS HiSpark Wi-Fi IoT 套件试用连载】更加优雅的使用OLED板的按键

本帖最后由 杜潇泊 于 2020-11-16 18:02 编辑

开发板OLED板下面有两个按键,上手开发板第一件事肯定是调试输入输出手段。串口几乎不需要调试什么,上手就能用。这个按键就成了第一个下手的目标。
起初没把这俩按键当回事,以为只是直接接在GPIO上的,顶多设置一下触发点平就行了。拿到原理图才发现,这俩按键居然是这样接的。
微信图片_20201028161006.png
也就是说必须使用ADC才能确认按下的是哪一个键。开发板官方给出了OLED板的demo,其中也包含了对屏幕下面两个按键的使用。但是查看代码发现,是使用死循环不断进行ADC转换来捕捉按键操作的。这样做会导致系统功耗上升,并且会持续占用CPU。

其实我们可以更加优雅的使用这俩按键,使用按键终端触发按键事件,再由按键线程完成按键事件的处理。这样做在平时不按按键时,系统CPU处于IDLE状态、ADC也处于停止状态。功耗、CPU都能降下来。甚至你可以配置进入低功耗模式。

代码不多
// 全局信号量,记录按键事件
osSemaphoreId_t g_keySem;

void KeyPressed(char *arg) {
    (void)arg;
    //释放一个信号量,注意这里是中断上下文,最好别调用太多东西
    osSemaphoreRelease(g_keySem);
}

void handlePressKeyTask(void* arg) {
    (void)arg;
    while(true) {
        // 这里去消费按键事件
        osStatus_t status = osSemaphoreAcquire(g_keySem,65535);
        if(status != 0) {
            continue;
        }

        while(true) {
            unsigned short data = 0;
            AdcRead(ANALOG_KEY_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0);
            float voltage = (float)data * 1.8 * 4 / 4096;

            if(voltage < 0.8f) {
                ssd1306_Fill(Black);
                ssd1306_SetCursor(0, 0);
                ssd1306_DrawString("Key1 Pressed!", Font_7x10, White);
                ssd1306_UpdateScreen();
            } else if(voltage < 2.0f) {
                ssd1306_Fill(Black);
                ssd1306_SetCursor(0, 0);
                ssd1306_DrawString("Key2 Pressed!", Font_7x10, White);
                ssd1306_UpdateScreen();
            } else {
                ssd1306_Fill(Black);
                ssd1306_SetCursor(0, 0);
                ssd1306_DrawString("Released!", Font_7x10, White);
                ssd1306_UpdateScreen();
                break;
            }
        }
    }
}

void initKey() {
    // 端口设置为GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO);
    // 设置为输入
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_GPIO_DIR_IN);
    // 设置在下降沿中断。(其实我想设置下降沿和上升沿中断的,然而接口居然不允许)
   
    osSemaphoreAttr_t semAttr = {
            .name = "KeyPressSemi",
            .attr_bits = 0,
            .cb_mem = NULL,
            .cb_size = 0
        };
    g_keySem = osSemaphoreNew(8, 0, &semAttr);
    GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_INT_TYPE_EDGE, WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW, KeyPressed, NULL);
   
    // 这里启动一个task处理按键事件
    osThreadAttr_t attr;
    attr.name = "KeyHandleTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 2048;
    attr.priority = osPriorityNormal;
    if (osThreadNew(handlePressKeyTask, NULL, &attr) == NULL) {
        printf("[%s]Falied to create KeyHandleTask!n", __func__);
    }
   
}

更多回帖

×
发帖