SDK使用ESP8266_NONOS_SDK V3.0
此文记录在使用GPIO口时,功能复用以及IO中断的问题。
接口 位于 /ESP8266_NONOS_SDK/include/eagle_soc.h和gpio.h。
管脚功能选择宏定义:PIN_FUNC_SELECT(PIN_NAME,FUNC);对于不同的引脚,PIN_NAME不同,IO口复用的功能FUNC也不同。由于我在配置GPIO14时,不小心错写成FUNC_GPIO4,IO口电平死活不会反转。。。
以8266的MTMS为例,说明GPIO功能的选择。
功能选择寄存器PERIPHS_IO_MUX_MTMS_U(不同的GPIO,该寄存器不同)
配置的时候,请参考引脚配置表,如下图
需要注意的是,如果需要配置为FUNCTION3,应该往寄存器对应的位中写2,如果需要配置为FUNCTION2,应该往寄存器对应的位中写1,以此类推。
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);//led
GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 1);
GPIO中断相关宏:
ETS_GPIO_INTR_ENABLE() //开 GPIO 中断
ETS_GPIO_INTR_DISABLE() //关 GPIO 中断
ETS_GPIO_INTR_ATTACH(func, arg) //注册 GPIO 中断处理函数
GPIO中断相关函数:gpio_pin_intr_state_set
0是失能; 1是上升沿触发; 2是下降沿; 3是边沿;4是低电平;5是高电平
参考:https://www.jianshu.com/p/ec424a87ded0
简单说下这种处理方式,在user_init()函数中加入按键初始化,注册中断处理函数以及设置为下降沿触发方式。然后在中断处理函数里面判断IO口状态,再delay延时后再去判断IO口状态,来最终判断是否按键按下。实际使用发现去抖效果并不好,会多次触发。而且个人也不喜欢这个延时方式。
于是在网上搜索发现sdk里面自带了按键的API,下面主要介绍这个以及遇到的问题。
参考:https://blog.csdn.net/qq_15647227/article/details/52218376
相关API不再介绍,参考链接即可,里面说的很详细了。使用时只需要将key.c和key.h放入你工程目录app下面的相应位置即可。key.c里面改为#include “key.h”。
说下不一样的,我是一个按键既有短按功能,也有长按功能。按照sdk的流程是有点问题的,长按后松手也会触发短按程序。
先贴初始化代码:
void usr_key_init(void)//按键初始化
{
switch_signle = key_init_single(GPIO_KEY_ID,
GPIO_KEY_NAME,
GPIO_KEY_FUNC,
&usr_longkey_process,
&usr_shortkey_process);
switch_param.key_num = 1;
switch_param.single_key = &switch_signle;
key_init(&switch_param);
}
按键处理函数:
static void usr_shortkey_process()
{
os_timer_disarm(&led_time);//定时器设置
os_timer_setfn(&led_time, (os_timer_func_t *)led_callback, NULL);
os_timer_arm(&led_time, 500, 1);//0.5s
os_printf("shortkey press!!!\r\n");
}
static void usr_longkey_process()
{
os_timer_disarm(&led_time);//定时器设置
os_timer_setfn(&led_time, (os_timer_func_t *)led_callback, NULL);
os_timer_arm(&led_time, 2000, 1);//2s
os_printf("longkey press!!!\r\n");
}
针对长按触发后松手会触发短按的现象,我对key.c相关函数做了修改。
首先我在5s定时器回调函数中置位key_level=2;
LOCAL void ICACHE_FLASH_ATTR
key_5s_cb(struct single_key_param *single_key)
{
os_timer_disarm(&single_key->key_5s);
// low, then restart
if (0 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
single_key->key_level = 2;
if (single_key->long_press) {
single_key->long_press();
}
}
}
在key_intr_handler()函数中加入长按松手后检测判断。
else if (keys->single_key[i]->key_level == 2){
keys->single_key[i]->key_level = 1;
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_NEGEDGE);
}
这样就实现了一个按键的短按和长按功能。
相对来说,软定时器没遇到什么问题。大家可以参考:https://blog.csdn.net/xh870189248/article/details/78155357
只要注意在初始化前先关闭该定时器,同一个定时器不能同时使用。还有就是设置好回调函数。我的回调函数如下:
void ICACHE_FLASH_ATTR
led_callback(void) // test
{
// os_printf("What!\r\n");
if (led_status == true)
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 0);
led_status = false;
}
else
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 1);
led_status = true;
}
}
以上便是我使用gpio遇到的问题了,欢迎不妥之处给予指正。