ADC检测多个按键

背景了解:

按照传统的按键检测方法就是一个按键对应一个GPIO口,进行高低电平输入检测。可是在GPIO口紧缺的情况下,不得不需要一个有效的解决方案,借鉴网上的资料了解到一个简单的方法,希望分享一下。

ADC检测实现简单实用的按键方法:仅需要一个ADC和若干个电阻就可实现多个按键的输入检测。工作原理:按下按键时,通过电阻分压得到不同的电压值,ADC采集在各个范围内的值来判定是哪个按键按下。

实践方案:

摘录网上的图片:

根据上述电路,4个1K的电阻串联后,节点的位置分别接有按键K1,K2,K3,K4,那么按键单独按下,单片机ADC依次检测到3.7V,3.33V,2.5V,0V,只要将分压值用数组保存起来。补充:没有按键按下时:ADC检测为5v。

通过查表法,就可以实现按键检测,在按键检测的过程中也需要进行按键消抖处理。

简单代码示例:

/***************************************************************************************************************************
 *功能描述:ADC采集多个按键
 *输入参数:无
 *输出参数:无
 *返回参数:非0为按下按键数,0:无按键按下
****************************************************************************************************************************/
unsigned float Sample_Volt[] = {3.75,3.33,2.5,0};   	   //对应上图K1,K2,K3,K4,AD口所采集到的电压值,供查表。
unsigned char ADC1_KeySample(void)
{
	unsigned float KeyVolt = ADC1_GetVolt();//ADC1_GetVolt为采集到按键电压函数,如果是八位单片机考虑浮点运算压力,可以使用采集ADC模拟量来进行判断
	for(unsigned char i = 0; i < 4; i++)
	{
		if((KeyVolt >= Sample_Volt[i] - 0.2) && KeyVolt <= Sample_Volt[i] + 0.2) //允许电压偏差正负0.2V,但还是会存在由于电源不稳导致误判断
		return i + 1;//返回按键数
	}
	return 0;//返回0:无按键按下
}

电路图存在隐患:按键不能串在分压回路里,分压检测需要各自独立,按键只需连接各分压点和ADC输入点,这样因为ADC的输入阻抗比较大,按键的接触电阻对电阻分压的影响较小,缺点:分压回路会一直消耗电流,对电源耗电不利。

改进方案:

硬件改进:

1、在ADC按键的基础上,可用增加二极管的方式,实现按键中断,并在中断服务程序里进行AD转换,从而识别按键。

2、按键消抖,给按键并联一个104左右的电容,软件上基本不用处理即可避免抖动。

软件改进:

将按键扫描放到定时器中断里面,这样就可周期性地检测按键按下情况,不受主循环的影响。使用按键检测状态机能解析出按键的不同状态,即短按,长按等状态,用以实现更丰富的功能。但需注意两点,一是定时器的定时时间,不可过长也不可过短,过长容易检测不到按下,过短会占用大量时间资源。二是中断服务程序需简单明了,只做检测用,通过全局变量传递,在主循环内完成按键响应,中断服务函数内尽量不要占用太多时间。

欢迎读者交流上述按键方案存在的不足之处,并提出行之有效的改进方案进行分享,不甚感激!!!

 

  • 15
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 我可以为您提供一些关于ADC按键滤波算法的基本概念:ADC按键滤波算法是用来减少按键输入的抖动,它可以通过检测按键的多次输入,过滤掉多余的按键点击,最终只保留有效的按键输入。用C语言实现ADC按键滤波算法可以使用一组带有瞬态反应的控制逻辑,以及一组计时器来检测输入按键的时间间隔,以确定按键输入是否有效。 ### 回答2: 在C语言中,可以使用滑动窗口滤波算法对三个ADC按键进行滤波。 首先,需要定义一个窗口大小,表示连续采样的次数。然后,使用一个数组来保存连续采样的数据。对ADC按键进行采样时,将采样值保存到数组中。 当数组满时,即采样次数达到窗口大小时,求得数组中所有元素的平均值,作为滤波后的数据输出。然后,将新的采样值替代数组中最旧的元素,并继续采样。 以下是一个示例代码: ```c // 定义窗口大小 #define WINDOW_SIZE 5 // 用于保存连续采样的数据 uint16_t adcData[WINDOW_SIZE]; uint8_t currentIndex = 0; // 滤波算法函数 uint16_t filter(uint16_t newValue) { // 将新的采样值替代数组中最旧的元素 adcData[currentIndex] = newValue; currentIndex++; currentIndex %= WINDOW_SIZE; // 当连续采样次数达到窗口大小时,进行滤波处理 if (currentIndex == 0) { uint32_t sum = 0; for (uint8_t i = 0; i < WINDOW_SIZE; i++) { sum += adcData[i]; } // 求平均值作为滤波后的数据输出 return sum / WINDOW_SIZE; } else { // 返回原始采样值 return newValue; } } // 主函数 int main() { // 模拟从ADC模块获取采样值 uint16_t newValue_1 = getADCValue_1(); uint16_t newValue_2 = getADCValue_2(); uint16_t newValue_3 = getADCValue_3(); // 对三个ADC按键进行滤波处理 uint16_t filteredValue_1 = filter(newValue_1); uint16_t filteredValue_2 = filter(newValue_2); uint16_t filteredValue_3 = filter(newValue_3); // 输出滤波后的结果 printf("Filtered Value 1: %d\n", filteredValue_1); printf("Filtered Value 2: %d\n", filteredValue_2); printf("Filtered Value 3: %d\n", filteredValue_3); return 0; } ``` 以上是一个简单的滑动窗口滤波算法示例,可以对三个ADC按键进行滤波处理。当窗口大小适当选择时,可以有效地降低采样噪声对结果的影响,使得输出更加平滑和可靠。具体的窗口大小需要根据实际情况进行调整。 ### 回答3: 对三个ADC按键写滤波算法的C语言代码如下: ```c #include <stdio.h> int main() { // 定义三个ADC按键的初始值 int adc1 = 0; int adc2 = 0; int adc3 = 0; // 定义滤波后的ADC按键的值 int filteredAdc1 = 0; int filteredAdc2 = 0; int filteredAdc3 = 0; // 定义滤波窗口大小和初始值个数 int windowSize = 5; int numInitialValues = 5; // 定义数组用于保存初始值 int initialValues1[numInitialValues] = {0}; int initialValues2[numInitialValues] = {0}; int initialValues3[numInitialValues] = {0}; // 循环获取ADC按键的值 while (1) { // 读取ADC按键的值 int adc1Value = getAdc1Value(); int adc2Value = getAdc2Value(); int adc3Value = getAdc3Value(); // 更新初始值数组 for (int i = numInitialValues - 1; i > 0; i--) { initialValues1[i] = initialValues1[i - 1]; initialValues2[i] = initialValues2[i - 1]; initialValues3[i] = initialValues3[i - 1]; } initialValues1[0] = adc1Value; initialValues2[0] = adc2Value; initialValues3[0] = adc3Value; // 计算平均值作为滤波后的值 int sum1 = 0; int sum2 = 0; int sum3 = 0; for (int i = 0; i < windowSize; i++) { sum1 += initialValues1[i]; sum2 += initialValues2[i]; sum3 += initialValues3[i]; } filteredAdc1 = sum1 / windowSize; filteredAdc2 = sum2 / windowSize; filteredAdc3 = sum3 / windowSize; // 输出滤波后的值 printf("Filtered ADC1: %d\n", filteredAdc1); printf("Filtered ADC2: %d\n", filteredAdc2); printf("Filtered ADC3: %d\n", filteredAdc3); } return 0; } ``` 以上代码展示了一个简单的滤波算法,其中使用了一个滑动窗口来计算滤波后的ADC按键值。初始值数组用于保存最新的ADC按键值,然后计算窗口内的平均值来获得滤波后的值。每次循环都会更新初始值数组,并输出滤波后的ADC按键值。请根据实际需求进行适当修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值