蓝桥杯嵌入式国赛 ---- ADC按键


前言

本文是基于嵌入式开发板CT117E,stm32f103RBT6。

一、原理图

在这里插入图片描述

二、由原理图得到的信息

  • 各个按键连接的电阻的阻值不一样。
  • 按键按下电路连通。
  • 电路连通后,每个按键按下的adc值都不一样,通过这个去判断是哪个按键按下。
  • 根据自己开发板测得的数据,进行代码的编写,不用死记硬背各个按键按下的adc值。

三、ADC按键初始化

adc_key.c

#include "adc_key.h"
u16 adc_val;
void adc_key_init(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

  /* Configure PC.01, PC.02 and PC.04 (ADC Channel11, Channel12 and Channel14)
    as analog input ----------------------------------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);  
  
  ADC_Cmd(ADC1, ENABLE);
  
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));  
}

adc_key.h

#ifndef ADC_KEY_H
#define ADC_KEY_H
#include "stm32f10x.h"
extern u16 adc_val;
u8 adc_key_read(void);
void adc_key_init(void);
#endif

四、ADC按键应用函数

u16  Adc_GetButtonVal(void){
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));

	ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
	return ADC_GetConversionValue(ADC1);
}
u16 get_adc(void)  //对获取的adc值进行滤波,冒泡排序取中间值
{
	u16 adc_buff[50];
	u8 i,j;
	
	for(i=0;i<50;i++)
	{
		adc_buff[i]=Adc_GetButtonVal();
	}

	for(i=0;i<50-1;i++)
	{
		for(j=0;j<50-i-1;j++)
		{
			if(adc_buff[j]>adc_buff[j+1])
			{
				adc_buff[j]=adc_buff[j] ^ adc_buff[j+1];
				adc_buff[j+1]=adc_buff[j] ^ adc_buff[j+1];
				adc_buff[j]=adc_buff[j] ^ adc_buff[j+1];
			}
		}
	}
	adc_val	= (adc_buff[24] + adc_buff[25])/2;
	return adc_val;
			
}
u8 adc_key_read(void)  //判断是哪个按键按下
{
	u16 temp = 0;
	temp = get_adc();
	if(temp<0x0015)			return 1;
	else if(temp<0x0250)	return 2;
	else if(temp<0x0500)	return 3;
	else if(temp<0x0700)	return 4;
	else if(temp<0x0A00)	return 5;
	else if(temp<0x0C00)	return 6;
	else if(temp<0x0E00)	return 7;
	else if(temp<0x0FC0)	return 8;
	else					return 0;	
}
						

五、ADC按键在主函数的应用方法

按键按下需要进行消抖,这里用一个前后台的思想,在系统滴答定时器中每50ms就会把按键标志位置1,然后在主函数中,判断这个标志位,再调用按键获取函数,达到消抖的效果。

while(1)
{
	if(key_flag)		 //50ms获取一次,达到按键消抖的效果
	{
		key=adc_key_read();
		if(key!=0)
		{
		 seg_show(16,16,key); //数码管显示按键值
		//Delay_Ms(50);   //消抖
		// sprintf((char *)buff,"adc_val: %x    ",adc_val);		//显示获取到的12位的电压值
		// LCD_DisplayStringLine(Line5,buff);
		 
		}
		key_flag=0;
	}
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值