单片机按键驱动,包括:长按统计,次数统计

 主程序:

#include "bsp_key.h"


static KEY_T s_tBtn[KEY_COUNT];

int main(void)
{
	
    uint8_t key_val = 0;

    for( ;; )
    {
        key_val = bsp_KeyScan();

        if(key_val)
        {
            LED_ON();
            vTaskDelay(50);
            LED_OFF();
            printf("KEY:%2x\r\n",key_val);
        }

        vTaskDelay(10);        //10s
    }
	
}

(1)按键GPIO初始化,给按键赋缺省值

void key_gpio_init(void)
{
	
	//PF14(UP),PC14(DOWN),PA0LEFTP),PF13(RIGHT),PF14(OK)

	rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOF);
	rcu_periph_clock_enable(RCU_GPIOG);          //LED1

    /* configure LEDs GPIO port */ 
    gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
    gpio_init(GPIOC, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);	
	
	gpio_init(GPIOG, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);    //LED1

	bsp_InitKeyVar();
}


static void bsp_InitKeyVar(void)
{
    uint8_t i;

    /* 给每个按键结构体成员变量赋一组缺省值 */
    for (i = 0; i < KEY_COUNT; i++)
    {
        s_tBtn[i].Wait=0;
        s_tBtn[i].Count=0;
        s_tBtn[i].LongState=0;
    }

    /* 判断按键按下的函数 */
    s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
    s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
    s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
    s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
    s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
}

(2)查询,并返回按键

uint8_t  bsp_KeyScan(void)
{
    uint8_t i;

    for (i = 0; i < KEY_COUNT; i++)
    {
        if(bsp_DetectKey(i))
        {
            return 1+i;
        }
    }
    return 0;
}

uint8_t bsp_DetectKey(uint8_t x)
{

    if(s_tBtn[x].IsKeyDownFunc())
    {
        vTaskDelay(10);
        if(s_tBtn[x].IsKeyDownFunc())
        {
            s_tBtn[x].Wait =1;
            s_tBtn[x].Count++;
            if(s_tBtn[x].Count>20)
            {
                s_tBtn[x].LongState=1;
                s_tBtn[x].Count=0;
            }
            else
            {
                s_tBtn[x].LongState=0;
            }
        }
    }
    if(!s_tBtn[x].IsKeyDownFunc())
    {
        s_tBtn[x].Count=0;
        s_tBtn[x].LongState=0;
        if(s_tBtn[x].Wait ==1)
        {
            s_tBtn[x].Wait =0;
            return 1;
        }
    }
    return 0;
}

static uint8_t IsKeyDown1(void)
{
    return KEY_DOWN_Val;
}

static uint8_t IsKeyDown2(void)
{
    return KEY_UP_Val;
}

static uint8_t IsKeyDown3(void)
{
    return KEY_LEFT_Val;
}

static uint8_t IsKeyDown4(void)
{
    return KEY_RIGHT_Val;
}

static uint8_t IsKeyDown5(void)
{
    return KEY_OK_Val;
}

(3)#include "bsp_key.h" 文件

typedef struct
{
    /* 下面是一个函数指针,指向判断按键手否按下的函数 */
    uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */

    uint8_t     LongState;      //  1:长按状态
    uint8_t     State;          //  1:弹起		0:按下
    uint8_t     Wait;           //  1:按下后等待弹起
    uint16_t    Count;          /* 计数器 */

}KEY_T;

void key_gpio_init(void);
uint8_t  bsp_KeyScan(void);
uint8_t bsp_DetectKey(uint8_t );
static void bsp_InitKeyVar(void);
	
#define KEY_COUNT           5
#define LED_ON()     gpio_bit_set(GPIOG, GPIO_PIN_11);
#define LED_OFF()    gpio_bit_reset(GPIOG, GPIO_PIN_11);

#define KEY_UP_Val      gpio_input_bit_get(GPIOF, GPIO_PIN_14)
#define KEY_DOWN_Val    gpio_input_bit_get(GPIOC, GPIO_PIN_13)
#define KEY_LEFT_Val    gpio_input_bit_get(GPIOA, GPIO_PIN_0)
#define KEY_RIGHT_Val   gpio_input_bit_get(GPIOF, GPIO_PIN_13)
#define KEY_OK_Val      gpio_input_bit_get(GPIOF, GPIO_PIN_15)

本次按键更新

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于51单片机的独立按键双击后按的驱动代码,供参考: ``` #include <reg51.h> #define KEY P3_3 // 定义按键连接的引脚 sbit LED = P1_0; // 定义 LED 连接的引脚 unsigned char key_buf = 0; // 按键缓存 unsigned char key_count = 0; // 按键计数器 unsigned char key_flag = 0; // 按键标志位 void delay_ms(unsigned int n); // 延时函数 void main() { KEY = 1; // 设置按键为输入模式 while(1) { if(KEY == 0) // 检测按键是否按下 { delay_ms(10); // 延时去抖动 if(KEY == 0) // 再次检测按键是否按下 { key_buf++; // 储存按键按下的次数 key_flag = 1; // 标记按键按下 } while(!KEY); // 等待按键释放 } if(key_flag) // 如果按键被按下 { delay_ms(10); // 延时去抖动 if(KEY == 0) // 如果按键没有释放 { key_count++; // 计数器加 1 if(key_count >= 100) // 如果按下超过 1 秒 { LED = 1; // 点亮 LED } } else // 如果按键释放了 { if(key_buf == 1) // 如果只按了一次 { LED = !LED; // 点亮 LED } else if(key_buf == 2) // 如果按了两次 { LED = 0; // 熄灭 LED } key_buf = 0; // 清空按键缓存 key_count = 0; // 清空计数器 key_flag = 0; // 清除按键标志位 } } } } void delay_ms(unsigned int n) { unsigned int i, j; for(i = 0; i < n; i++) { for(j = 0; j < 125; j++); } } ``` 该代码实现了以下功能: - 检测独立按键的按下和释放; - 记录按键的按下次数; - 判断按键是单击还是双击; - 判断按键是否按; - 在 LED 上进行相应操作。 需要注意的是,该代码中的延时函数可能需要根据实际情况进行调整。同时,该代码只能处理一个按键,如果需要处理多个按键,需要进行相应的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值