STM32 ADC按键

主控stm32f103vet6,使用adc1的通道0即A0口,实验目的,一个GPIO检测11个按键的多种状态,按下状态,按下释放状态,长按状态,长按释放状态,一直按状态,5种状态检测。

原理图如上图,采用电阻分压,adc采集到的不同的电压值判断是哪一个按键按下。

 效果如图下图:

0代表第一个按键,1代表按下 2代表按下释放,3代表长按,4代表按着不松开,5代表长按释放
//第一次按下立马释放

[21:45:07.441]收←◆adc_key: 0,1        //检测到按下

[21:45:07.582]收←◆adc_key: 0,2        //检测到释放

//第二次按下1.5s释放

[21:45:08.645]收←◆adc_key: 0,1        //检测到按下

[21:45:09.446]收←◆adc_key: 0,3        //检测到长按

[21:45:09.757]收←◆adc_key: 0,5        //检测到长按后释放

//第三次按下4s释放

[21:45:11.939]收←◆adc_key: 0,1        //检测到按下

[21:45:12.739]收←◆adc_key: 0,3        //检测到长按

[21:45:13.241]收←◆adc_key: 0,4        //检测到一直按

[21:45:13.742]收←◆adc_key: 0,4        //检测到一直按

[21:45:14.244]收←◆adc_key: 0,4        //检测到一直按

[21:45:14.356]收←◆adc_key: 0,5        //检测到长按后释放

adc_key.h

#ifndef __ADC_KEY_H__
#define __ADC_KEY_H__
#include "stm32f10x.h"

#define ADC_KEY_EN //adc按键使能
#ifdef ADC_KEY_EN

extern uint16_t ADCKEYSCANTIME;		//按键扫描时间
typedef enum _AdcKeyType
{
	ADC_KEY_UNKOWN_TYPE = 0,
	ADC_KEY_PRESSED,				//按下
	ADC_KEY_RELEASED,				//按下释放
	ADC_KEY_LONG_PRESSED,			//长按
	ADC_KEY_LONG_PRESS_HOLD,		//一直按
	ADC_KEY_LONG_RELEASED,			//长按释放
}AdcKeyType;

typedef struct _AdcKeyMsg
{
    uint16_t index;
    uint16_t type;
}AdcKeyMsg;

uint8_t GetAdcKeyIndex(void);

AdcKeyMsg AdcKeyScan(void);

void AdcKeyInit(void);
#endif

#endif

adc_key.c

#include "adc_key.h"
#include "adc.h"
#include "timer.h"

/*
 * ******************************************
 * ADC KEY标准电阻值: 上拉 10k (3.30V)
 * 0 = 100(0.00V), 1 = 1K(0.30V),  2 = 2.2K(0.59V), 3 = 3.6K(0.87V), 4= 5.6K(1.18V), 5 = 8.2K(1.48V), 
 * 6 = 12K(1.80V), 7 = 18K(2.10V), 8 = 27K(2.40V),  9 = 47K(2.70V),  10=100K(3.00V),
 *
 ********************************************
*/
#ifdef ADC_KEY_EN

#define 	ADC_KEY_SCAN_TIME			10		//按键扫描时间(ms)
#define 	ADC_KEY_JITTER_TIME			30		//按键消抖时间(ms)
#define 	ADC_KEY_CP_TIME				800 	//长按到长按,长按到一直按时间(ms)
#define 	ADC_KEY_CPH_TIME			500		//一直按触发间隔(ms)
#define	    ADC_KEY_COUNT				11		//标准adc按键个数
#define		ADC_KEY_FULL_VAL			4096	//12位adc精度

uint16_t ADCKEYSCANTIME = ADC_KEY_SCAN_TIME;

typedef enum _ADC_KEY_STATE
{
	ADC_KEY_STATE_IDLE,
	ADC_KEY_STATE_JITTER,
	ADC_KEY_STATE_PRESS_DOWN,
	ADC_KEY_STATE_CP

} ADC_KEY_STATE;

TIMER			AdcKeyWaitTimer;
TIMER			AdcKeyScanTimer;
ADC_KEY_STATE	AdcKeyState;
static 	uint8_t 	PreKeyIndex = ADC_KEY_COUNT;

void AdcKeyInit(void)
{
	Adc_Init();						//初始化adc1通道0
	TIM1_Int_Init(10-1, 7200-1);	//初始化定时器 1ms 
}

uint8_t GetAdcKeyIndex(void)
{
	uint16_t Val;
	uint8_t	KeyIndex = ADC_KEY_COUNT;

	Val = Get_Adc(ADC_Channel_0);

	KeyIndex = (Val + (ADC_KEY_FULL_VAL / ADC_KEY_COUNT) / 2) * ADC_KEY_COUNT / ADC_KEY_FULL_VAL;

	return KeyIndex;
}


/**
*按键处理函数
*返回:按键个数 按键事件  
*buttonmsg.index = 0, buttonmsg.type = ADC_KEY_LONG_PRESS_HOLD,意思第1个按键一直按下
*buttonmsg.index = 2, buttonmsg.type = ADC_KEY_RELEASED,意思第3个按键按下后释放
*/
AdcKeyMsg AdcKeyScan(void)
{
	uint8_t				KeyIndex=ADC_KEY_COUNT;
	AdcKeyMsg Msg = {ADC_KEY_COUNT, ADC_KEY_UNKOWN_TYPE};

	KeyIndex = GetAdcKeyIndex();
	
	switch(AdcKeyState)
	{
		case ADC_KEY_STATE_IDLE:
			if(KeyIndex == ADC_KEY_COUNT)
			{
				return Msg;
			}
			PreKeyIndex = KeyIndex;
			TimeOutSet(&AdcKeyWaitTimer, ADC_KEY_JITTER_TIME);
			//APP_DBG("GOTO JITTER!\n");
			AdcKeyState = ADC_KEY_STATE_JITTER;

		case ADC_KEY_STATE_JITTER:
			if(PreKeyIndex != KeyIndex)
			{
				//APP_DBG("GOTO IDLE Because jitter!\n");
				PreKeyIndex = ADC_KEY_COUNT;
				AdcKeyState = ADC_KEY_STATE_IDLE;
			}
			else if(IsTimeOut(&AdcKeyWaitTimer))
			{
				//APP_DBG("GOTO PRESS_DOWN!\n");
				TimeOutSet(&AdcKeyWaitTimer, ADC_KEY_CP_TIME);
				AdcKeyState = ADC_KEY_STATE_PRESS_DOWN;
				Msg.index = PreKeyIndex;
				Msg.type = ADC_KEY_PRESSED;
			}
			break;

		case ADC_KEY_STATE_PRESS_DOWN:
			if(PreKeyIndex != KeyIndex)
			{
				//APP_DBG("key release %d\n", PreKeyIndex);
				AdcKeyState = ADC_KEY_STATE_IDLE;
				Msg.index = PreKeyIndex;
				Msg.type = ADC_KEY_RELEASED;
				PreKeyIndex = ADC_KEY_COUNT;
			}
			else if(IsTimeOut(&AdcKeyWaitTimer))
			{
				//return key cp value
				//APP_DBG("ADC KEY CPS!\n");
				TimeOutSet(&AdcKeyWaitTimer, ADC_KEY_CPH_TIME);
				AdcKeyState = ADC_KEY_STATE_CP;
				Msg.index = PreKeyIndex;
				Msg.type = ADC_KEY_LONG_PRESSED;
			}
			break;

		case ADC_KEY_STATE_CP:
			if(PreKeyIndex != KeyIndex)
			{
				//return key cp value
				//APP_DBG("ADC KEY CPR!\n");
				AdcKeyState = ADC_KEY_STATE_IDLE;
				Msg.index = PreKeyIndex;
				Msg.type  = ADC_KEY_LONG_RELEASED;
				PreKeyIndex = ADC_KEY_COUNT;
			}
			else if(IsTimeOut(&AdcKeyWaitTimer))
			{
				//return key cph value
				//APP_DBG("ADC KEY CPH!\n");
				TimeOutSet(&AdcKeyWaitTimer, ADC_KEY_CPH_TIME);
				Msg.index = PreKeyIndex;
				Msg.type  = ADC_KEY_LONG_PRESS_HOLD;
			}
			break;

		default:
			AdcKeyState = ADC_KEY_STATE_IDLE;
			PreKeyIndex = ADC_KEY_COUNT;
			break;
	}

	return Msg;
}

#endif

github:hahahahahaxiaoming/stm32adckey: stm32f103adc按键采集 (github.com)

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值