蓝桥杯嵌入式扩展板学习之ADC按键

作者:*wj(萌新一枚,有不足和错误希望多多指点帮助改正)
硬件模块

  1. 电路图
    蓝桥杯嵌入式扩展板学习之ADC按键_第1张图片
    蓝桥杯嵌入式扩展板学习之ADC按键_第2张图片
    工作原理:根据ADC采集到不同的值判断对应的按键是否按下
    K1按下:ADC读取R1对地的电压
    K2按下:ADC读取R1和R2对地的电压
    K3按下:ADC读取R1和R2和R3对地的电压
    依次累加到K8
    程序
    ADC配置和之前没什么区别,唯一改变的就是采集的通道号变成ADC_Channel_5
void ADC_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1  , ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
		//ADC
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	// ADC1 工作模式配置
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //单次转换  两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);	
	
	ADC_Cmd(ADC1, ENABLE);   
	ADC_ResetCalibration(ADC1);
	/* Check the end of ADC1 reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	/* Check the end of ADC1 calibration */
	while(ADC_GetCalibrationStatus(ADC1));	

}
/***********************ADC值读取函数******************************/
//返回类型是u16
u16 btn_buff[BTN_BUFF_LEN];   //数组的类型必须是u16,才能装满一个16进制数字
u16 Get_ADC(void)
{
	u16 temp;
	ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_1Cycles5);  //ADC_KEY对应的是通道5
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
	temp = ADC_GetConversionValue(ADC1);
  ADC_SoftwareStartConvCmd(ADC1,DISABLE);	
	return temp;
}

蓝桥杯嵌入式扩展板学习之ADC按键_第3张图片
官方给的这个算法:目的想的是提高AD采集的稳定性和精度,其实经过测试之后,发现完全可以不需要这个算法,我们直接读取Get_ADC()函数的返回数值即可。就当平时训练的时候扩展了一下算法的知识吧,只是比赛的时候时间比较紧张的话,可以完全不用这个算法,影响不大。

/***********************按键读取函数******************************/
//返回类型是u16
u16 Read_Btn(void)
{
	u16 temp;                //中间变量 大小应为u16
	u8 i =0,j=0;             //循环变量
	for(i=0;i<BTN_BUFF_LEN;i++)//循环读取ADC采集的值存放在数组btn_buff[]中 BTN_BUFF_LEN宏定义为50次
	{
	  btn_buff[i] = Get_ADC();		
	}
	for(i=0;i<BTN_BUFF_LEN-1;i++) /* 外循环为排序趟数,len个数进行len-1趟 */
	{
		for(j=0;j<BTN_BUFF_LEN-i-1;j++) /* 内循环为每趟比较的次数,第i趟比较len-i次 */
		{
			if(btn_buff[j+1] < btn_buff[j])/* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
			{
				temp = btn_buff[j+1];
				btn_buff[j+1] = btn_buff[j];
				btn_buff[j] = temp;			
			}	
		}
	}
	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();
	//根据自己读取的adc数值设置边界范围
		if(btn_tmp <= 0x0020)
			{
			   return 1;
			}
		else if((btn_tmp >= 0x00B0) && (btn_tmp <= 0x0230))
			{
		     return 2;
	    }
		else if((btn_tmp >= 0x0240) && (btn_tmp <= 0x0500))
			{
		     return 3;
	    }
		else if((btn_tmp >= 0x0510) && (btn_tmp <= 0x0700))
			{
		     return 4;
	    }
		else if((btn_tmp >= 0x0710) && (btn_tmp <= 0x0970))
			{
		     return 5;
	    }
		else if((btn_tmp >= 0x0980) && (btn_tmp <= 0x0B50))
			{
		     return 6;
     	}
		else if((btn_tmp >= 0x0B60) && (btn_tmp <= 0x0DCF))
			{
		     return 7;
	    }
		else if((btn_tmp >= 0x0DB0) && (btn_tmp <= 0x0FAF))
			{
		    return 8;
	    }
		else
			{
		    return 0;	//error status & no key
	    }
}
方法1:用十六进制表示

蓝桥杯嵌入式扩展板学习之ADC按键_第4张图片
蓝桥杯嵌入式扩展板学习之ADC按键_第5张图片

while(1)
{
	snprintf((char*)str,sizeof(str),"  Button ADC:%04X  ",Read_Btn());  //%04X表示显示4位16进制
	LCD_DisplayStringLine(Line6,str);	
	key_val = Scan_Btn();
	
	if(key_val != 0)
	{
		SEG_DisplayValue(16, 16, key_val);
		sprintf((char*)str,"  Button Value:%d  ",key_val);
		LCD_DisplayStringLine(Line7,str);		
	}		
}

方法2:用十进制表示,可以更方便显示和取范围

sprintf((char*)str,"  Button ADC:%d    ",Read_Btn());
if(btn_tmp <= 50)
	{
	   return 1;
	}
else if((btn_tmp >= 200) && (btn_tmp <= 700))
	{
     return 2;
}
else if((btn_tmp >= 750) && (btn_tmp <= 1200))
	{
     return 3;
}
else if((btn_tmp >= 1250) && (btn_tmp <= 2000))
	{
     return 4;
}
else if((btn_tmp >= 2050) && (btn_tmp <= 2500))
	{
     return 5;
}
else if((btn_tmp >= 2550) && (btn_tmp <= 3000))
	{
     return 6;
}
else if((btn_tmp >= 3050) && (btn_tmp <= 3600))
	{
     return 7;
}
else if((btn_tmp >= 3650) && (btn_tmp <= 4000))
	{
    return 8;
}
else
	{
    return 0;	//error status & no key
}

注意
u16 btn_buff[BTN_BUFF_LEN]; //数组的类型必须是u16,才能装满一个16进制数字,最开始我定义为u8类型,只能最多存储到0X00FF,这样和ADC精度12位读取最大值为0x0FFF不相符

你可能感兴趣的:(蓝桥杯嵌入式)