【蓝桥杯嵌入式国赛】①拓展板——高效ADC按键驱动代码

前言

        此系列教程针对蓝桥杯比赛。本人才疏学浅,如有不足之处,敬请批评指正。

摘要

        本篇文章主要介绍了蓝桥杯嵌入式比赛扩展板上面ADC按键的工作原理与使用方法。

跳线帽与原理图

        要想使用ADC按键需要将扩展板连接到主板上,如下图所示,并且还要短路扩展板上AKEY跳线帽。

        连接成功后,ADC按键与主控板上的PA5(使用ADC2_IN13)引脚相连,ADC按键共有8个子按键,原理图如下图所示:

        从上图可以看出,当没有按键按下时,ADC_KEY的电压为3.3V,当按下不同的按键时,根据串联分压原理,ADC_KEY上会产生不同的电压,根据电压的值,可判断哪个按键被按下。比如按键S1被按下时,ADC_KEY上的电压约为0.2V,按键S4按下时,ADC_KEY上的电压约为1.5V。 

        在比赛中需要对按键进行消抖,直接读取ADC的范围计算会导致按键多次抖动,造成功能无法实现。在官方例程中,消抖方式过于复杂,于是作者在这里提供一种高效的消抖方式。

官方例程

 1、编写ADC采集函数

uint16_t getADC(void)
{
    uint16_t adc = 0;

    HAL_ADC_Start(&hadc2);
    adc = HAL_ADC_GetValue(&hadc2);

    return adc;
}

 2、官方驱动例程


#include "button.h"

static u16 btn_buff[BTN_BUFF_LEN];


u16 Read_Btn(void)
{
    u16 tmp;
    u8 i = 0, j = 0;

    for(i = 0; i < BTN_BUFF_LEN; i++)
    {
        btn_buff[i] = getADC();
    }

    for(i = 0; i <= BTN_BUFF_LEN / 2; i++)
    {
        for(j = 0; j <	BTN_BUFF_LEN - i - 1; j++)
        {
            if(btn_buff[j + 1] < btn_buff[j])
            {
                tmp = btn_buff[j + 1];
                btn_buff[j + 1] = btn_buff[j];
                btn_buff[j] = tmp;
            }
        }
    }

    if(BTN_BUFF_LEN % 2 == 0)
    {
        return(btn_buff[BTN_BUFF_LEN / 2 - 1] + btn_buff[BTN_BUFF_LEN / 2]) / 2;
    }
    else
    {
        return(btn_buff[BTN_BUFF_LEN / 2]);
    }
}

//
u8 Scan_Btn(void)
{
    u16 btn_tmp = 0;

    btn_tmp = Read_Btn();
    if(btn_tmp < 0x0FFF / 14)
    {
        return 1;
    }
    else if((btn_tmp > 0x0FFF / 14) && (btn_tmp < 0x0FFF / 14 * 3))
    {
        return 2;
    }
    else if((btn_tmp > 0x0FFF / 14 * 3) && (btn_tmp < 0x0FFF / 14 * 5))
    {
        return 3;
    }
    else if((btn_tmp > 0x0FFF / 14 * 5) && (btn_tmp < 0x0FFF / 14 * 7))
    {
        return 4;
    }
    else if((btn_tmp > 0x0FFF / 14 * 7) && (btn_tmp < 0x0FFF / 14 * 9))
    {
        return 5;
    }
    else if((btn_tmp > 0x0FFF / 14 * 9) && (btn_tmp < 0x0FFF / 14 * 11))
    {
        return 6;
    }
    else if((btn_tmp > 0x0FFF / 14 * 11) && (btn_tmp < 0x0FFF / 14 * 13))
    {
        return 7;
    }
    else if((btn_tmp > 0x0FFF / 14 * 13) && (btn_tmp < 0x0F6F))
    {
        return 8;
    }
    else
    {
        return 0;	//error status & no key
    }
}

        官方代码比较难理解,而且编写花费时间较多,这里作者采用使用标志位判断的方法同时对多个按键扫描判断,大大减短编写时间

高效代码

1、编写ADC采集函数(同上)

uint16_t getADC(void)
{
    uint16_t adc = 0;

    HAL_ADC_Start(&hadc2);
    adc = HAL_ADC_GetValue(&hadc2);

    return adc;
}

2、编写按键扫描函数


 int key_scan(void)
 {	 
	static int flag=0;
    if(getADC()<4000&&flag==0)
	{
		HAL_Delay(20);
		flag=1;
		if(getADC() < 10)   return 1;
		if(getADC() < 800)  return 2;
		if(getADC() < 1600) return 3;
		if(getADC() < 2000) return 4;
		if(getADC() < 2700) return 5;
		if(getADC() < 3300) return 6;
		if(getADC() < 3700) return 7;
		if(getADC() < 4000) return 8;	 
	 }
	 else if(flag==1&&getADC()>4000)
		flag=0;	 
	 return 0;
  
 }

        优化后的代码,通过判断按键是否按下,Delay延迟20毫秒,从而消抖。第二次通过ADC的值判断哪个按键按下并返回相应返回值。同时防止了多个按键同时按下造成的干扰,当全部按键松开时,标志位清0,才能进入下一轮判断按键值。在主函数中调用此函数,即可实现消抖后的按键扫描函数,非常方便。

        注意:此函数中使用Delay函数来延时消抖,在整个代码中最好仅调用一次此函数(可以用switch判断函数的返回值来使用),调用多次扫描函数会有机率读取不到按键按下

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值