一、功能实现:
1、修改宏定义中按钮的位置。
2、在main函数里将按钮初始化。
3、修改自定义函数内容。
二、完整代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "lvgl_init.h"
#define GPIO_OUTPUT_IO_LED2 15
#define GPIO_OUTPUT_IO_LED3 2
#define GPIO_OUTPUT_IO_LED4 4
#define GPIO_OUTPUT_IO_BEEP 19
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_LED2) | (1ULL<<GPIO_OUTPUT_IO_LED3) | (1ULL<<GPIO_OUTPUT_IO_LED4)| (1ULL<<GPIO_OUTPUT_IO_BEEP))
#define GPIO_INPUT_IO_SW3 37
#define GPIO_INPUT_IO_SW4 38
#define GPIO_INPUT_IO_SW5 39
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_SW3) | (1ULL<<GPIO_INPUT_IO_SW4)| (1ULL<<GPIO_INPUT_IO_SW5))
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "time.h"
#include "sys/time.h"
#include "sys/unistd.h"
#include <sys/time.h>
long CurrentTime=0;
void UpdateCurrentTime(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
CurrentTime=tv.tv_sec*1000+tv.tv_usec/1000;
}
int display1=0;
int display2=0;
int display3=0;
int display4=0;
int display5=0;
int display6=0;
int display7=0;
int display8=0;
int display9=0;
typedef unsigned char u8;
typedef unsigned short u16;
#define KEY_NUM 5
#define GPIO_KEY1 14
#define GPIO_KEY2 12
#define GPIO_KEY3 0
#define GPIO_KEYEXT 19
#define GPIO_KEYEXT2 5
#define GPIO_INPUT_HW_PIN_SEL ((1ULL<<GPIO_KEY1) | (1ULL<<GPIO_KEY2)| (1ULL<<GPIO_KEY3)| (1ULL<<GPIO_KEYEXT)| (1ULL<<GPIO_KEYEXT2))
void HardwareInit(void);
void HandleKey(void);
void OnKey1Presseds(void)
{
display1++;
printf("key1presseds:%d\n",display1);
sleep(0.5);
}
void OnKey1Pressedl(void)
{
display2++;
printf("key1pressedl:%d\n",display2);
}
void OnKey1Released(void)
{
display3++;
printf("Key1Released:%d\n",display3);
}
void OnKey2Presseds(void)
{
display4++;
printf("key2presseds:%d\n",display4);
sleep(0.5);
}
void OnKey2Pressedl(void)
{
display5++;
printf("key2pressedl:%d\n",display5);
}
void OnKey2Released(void)
{
display6++;
printf("Key2Released:%d\n",display6);
}
void OnKey3Presseds(void)
{
display7++;
printf("key3presseds:%d\n",display7);
sleep(0.5);
}
void OnKey3Pressedl(void)
{
display8++;
printf("key3pressedl:%d\n",display8);
}
void OnKey3Released(void)
{
display9++;
printf("Key3Released:%d\n",display9);
}
void OnKeyEXTPresseds(void)
{
}
void OnKeyEXTPressedl(void)
{
}
void OnKeyEXTReleased(void)
{
}
void OnKeyEXT2Presseds(void)
{
}
void OnKeyEXT2Pressedl(void)
{
}
void OnKeyEXT2Released(void)
{
}
gpio_num_t KeyPinNum[]={GPIO_KEY1,GPIO_KEY2,GPIO_KEY3,GPIO_KEYEXT,GPIO_KEYEXT2,};
void (*pOnKeyPressedS[])(void)={OnKey1Presseds,OnKey2Presseds,OnKey3Presseds,OnKeyEXTPresseds,OnKeyEXT2Presseds};
void (*pOnKeyPressedL[])(void)={OnKey1Pressedl,OnKey2Pressedl,OnKey3Pressedl,OnKeyEXTPressedl,OnKeyEXT2Pressedl};
void (*pOnKeyReleased[])(void)={OnKey1Released,OnKey2Released,OnKey3Released,OnKeyEXTReleased,OnKeyEXT2Released};
u8 KeyPressed[]={0,0,0,0,0};
long KeyLastPressedTime[]={0,0,0,0,0};
long KeyLastReleasedTime[]={0,0,0,0,0};
u8 isSendKeyLongPressedEvent[]={0,0,0,0,0};
void HandleKey(void)
{
for(u8 i=0;i<KEY_NUM;i++)
{
if(KeyPressed[i])
{
//已经按下
if(CurrentTime-KeyLastPressedTime[i]>50)
{
//按下超过50ms
if(gpio_get_level(KeyPinNum[i]))
{
//松开
if(!isSendKeyLongPressedEvent[i])
{
if(pOnKeyReleased[i])
{
pOnKeyReleased[i]();
}
}
KeyPressed[i]=0;
KeyLastReleasedTime[i]=CurrentTime;
}
else
{
//未松开
if(CurrentTime-KeyLastPressedTime[i]>1000)
{
//超过1000ms
if(!isSendKeyLongPressedEvent[i])
{
//没有触发过长按则触发长按
isSendKeyLongPressedEvent[i]=1;
if(pOnKeyPressedL[i])
{
pOnKeyPressedL[i]();
}
}
}
}
}
} else
{
//未按下
if( !gpio_get_level(KeyPinNum[i])&&(CurrentTime-KeyLastReleasedTime[i]>200))
{
//首次按下
KeyPressed[i]=1;
KeyLastPressedTime[i]=CurrentTime;
isSendKeyLongPressedEvent[i]=0;
if(pOnKeyPressedS[i])
{
pOnKeyPressedS[i]();
}
}
}
}//for
}
void HardwareInit(void)
{
//1.IO
gpio_config_t io_conf;
//disable interrupt
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_HW_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
}
void TaskReadSW1(void *arg)
{
uint32_t io_num;
while (1)
{
vTaskDelay(10 / portTICK_RATE_MS);
}
}
void app_main(){
HardwareInit();
xTaskCreate(TaskReadSW1, "TaskReadSW1", 2048, NULL, 10, NULL);
while(1){
HandleKey();
UpdateCurrentTime();
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}
三、代码解析
1、宏定义按钮在芯片上的位置,笔者的按钮在开发板位置是14、12、0。读者请根据自己按钮在芯片上的位置修改。
#define GPIO_KEY1 14
#define GPIO_KEY2 12
#define GPIO_KEY3 0
2、修改按钮的三个状态函数,根据自己需要修改函数,例如笔者的代码为每次实现一次按钮函数,则display++并且printf打印,因此可直观看出该自定义函数是否运行。
void OnKey1Presseds(void)
{
display1++;
printf("key1presseds:%d\n",display1);
sleep(0.5);
}
void OnKey1Pressedl(void)
{
display2++;
printf("key1pressedl:%d\n",display2);
}
void OnKey1Released(void)
{
display3++;
printf("Key1Released:%d\n",display3);
}
void OnKey2Presseds(void)
{
display4++;
printf("key2presseds:%d\n",display4);
sleep(0.5);
}
void OnKey2Pressedl(void)
{
display5++;
printf("key2pressedl:%d\n",display5);
}
void OnKey2Released(void)
{
display6++;
printf("Key2Released:%d\n",display6);
}
void OnKey3Presseds(void)
{
display7++;
printf("key3presseds:%d\n",display7);
sleep(0.5);
}
void OnKey3Pressedl(void)
{
display8++;
printf("key3pressedl:%d\n",display8);
}
void OnKey3Released(void)
{
display9++;
printf("Key3Released:%d\n",display9);
}
void OnKeyEXTPresseds(void)
{
}
void OnKeyEXTPressedl(void)
{
}
void OnKeyEXTReleased(void)
{
}
void OnKeyEXT2Presseds(void)
{
}
void OnKeyEXT2Pressedl(void)
{
}
void OnKeyEXT2Released(void)
{
}
3、按钮的初始化与处理。在理解了该代码之后可知若实现短按必然实现释放,若想要实现长按则必然提前实现短按,因此如果只是一个按键的处理则只需要修改该按钮的短按函数,若一个按键想要实现两个功能则要修改该按钮的长按与释放函数。
void HandleKey(void)
{
for(u8 i=0;i<KEY_NUM;i++)
{
if(KeyPressed[i])
{
//已经按下
if(CurrentTime-KeyLastPressedTime[i]>50)
{
//按下超过50ms
if(gpio_get_level(KeyPinNum[i]))
{
//松开
if(!isSendKeyLongPressedEvent[i])
{
if(pOnKeyReleased[i])
{
pOnKeyReleased[i]();
}
}
KeyPressed[i]=0;
KeyLastReleasedTime[i]=CurrentTime;
}
else
{
//未松开
if(CurrentTime-KeyLastPressedTime[i]>1000)
{
//超过1000ms
if(!isSendKeyLongPressedEvent[i])
{
//没有触发过长按则触发长按
isSendKeyLongPressedEvent[i]=1;
if(pOnKeyPressedL[i])
{
pOnKeyPressedL[i]();
}
}
}
}
}
} else
{
//未按下
if( !gpio_get_level(KeyPinNum[i])&&(CurrentTime-KeyLastReleasedTime[i]>200))
{
//首次按下
KeyPressed[i]=1;
KeyLastPressedTime[i]=CurrentTime;
isSendKeyLongPressedEvent[i]=0;
if(pOnKeyPressedS[i])
{
pOnKeyPressedS[i]();
}
}
}
}//for
}
void HardwareInit(void)
{
//1.IO
gpio_config_t io_conf;
//disable interrupt
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_HW_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
}
4、时间更新函数
long CurrentTime=0;
void UpdateCurrentTime(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
CurrentTime=tv.tv_sec*1000+tv.tv_usec/1000;
}
5、最简单的main函数:将按钮初始化之后,在while(1)循环里,反复实现HandleKey()函数,因此只要按钮按下,便会打印出相对应的按钮的变量的增加。
void app_main(){
HardwareInit();
xTaskCreate(TaskReadSW1, "TaskReadSW1", 2048, NULL, 10, NULL);
while(1){
HandleKey();
UpdateCurrentTime();
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}