山景BP10_128DBG开发板ADC_Key驱动

前言

最近在学习山景BP10_128DBG开发板,想使用开发板上的按键,看了看原理图和之前用过的按键好像有点不一样。常见的按键都是判断IO口是否被拉低或拉高来判断按键是否被按下。山景BP10_128DBG开发板上的按键是ADC按键,每个按键按下之后ADC的采样值是不同的,通过ADC采样回来的值进而判断哪个按键按下。这种方式核心思想就是用一个ADC通道来节约IO口,对于IO紧张的芯片是一个不错的解决思路。

常见按键连接方式
常见按键

 

ADC按键

我把ADC按键给封装起来了,给用户提供一个.c和.h文件

adckey.c代码

#include "adckey.h"

//	ADC_CHANNEL_VIN = 0,		/**channel 0*/
//	ADC_CHANNEL_VBK,			/**channel 1*/
//	ADC_CHANNEL_VDD1V2,			/**channel 2*/
//	ADC_CHANNEL_VCOM,			/**channel 3*/
//	ADC_CHANNEL_GPIOA20_A23,	/**channel 4*/
//	ADC_CHANNEL_GPIOA21_A24,	/**channel 5*/
//	ADC_CHANNEL_GPIOA22_A25,	/**channel 6*/
//	ADC_CHANNEL_GPIOA26,		/**channel 7*/
//	ADC_CHANNEL_GPIOA27,		/**channel 8*/
//	ADC_CHANNEL_GPIOA28,		/**channel 9*/
//	ADC_CHANNEL_GPIOA29,		/**channel 10*/
//	ADC_CHANNEL_GPIOA30,		/**channel 11*/
//	ADC_CHANNEL_GPIOA31,		/**channel 12*/
//	ADC_CHANNEL_GPIOB0,			/**channel 13*/
//	ADC_CHANNEL_GPIOB1,			/**channel 14*/
//	ADC_CHANNEL_POWERKEY		/**channel 15*/


//以下定义的宏是按键按下后返回对应的键值
#define KEY8_PRESS		8
#define KEY9_PRESS		9
#define KEY10_PRESS		10
#define KEY11_PRESS		11
#define KEY12_PRESS		12
#define KEY13_PRESS		13
#define KEY14_PRESS		14
#define KEY15_PRESS		15
#define KEY16_PRESS		16
#define KEY17_PRESS		17
#define KEY18_PRESS		18
#define KEY19_PRESS		19
#define KEY20_PRESS		20
#define KEY21_PRESS		21
#define KEY22_PRESS		22
#define KEY23_PRESS		23
#define KEY24_PRESS		24
#define KEY25_PRESS		25
#define KEY26_PRESS		26
#define KEY27_PRESS		27
#define KEY28_PRESS		28
#define KEY29_PRESS		29



/*
	以下两个数组存放的是ADC按键按下之后ADC采样回来的原始数据
	获取ADC的值与下方数组的值进行比较就可以知道那个按键被按下了
*/

uint16_t ADC1_Key_Data[11] = {1200, 1485, 1577, 1644, 1720, 1850, 2190, 2584, 2922, 3309, 3650};
uint16_t ADC2_Key_Data[11] = {47, 370, 730, 1060, 1447, 1814, 2193, 2592, 2926, 3314, 3650};

/*
	ADC_Key初始化函数
	(0, 0)ADC1_KEY和ADC2_Key都不初始化
	(1, 0)ADC1_KEY初始化和ADC2_Key不初始化
	(0, 1)ADC1_KEY不初始化和ADC2_Key初始化
	(1, 1)ADC1_KEY和ADC2_Key都初始化
*/

void ADC_Key_Init(bool ADC1_Key_Enable, bool ADC2_Key_Enable)
{
	SarADC_Init();
	if(ADC1_Key_Enable){
		GPIO_RegOneBitClear(GPIO_A_ANA_EN, GPIO_INDEX20);//channel
		GPIO_RegOneBitSet(GPIO_A_ANA_EN, GPIO_INDEX23);
	}
	if(ADC2_Key_Enable){
		GPIO_RegOneBitSet(GPIO_A_ANA_EN, GPIO_INDEX26);//channel
	}
	if(ADC1_Key_Enable && ADC2_Key_Enable){
		GPIO_RegOneBitClear(GPIO_A_ANA_EN, GPIO_INDEX20);
		GPIO_RegOneBitSet(GPIO_A_ANA_EN, GPIO_INDEX23);//channel
		GPIO_RegOneBitSet(GPIO_A_ANA_EN, GPIO_INDEX26);//channel
	}
}

/*
	获取ADC_Key的采样值,范围是0-4095(2^12 - 1)
*/
uint16_t ADC_Key_Data_Get(ADC_Key_CHANNEL_SEL adc_key_channel)
{
	uint16_t ADC_Key_Data = 0;
	if(adc_key_channel == ADC1_Key_Channel){
		ADC_Key_Data = ADC_SingleModeDataGet(ADC_CHANNEL_GPIOA20_A23);

	}
	if(adc_key_channel == ADC2_Key_Channel){
		ADC_Key_Data = ADC_SingleModeDataGet(ADC_CHANNEL_GPIOA26);
	}
	return ADC_Key_Data;
}


/*
	开发板对应按键返回函数
	adc_key_channel用于选择那个ADC_Key
	根据adc_key_data来判断两个ADC组中具体哪个按键按下了
*/

uint8_t ADC_Key_Press_Return(ADC_Key_CHANNEL_SEL adc_key_channel, uint16_t adc_key_data)
{
	int temp[11];
	uint8_t i = 0;
	int min;
	uint8_t index;
	memset(temp, 0x00, sizeof(temp));
	//ADC_Key1组中的按键返回
	if(adc_key_channel == ADC1_Key_Channel){
		//先计算adc_key_data和标准ADC按键返回值的差值
		for(i = 0; i < 11; i++){
			temp[i] = adc_key_data - ADC1_Key_Data[i];
			//DBG("temp[%d] = %d\r\n", i, temp[i]);
		}
		//先默认temp[0]是差值最小的,下面比较都是在正整数的基础上进行的
		if(temp[0] < 0){
			min = -temp[0];
			index = 0;
		}
		else{
			min = temp[0];
			index = 0;
		}

		//遍历数组temp找到差距最小的下标
		for(i = 0; i < 11; i++){
			if(temp[i] < 0){
				temp[i] = -temp[i];
			}
			if(min > temp[i]){
				min = temp[i];
				index = i;
			}
		}
		switch(index){
			case 0:
				return KEY9_PRESS;
			case 1:
				return KEY11_PRESS;
			case 2:
				return KEY13_PRESS;
			case 3:
				return KEY15_PRESS;
			case 4:
				return KEY17_PRESS;
			case 5:
				return KEY19_PRESS;
			case 6:
				return KEY21_PRESS;
			case 7:
				return KEY23_PRESS;
			case 8:
				return KEY25_PRESS;
			case 9:
				return KEY27_PRESS;
			case 10:
				return KEY29_PRESS;
		}
	}
	//ADC_Key2组中的按键返回
	if(adc_key_channel == ADC2_Key_Channel){
		//先计算adc_key_data和标准ADC按键返回值的差值
		for(i = 0; i < 11; i++){
			temp[i] = adc_key_data - ADC2_Key_Data[i];
		}
		//先默认temp[0]是差值最小的,下面比较都是在正整数的基础上进行的
		if(temp[0] < 0){
			min = -temp[0];
			index = 0;
		}
		else{
			min = temp[0];
			index = 0;
		}
		//遍历数组temp找到差距最小的下标
		for(i = 0; i < 11; i++){
			if(temp[i] < 0){
				temp[i] = -temp[i];
			}
			if(min > temp[i]){
				min = temp[i];
				index = i;
			}
		}
		switch(index){
			case 0:
				return KEY8_PRESS;
			case 1:
				return KEY10_PRESS;
			case 2:
				return KEY12_PRESS;
			case 3:
				return KEY14_PRESS;
			case 4:
				return KEY16_PRESS;
			case 5:
				return KEY18_PRESS;
			case 6:
				return KEY20_PRESS;
			case 7:
				return KEY22_PRESS;
			case 8:
				return KEY24_PRESS;
			case 9:
				return KEY26_PRESS;
			case 10:
				return KEY28_PRESS;
		}
	}
}

adckey.h代码

#ifndef __ADCKEY_H
#define __ADCKEY_H

#include "sadc_interface.h"
#include "irqn.h"
#include "adc.h"
#include "string.h"
#include "delay.h"  //这个头文件在mv_utils的inc文件夹下
#include "gpio.h"
#include "type.h"

/*
  定义一个ADC_Key_CHANNEL_SEL的枚举
  以便于用户使用ADC_Key,而不用去管到底是哪个ADC通道进行采样,哪个IO进行模拟复用
*/

typedef enum __ADC_Key_CHANNEL_SEL
{
	ADC1_Key_Channel,
	ADC2_Key_Channel
}ADC_Key_CHANNEL_SEL;

void ADC_Key_Init(bool ADC1_Key_Enable, bool ADC2_Key_Enable);
uint16_t ADC_Key_Data_Get(ADC_Key_CHANNEL_SEL adc_key_channel);
uint8_t ADC_Key_Press_Return(ADC_Key_CHANNEL_SEL adc_key_channel, uint16_t adc_key_data);

#endif

提供的一个样例测试代码,死循环扫描哪个ADC按键被按下

void SarADC_DCSingleMode(void)
{
	uint16_t DC_Data;
	uint8_t key;
	DBG("SarADC DC example\n");
	//GPIOA23做为ADC采样输入引脚
	//BP10开发板上按下不同的按键串口会打印输出不同的电压采样值
	ADC_Key_Init(1, 1);
	while(1)
	{
		DC_Data = ADC_Key_Data_Get(ADC1_Key_Channel);
		//DBG("ADC1_Data = %d\r\n", DC_Data);
		key = ADC_Key_Press_Return(ADC1_Key_Channel, DC_Data);
		DBG("key %d is pressed\r\n", key);
		DelayMs(500);

		DC_Data = ADC_Key_Data_Get(ADC2_Key_Channel);
		//DBG("ADC2_Data = %d\r\n", DC_Data);
		key = ADC_Key_Press_Return(ADC2_Key_Channel, DC_Data);
		DBG("key %d is pressed\r\n", key);
		DelayMs(500);

	}
}

按下开发板上对应按键之后串口会打印出来,当没有按键按下之默认是key28和key29,所以这两个按键在这种方式中就会不起作用,尽量就别用。

串口打印结果

总结

以上就是本文的全部内容,希望可以帮你使用到ADC_Key。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

门牙会稍息

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值