ad-矩阵-io口多按键驱动

按键实现思路

多按键驱动的思路和之前的io单按键,思路类似单按键是判断按键是按下,多按键判断是否有按键按下,按下的是哪个按键号,下面以最近工作用使用的ad按键为例
整个驱动一共4个c文件(键值、扫描、任务、驱动),6个h文件
核心思路是定时器中每10ms扫描一次按键,将按键值传入扫描函数,获得有效按键的按键号和按键状态,抄表将按键号按键状态两个变量转换成一个变量,将这个有效值传入队列,在主函数中出队列,将按键有效值作为参数哦传递给函数指针数组调用对应的任务函数,整个驱动没有使用一个与ic芯片有关的头文件,函数等,十分方便移植(整个驱动的思路来源于之前的几个项目,抄表是杰里的按键驱动,按键扫描代码是自己撸的,队列做数据透传的时候写的),可能程序的效率和代码量不够理想,但整体功能能比较好实现,最后面将会把10个文件全部贴出,附带完整工程下载
在这里插入图片描述

驱动分析:

一、有效键值

主要文件key_ad.c .h
h文件将每个按键对应电压的ad转换值算出来,选用两个键值的中值做作为有效键值判断
c文件,将h文件中的键值作为数组的元素,将获取的按键值和表对比获取获得按键号

#define R_UP       220L     //22K
/* 不同电压对应的ad值 12bit adc */
#define ADC_33   (4096)		//VCC
#define ADC_30   (3680)     //220K
#define ADC_27   (3357)     //100K
#define ADC_23   (2860)     //51K
#define ADC_20   (2450)     //33K
#define ADC_17   (2120)     //24K
#define ADC_13   (1610)     //15K
#define ADC_10   (1210)     //9.1K
#define ADC_07   (915)     //6.2K
#define ADC_03   (490)     //3K
#define ADC_00   (0)

/* key voltage threshold */
#define AD_NOKEY        ((ADC_33 + ADC_30)/2)
#define AD_KEY_0		((ADC_30 + ADC_27)/2)
#define AD_KEY_1		((ADC_27 + ADC_23)/2)
#define AD_KEY_2		((ADC_23 + ADC_20)/2)
#define AD_KEY_3		((ADC_20 + ADC_17)/2)
#define AD_KEY_4		((ADC_17 + ADC_13)/2)
#define AD_KEY_5		((ADC_13 + ADC_10)/2)
#define AD_KEY_6		((ADC_10 + ADC_07)/2)
#define AD_KEY_7		((ADC_07 + ADC_03)/2)
#define AD_KEY_8		((ADC_03 + ADC_00)/2)

void get_key_adc_address(u16* _address);
KEY_NUMBER_U get_current_key_number(void);
/////////////////////////////////////////////////////////////////////////
/* c文件 */
#define KEY_SIZE (KEY_NUMBER - 1)
const static u16 ad_key_table[KEY_SIZE] = {
    AD_KEY_0, AD_KEY_1, AD_KEY_2, 
    AD_KEY_3, AD_KEY_4, AD_KEY_5, 
    AD_KEY_6, AD_KEY_7, AD_KEY_8,
};

static u16* s_ad_key_value;
/* 初始化时将按键的ad值地址传进来,用指针变量存起来,就可以不用包含ad值的头文件了,方便移植 */
void get_key_adc_address(u16* _address)
{
    s_ad_key_value = _address;
}
KEY_NUMBER_U get_current_key_number(void)
{
    u8 l_number = KEY_NONE;
    if (*s_ad_key_value > AD_NOKEY){
        return KEY_NONE;  
    }
    for (l_number = 0; l_number < KEY_SIZE; l_number++){	
        if (*s_ad_key_value > ad_key_table[l_number]){
            break; 
        }      
    }
    return (KEY_NUMBER_U)(KEY_SIZE - l_number);   
}

二、键值扫描

这部分较为简单,主要文件key_scan.c .h 。将上一步扫描的键值传入key_scan中,基本是在io单按键的基础稍作修改的

void key_scan(KEY_SCAN_S *_key)
{
    _key->value = NO_KEY;
    _key->type = KEY_NO_PRESS; 
    if (_key->cur_key == NO_KEY){
        switch (_key->status){
        case KEY_NO_PRESS:
            
            break;
        case KEY_DOWN:
            
            break;
        case KEY_SHORT:
            _key->type = KEY_SHORT;
            break;
        case KEY_LONG:
        
            break;
        case KEY_HOLD:
            _key->type = KEY_HOLD_UP;
            break;
        default:
            break;
        }
        _key->cnt = 0;
        _key->status = KEY_NO_PRESS;
    }else{
        /* 上次的按值有效,但和这次不同 */
        if ((NO_KEY != _key->last_key)&&(_key->last_key != _key->cur_key)){
            /* 这次按键比上次小,认为是一个误触按键*/
            if (_key->cur_key <= _key->last_key){
                _key->last_key = _key->cur_key;
                _key->cnt = 0;
                _key->status = KEY_NO_PRESS;
                return;   //异常退出 
            }
            /* 实际测试的时候抬手的一瞬间内,按键抖动,导致最后一次传入一个比当前键值大的键值
                如果认为是异常则按键扫描识别率低,所以这次按键比上次大,认为是一个松手按键 */
            if (KEY_SHORT == _key->status){
                _key->type = KEY_SHORT;
            }else if (KEY_HOLD == _key->status){
                _key->type = KEY_HOLD_UP;
            }
            _key->cnt = 0;
            _key->status = KEY_NO_PRESS;
        }
        _key->cnt++;
        switch (_key->status){
        case KEY_NO_PRESS:
            _key->status = KEY_DOWN;
            break;
        case KEY_DOWN:
            if (_key->cnt >= KEY_BASE_CNT) {        //长按
                _key->status = KEY_SHORT;
            }
            break;    
        case KEY_SHORT:
            if (_key->cnt >= KEY_LONG_CNT) {        //长按
                _key->status = KEY_LONG;
                _key->type = KEY_LONG;
            }
            break;
        case KEY_LONG:
            if (_key->cnt >= (KEY_LONG_CNT + KEY_HOLD_CNT)) {    //连按
                _key->status = KEY_HOLD;
                _key->type = KEY_HOLD;
                _key->cnt = KEY_LONG_CNT;
            }
            break;
        case KEY_HOLD:
            if (_key->cnt >= (KEY_LONG_CNT + KEY_HOLD_CNT)) {    //连按
                _key->type = KEY_HOLD;
                _key->cnt = KEY_LONG_CNT;
            }
            break;
        default:
            break;
        } 
    }
    if (KEY_NO_PRESS != _key->type){
        _key->number = _key->last_key;
       _key->value = ((_key->type << 5)|(_key->number & 0x1f));     //高3位代表按键状态,低5位代表键值
    }
    _key->last_key = _key->cur_key;
}

三、按键处理

按键处理经过上一步,就已经获得了有效的键值和按键类型,开始按键处理 主要文件 key_device.c .h
按键初始化要传入按键ad值的地址,初始化一个fifo队列,不想用队列也是可以的,但是要扫描完立马进行按键任务处理

/* 为了方便抄表,NO_PRESS不是0,初始化赋值 */
static KEY_SCAN_S s_key = {KEY_NO_PRESS,0,0,0,0,0,0,0};
static QUEUE_ELEMENT_S s_queue;
/* 传入adc地址,初始化队列 */
static void task_key_init(u16* _key_adc_address)
{
	get_key_adc_address(_key_adc_address);	
    init_queue(&s_queue);
}
/*
	按键扫描,把消息传入队列
*/
static void task_key_scan(void)
{
    u8 l_msg = NO_MSG;
    s_key.cur_key = get_current_key_number();    /* 获得按键值 */
    key_scan(&s_key);				    /* 传入扫描,获取按键结果 */
    if(KEY_NONE != s_key.value){	    /* 将按键结果传入队列 */
    	/* 抄表获取对应的按键变量 */
        l_msg = key_msg_buff[s_key.type][s_key.number];
        if (NO_MSG != l_msg){
            in_queue_fifo(&s_queue, l_msg);
        }
    }
}

四、按键任务调用

上面三步完成了按键的扫描,接下来就是要做按键的功能函数了,个人喜欢将按键类型也分成函数,如果不喜欢可改用按键号函数,键类型传参进去,这里使用了函数指针数组来实现32个函数的调用,使得整个任务调用变得简洁,如果芯片资源紧张,也可以用switch来处理感觉代码庞大,主要文件 key_task.c .h

/*
	消息出队列,调用相应的功能函数
*/
static void task_key_deal(void)
{
    u8 l_smg = NO_MSG;
    /* 按键消息出队列 */
    if (1 == out_queue(&s_queue, &l_smg)){
        /* 超出了最大任务数,退出防止指针数组访问越界 */
        if (l_smg >= TASK_SIZE){
            printf("key_task error\r\n");
            return ;
        }
        key_task[l_smg]();/* 调用按键功能函数指针 */
        //key_task[s_key.number](s_key.type);
    } 
}
/* 按键函数的类型 */
typedef void (*const KEY_TASK_CB)(void);
extern KEY_TASK_CB key_task[TASK_SIZE];
/* 函数指针声明为常量初始化之后不允许改变 */
const KEY_TASK_CB key_task[TASK_SIZE]  = {
	[KEY0_SHORT] = task_key0_short,
	[KEY0_LONG] = task_key0_long, 
	[KEY0_HOLD] = task_key0_hold, 
	[KEY0_HOLD_UP] = task_key0_hold_up,
	/* 还有20多个元素没复制 */	
};
/*---------------------------key0------------------------------------*/

static void task_key0_short(void)
{
	printf("task_key0_short\r\n");
//	read_64bit_uid(test_id);	
}
static void task_key0_long(void)
{
	printf("task_key0_long\r\n");
}
static void task_key0_hold(void)
{
	printf("task_key0_hold\r\n");
}
static void task_key0_hold_up(void)
{
	printf("task_key0_hold_up\r\n");
}

五、main函数调用

通过队列,将扫描和处理分开,按键处理放在主函数中,主函数即使有很多阻塞操作也不会影响按键处理

int main(void)
{
	system_init();
	while (1){
		g_key.deal();
	}
	return 1;/* never do there */
}

void TIM6_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET){
    TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
	g_adc.finsh_detect();
	g_key.scan();
  }
}

所有文件源码

有需要可以直接下载完整工程移植到stm32上测试,本人用的ic是国产cortex-m0内核ic。

key_api.h

#ifndef __KEY_API_H
#define __KEY_API_H

//自行定义消息在
typedef enum{
    KEY0_SHORT,
    KEY0_LONG,
    KEY0_HOLD,
    KEY0_HOLD_UP,
    /////////
    KEY1_SHORT,
    KEY1_LONG,
    KEY1_HOLD,
    KEY1_HOLD_UP,
    /////////
    KEY2_SHORT,
    KEY2_LONG,
    KEY2_HOLD,
    KEY2_HOLD_UP,
    /////////
    KEY3_SHORT,
    KEY3_LONG,
    KEY3_HOLD,
    KEY3_HOLD_UP,
    /////////
    KEY4_SHORT,
    KEY4_LONG,
    KEY4_HOLD,
    KEY4_HOLD_UP,
    /////////
    KEY5_SHORT,
    KEY5_LONG,
    KEY5_HOLD,
    KEY5_HOLD_UP,
    /////////
    KEY6_SHORT,
    KEY6_LONG,
    KEY6_HOLD,
    KEY6_HOLD_UP,
    /////////
    KEY7_SHORT,
    KEY7_LONG,
    KEY7_HOLD,
    KEY7_HOLD_UP,
    
    KEY_TASK_MAX,
    
    NO_MSG = 0xff,
}KEY_MSG_U;
/////////////////////////////////////////////////////////////
#define KEY_STATUS_SHORT	\
        /* key0 */KEY0_SHORT,\
        /* key1 */KEY1_SHORT,\
        /* key2 */KEY2_SHORT,\
        /* key3 */KEY3_SHORT,\
        /* key4 */KEY4_SHORT,\
        /* key5 */KEY5_SHORT,\
        /* key6 */KEY6_SHORT,\
        /* key7 */KEY7_SHORT,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////
#define KEY_STATUS_DOUBLE   \
        /* key0 */NO_MSG,\
        /* key1 */NO_MSG,\
        /* key2 */NO_MSG,\
        /* key3 */NO_MSG,\
        /* key4 */NO_MSG,\
        /* key5 */NO_MSG,\
        /* key6 */NO_MSG,\
        /* key7 */NO_MSG,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////
#define KEY_STATUS_THREE    \
        /* key0 */NO_MSG,\
        /* key1 */NO_MSG,\
        /* key2 */NO_MSG,\
        /* key3 */NO_MSG,\
        /* key4 */NO_MSG,\
        /* key5 */NO_MSG,\
        /* key6 */NO_MSG,\
        /* key7 */NO_MSG,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////
#define KEY_STATUS_LONG \
        /* key0 */KEY0_LONG,\
        /* key1 */KEY1_LONG,\
        /* key2 */KEY2_LONG,\
        /* key3 */KEY3_LONG,\
        /* key4 */KEY4_LONG,\
        /* key5 */KEY5_LONG,\
        /* key6 */KEY6_LONG,\
        /* key7 */KEY7_LONG,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////
#define KEY_STATUS_HOLD \
        /* key0 */KEY0_HOLD,\
        /* key1 */KEY1_HOLD,\
        /* key2 */KEY2_HOLD,\
        /* key3 */KEY3_HOLD,\
        /* key4 */KEY4_HOLD,\
        /* key5 */KEY5_HOLD,\
        /* key6 */KEY6_HOLD,\
        /* key7 */KEY7_HOLD,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////	
#define KEY_STATUS_HOLD_UP  \
        /* key0 */KEY0_HOLD_UP,\
        /* key1 */KEY1_HOLD_UP,\
        /* key2 */KEY2_HOLD_UP,\
        /* key3 */KEY3_HOLD_UP,\
        /* key4 */KEY4_HOLD_UP,\
        /* key5 */KEY5_HOLD_UP,\
        /* key6 */KEY6_HOLD_UP,\
        /* key7 */KEY7_HOLD_UP,\
        /* key8 */NO_MSG,\
        /* key9 */NO_MSG
/////////////////////////////////////////////////////////////
#endif

key_head.h

#ifndef __KEY_HEAD_H
#define __KEY_HEAD_H

#define KEY_NUMBER 10
// #define TASK_SIZE 16
//typedef enum{
//    AD_KEY,
//    MATRIX_KEY,
//    IO_KEY,
//}KEY_TYPE_U;

// #define KEY_TYPE MATRIX_KEY

typedef enum{
    KEY_0 = 0,
    KEY_1,
    KEY_2,
    KEY_3,
    KEY_4,
    KEY_5,
    KEY_6,
    KEY_7,
    KEY_8,
    KEY_9,
    KEY_NONE = 0xff,
}KEY_NUMBER_U;
#endif // !__KEY_HEAD_H

key_ad.c

#include "key_ad.h"
/* 最后一个键值不用判断,只要按键有效,扫描一轮,提前退出 */
#define KEY_SIZE (KEY_NUMBER - 1)
const static u16 ad_key_table[KEY_SIZE] = {
    AD_KEY_0, AD_KEY_1, AD_KEY_2, 
    AD_KEY_3, AD_KEY_4, AD_KEY_5, 
    AD_KEY_6, AD_KEY_7, AD_KEY_8,
};

static u16* s_ad_key_value;

void get_key_adc_address(u16* _address)
{
    s_ad_key_value = _address;
}
KEY_NUMBER_U get_current_key_number(void)
{
    u8 l_number = KEY_NONE;
    if (*s_ad_key_value > AD_NOKEY){
        return KEY_NONE;  
    }
    for (l_number = 0; l_number < KEY_SIZE; l_number++){	
        if (*s_ad_key_value > ad_key_table[l_number]){
            break; 
        }      
    }
    return (KEY_NUMBER_U)(KEY_SIZE - l_number);   
}

key_ad.h

#ifndef __KEY_AD_H
#define __KEY_AD_H
#include "user_typedef.h"
#include "key_head.h"

#define R_UP       220L     //22K

// #define ADC_33   (1024L)		//VCC
// #define ADC_33   (4096L)		//VCC
// #define ADC_30   (ADC_33*2200L/(2200L + R_UP))     //220K 3700
// #define ADC_27   (ADC_33*1000L/(1000L + R_UP))     //100K 3357
// #define ADC_23   (ADC_33*510L /(510L  + R_UP))     //51K  2860
// #define ADC_20   (ADC_33*330L /(330L  + R_UP))     //33K  2450
// #define ADC_17   (ADC_33*240L /(240L  + R_UP))     //24K  2120
// #define ADC_13   (ADC_33*150L /(150L  + R_UP))     //15K  1610
// #define ADC_10   (ADC_33*91L  /(91L   + R_UP))     //9.1K 1210
// #define ADC_07   (ADC_33*62L  /(62L   + R_UP))     //6.2K 915
// #define ADC_03   (ADC_33*30L  /(30L   + R_UP))     //3K  490
// #define ADC_00   (0)

#define ADC_33   (4096)		//VCC
#define ADC_30   (3680)     //220K
#define ADC_27   (3357)     //100K
#define ADC_23   (2860)     //51K
#define ADC_20   (2450)     //33K
#define ADC_17   (2120)     //24K
#define ADC_13   (1610)     //15K
#define ADC_10   (1210)     //9.1K
#define ADC_07   (915)     //6.2K
#define ADC_03   (490)     //3K
#define ADC_00   (0)

/* key voltage threshold */
#define AD_NOKEY        ((ADC_33 + ADC_30)/2)
#define AD_KEY_0		((ADC_30 + ADC_27)/2)
#define AD_KEY_1		((ADC_27 + ADC_23)/2)
#define AD_KEY_2		((ADC_23 + ADC_20)/2)
#define AD_KEY_3		((ADC_20 + ADC_17)/2)
#define AD_KEY_4		((ADC_17 + ADC_13)/2)
#define AD_KEY_5		((ADC_13 + ADC_10)/2)
#define AD_KEY_6		((ADC_10 + ADC_07)/2)
#define AD_KEY_7		((ADC_07 + ADC_03)/2)
#define AD_KEY_8		((ADC_03 + ADC_00)/2)

void get_key_adc_address(u16* _address);
KEY_NUMBER_U get_current_key_number(void);

#endif // !__KEY_AD_H

key_scan.c

#include "key_scan.h"

/* 将键值和类型抄表转换成一个变量 */
const u8 key_msg_buff[6][10] = {
    {KEY_STATUS_SHORT},
    {KEY_STATUS_DOUBLE},
    {KEY_STATUS_THREE},
    {KEY_STATUS_LONG},
    {KEY_STATUS_HOLD},
    {KEY_STATUS_HOLD_UP},
};
void key_scan(KEY_SCAN_S *_key)
{
    _key->value = NO_KEY;
    _key->type = KEY_NO_PRESS; 
    if (_key->cur_key == NO_KEY){
        switch (_key->status){
        case KEY_NO_PRESS:
            
            break;
        case KEY_DOWN:
            
            break;
        case KEY_SHORT:
            _key->type = KEY_SHORT;
            break;
        case KEY_LONG:
        
            break;
        case KEY_HOLD:
            _key->type = KEY_HOLD_UP;
            break;
        default:
            break;
        }
        _key->cnt = 0;
        _key->status = KEY_NO_PRESS;
    }else{
        /* 上次的按值有效,但和这次不同 */
        if ((NO_KEY != _key->last_key)&&(_key->last_key != _key->cur_key)){
            /* 这次按键比上次小,认为是一个误触按键*/
            if (_key->cur_key <= _key->last_key){
                _key->last_key = _key->cur_key;
                _key->cnt = 0;
                _key->status = KEY_NO_PRESS;
                return;   //异常退出 
            }
            /* 实际测试的时候抬手的一瞬间内,按键抖动,导致最后一次传入一个比当前键值大的键值
                如果认为是异常则按键扫描识别率低,所以这次按键比上次大,认为是一个松手按键 */
            if (KEY_SHORT == _key->status){
                _key->type = KEY_SHORT;
            }else if (KEY_HOLD == _key->status){
                _key->type = KEY_HOLD_UP;
            }
            _key->cnt = 0;
            _key->status = KEY_NO_PRESS;
        }
        _key->cnt++;
        switch (_key->status){
        case KEY_NO_PRESS:
            _key->status = KEY_DOWN;
            break;
        case KEY_DOWN:
            if (_key->cnt >= KEY_BASE_CNT) {        //长按
                _key->status = KEY_SHORT;
            }
            break;    
        case KEY_SHORT:
            if (_key->cnt >= KEY_LONG_CNT) {        //长按
                _key->status = KEY_LONG;
                _key->type = KEY_LONG;
            }
            break;
        case KEY_LONG:
            if (_key->cnt >= (KEY_LONG_CNT + KEY_HOLD_CNT)) {    //连按
                _key->status = KEY_HOLD;
                _key->type = KEY_HOLD;
                _key->cnt = KEY_LONG_CNT;
            }
            break;
        case KEY_HOLD:
            if (_key->cnt >= (KEY_LONG_CNT + KEY_HOLD_CNT)) {    //连按
                _key->type = KEY_HOLD;
                _key->cnt = KEY_LONG_CNT;
            }
            break;
        default:
            break;
        } 
    }
    if (KEY_NO_PRESS != _key->type){
        _key->number = _key->last_key;
       _key->value = ((_key->type << 5)|(_key->number & 0x1f));     //高3位代表按键状态,低5位代表键值
    }
    _key->last_key = _key->cur_key;
} 

key_scan.h

#ifndef __KEY_SCAN_H
#define __KEY_SCAN_H

#include "key_api.h"
#include "user_typedef.h"

/* 按键的8个状态 */
typedef enum{
    KEY_SHORT = 0,	/* 短按 */
    KEY_DOUBLE,		  /* 双击 */
    KEY_THREE,		  /* 三击 */
    KEY_LONG,		    /* 长按 */
    KEY_HOLD,		    /* 保持 */
    KEY_HOLD_UP,    /* 抬起 */
    KEY_NO_PRESS,   /* 没有按下 */
    KEY_DOWN,       /* 按键按下 */
}KEY_STATE_U;
/* 按键的扫描使用的结构体 */
typedef struct{
  //scan
  u8 status;    /* 按键状态 */
  u8 cur_key;   /* 当前键值 */
  u8 last_key;  /* 上次键值 */
  u8 cnt;       /* 状态计数 */
  u8 press_flag;/* 复按flag,用于扫描多按 */
  //value
  u8 value;     /* 按键值,将number和type整和一个变量 */
  u8 number;    /* 有效键值 */
  u8 type ;     /* 有效按键类型 */
}KEY_SCAN_S;

extern const u8 key_msg_buff[6][10];

void key_scan(KEY_SCAN_S *_key);

#define KEY_BASE_CNT  3      /* 按键消抖 */
#define KEY_LONG_CNT  100   /* 长按触发 1000ms */
#define KEY_HOLD_CNT  50    /* 保持触发时长 500ms */
#define KEY_SHORT_CNT 7
#define KEY_DOUBLE_CNT 35   /* 连按识别350ms */
#define KEY_REPETE_CNT 35

#define NO_KEY        0xff

#endif

key_decive.c

#include "key_drive.h"
#include "key_scan.h"
#include "queue.h"
#include "key_task.h"
#include "key_ad.h"

#include "usart.h"
// #include "key_matrix.h"
// #include "key_io.h"
/* 按键类型选择 */
// #if (KEY_TYPE == AD_KEY)
// #include "key_ad.h"
// #elif (KEY_TYPE == MATRIX_KEY)
// #include "key_matrix.h"
// #elif (KEY_TYPE == IO_KEY)
// #include "key_io.h"
// #endif


static void task_key_init(u16* _key_adc_address);
static void task_key_scan(void);
static void task_key_deal(void);

static KEY_SCAN_S s_key = {KEY_NO_PRESS,0,0,0,0,0,0,0};
static QUEUE_ELEMENT_S s_queue;

KEY_S g_key ={
    .init = task_key_init,
    .scan = task_key_scan,
    .deal = task_key_deal,
};
/*
	按键io初始化 队列初始化
*/
static void task_key_init(u16* _key_adc_address)
{
	get_key_adc_address(_key_adc_address);	
    init_queue(&s_queue);
}
/*
	按键扫描,把消息传入队列
*/
static void task_key_scan(void)
{
    u8 l_msg = NO_MSG;
    s_key.cur_key = get_current_key_number();    /* 获得按键值 */
    key_scan(&s_key);				    /* 传入扫描,获取按键结果 */
    if(KEY_NONE != s_key.value){	    /* 将按键结果传入队列 */
        l_msg = key_msg_buff[s_key.type][s_key.number];
        if (NO_MSG != l_msg){
            in_queue_fifo(&s_queue, l_msg);
        }
    }
}
/*
	消息出队列,调用相应的功能函数
*/
static void task_key_deal(void)
{
    u8 l_smg = NO_MSG;
    /* 按键消息出队列 */
    if (1 == out_queue(&s_queue, &l_smg)){
        /* 超出了最大任务数,退出防止指针数组访问越界 */
        if (l_smg >= TASK_SIZE){
            printf("key_task error\r\n");
            return ;
        }
        key_task[l_smg]();/* 调用按键功能函数指针 */
//        key_task[s_key.number](s_key.type);
    } 
}

key_deceive.h

#ifndef __KEY_DRIVE_H
#define __KEY_DRIVE_H
#include "key_head.h"
#include "user_typedef.h"
typedef struct key{
    // void (*init)(void);
    void (*const init)(u16* _address);
    void (*const scan)(void);
    void (*const deal)(void);
}KEY_S;

extern KEY_S g_key;

#endif /* __KEY_DRIVE_H */

key_task.c

#include "key_task.h"
#include "user_typedef.h"
#include "key_api.h"
#include "usart.h"
//#include "flash.h"
static void task_key0_short(void);
static void task_key0_long(void);
static void task_key0_hold(void);
static void task_key0_hold_up(void);

static void task_key1_short(void);
static void task_key1_long(void);
static void task_key1_hold(void);
static void task_key1_hold_up(void);

static void task_key2_short(void);
static void task_key2_long(void);
static void task_key2_hold(void);
static void task_key2_hold_up(void);

static void task_key3_short(void);
static void task_key3_long(void);
static void task_key3_hold(void);
static void task_key3_hold_up(void);

static void task_key4_short(void);
static void task_key4_long(void);
static void task_key4_hold(void);
static void task_key4_hold_up(void);

static void task_key5_short(void);
static void task_key5_long(void);
static void task_key5_hold(void);
static void task_key5_hold_up(void);

static void task_key6_short(void);
static void task_key6_long(void);
static void task_key6_hold(void);
static void task_key6_hold_up(void);

static void task_key7_short(void);
static void task_key7_long(void);
static void task_key7_hold(void);
static void task_key7_hold_up(void);

/* 函数指针声明为常量初始化之后不允许改变 */
const KEY_TASK_CB key_task[TASK_SIZE] = {
	[KEY0_SHORT] = task_key0_short,
	[KEY0_LONG] = task_key0_long, 
	[KEY0_HOLD] = task_key0_hold, 
	[KEY0_HOLD_UP] = task_key0_hold_up,

	[KEY1_SHORT] = task_key1_short,
	[KEY1_LONG] = task_key1_long,
	[KEY1_HOLD] = task_key1_hold, 
	[KEY1_HOLD_UP] = task_key1_hold_up, 

	[KEY2_SHORT] = task_key2_short,
	[KEY2_LONG] = task_key2_long, 
	[KEY2_HOLD] = task_key2_hold, 
	[KEY2_HOLD_UP] = task_key2_hold_up,

	[KEY3_SHORT] = task_key3_short,
	[KEY3_LONG] = task_key3_long, 
	[KEY3_HOLD] = task_key3_hold,
	[KEY3_HOLD_UP] = task_key3_hold_up, 

	[KEY4_SHORT] = task_key4_short,
	[KEY4_LONG] = task_key4_long, 
	[KEY4_HOLD] = task_key4_hold,
	[KEY4_HOLD_UP] = task_key4_hold_up,

	[KEY5_SHORT] = task_key5_short,
	[KEY5_LONG] = task_key5_long, 
	[KEY5_HOLD] = task_key5_hold,
	[KEY5_HOLD_UP] = task_key5_hold_up,

	[KEY6_SHORT] = task_key6_short,
	[KEY6_LONG] = task_key6_long, 
	[KEY6_HOLD] = task_key6_hold,
	[KEY6_HOLD_UP] = task_key6_hold_up,

	[KEY7_SHORT] = task_key7_short,
	[KEY7_LONG] = task_key7_long, 
	[KEY7_HOLD] = task_key7_hold,
	[KEY7_HOLD_UP] = task_key7_hold_up,
};
uint8_t test_id[8];
/*---------------------------key0------------------------------------*/

static void task_key0_short(void)
{
	printf("task_key0_short\r\n");
//	read_64bit_uid(test_id);	
}
static void task_key0_long(void)
{
	printf("task_key0_long\r\n");
}
static void task_key0_hold(void)
{
	printf("task_key0_hold\r\n");
}
static void task_key0_hold_up(void)
{
	printf("task_key0_hold_up\r\n");
}
/*---------------------------key1------------------------------------*/
static void task_key1_short(void)
{
	printf("task_key1_short\r\n");
}
static void task_key1_long(void)
{
	printf("task_key1_long\r\n");
}
static void task_key1_hold(void)
{
	printf("task_key1_hold\r\n");
}
static void task_key1_hold_up(void)
{
	printf("task_key1_hold_up\r\n");
}
/*---------------------------key2------------------------------------*/
static void task_key2_short(void)
{
	printf("task_key2_short\r\n");
}
static void task_key2_long(void)
{
	printf("task_key2_long\r\n");
}
static void task_key2_hold(void)
{
	printf("task_key2_hold\r\n");
}
static void task_key2_hold_up(void)
{
	printf("task_key2_hold_up\r\n");
}
/*---------------------------key3------------------------------------*/
static void task_key3_short(void)
{
	printf("task_key3_short\r\n");
}
static void task_key3_long(void)
{
	printf("task_key3_long\r\n");
}
static void task_key3_hold(void)
{
	printf("task_key3_hold\r\n");
}
static void task_key3_hold_up(void)
{
	printf("task_key3_hold_up\r\n");
}
/*---------------------------key4------------------------------------*/
static void task_key4_short(void)
{
	printf("task_key4_short\r\n");
}
static void task_key4_long(void)
{
	printf("task_key4_long\r\n");
}
static void task_key4_hold(void)
{
	printf("task_key4_hold\r\n");
}
static void task_key4_hold_up(void)
{
	printf("task_key4_hold_up\r\n");
}
/*---------------------------key5------------------------------------*/
static void task_key5_short(void)
{
	printf("task_key5_short\r\n");
}
static void task_key5_long(void)
{
	printf("task_key5_long\r\n");
}
static void task_key5_hold(void)
{
	printf("task_key5_hold\r\n");
}
static void task_key5_hold_up(void)
{
	printf("task_key5_hold_up\r\n");
}
/*---------------------------key6------------------------------------*/
static void task_key6_short(void)
{
	printf("task_key6_short\r\n");
}
static void task_key6_long(void)
{
	printf("task_key6_long\r\n");
}
static void task_key6_hold(void)
{
	printf("task_key6_hold\r\n");
}
static void task_key6_hold_up(void)
{
	printf("task_key6_hold_up\r\n");
}
/*---------------------------key7------------------------------------*/
static void task_key7_short(void)
{
	printf("task_key7_short\r\n");
}
static void task_key7_long(void)
{
	printf("task_key7_long\r\n");
}
static void task_key7_hold(void)
{
	printf("task_key7_hold\r\n");
}
static void task_key7_hold_up(void)
{
	printf("task_key7_hold_up\r\n");
}

key_task.h

#ifndef __key_task_H
#define __key_task_H

#define TASK_SIZE 32
/* 按键函数的类型 */
typedef void (*const KEY_TASK_CB)(void);
extern KEY_TASK_CB key_task[TASK_SIZE];

#endif

队列

c语言数组实现队列

猜你喜欢

转载自blog.csdn.net/lala0903/article/details/105649060
今日推荐