一、按键原理
扩展板上按键原理图如下:
将八个按键的高电平端接入ADC_KEY引脚,并且每一个按键前串联相应的电阻。当每个按键按下时,该引脚的电位就会发生变化,不同的按键按下,通过ad采集到的电位不一样,因此可根据不同的电位来区分不同的按键。原理本质上是电阻分压,通过按下不同的按键来改变电压值,然后ADC引脚进行采集对应的电压,然后就可以做出判断,实现按键功能。
优点:节省IO口,只需要一个IO口就可以检测这么多按键。但是缺点受硬件影响比较大,不同的板子,电阻也略有不同,检测得到的电压也有不同。对电阻的阻值有要求:每个按键按下时,它所相应的电位的变化需要比较大。并且不支持多个按键同时触发,如果多个按键同时触发就会产生混乱。
不同的按键按下电压所占比重值:
二、程序
电路图所示需要将P4和P5的PA5、ADC_KEY连接,用跳线帽将扩展板上对于的引脚进行连接。
PA5连接ADC_KEY,PA5就是一个ADC采集口,通过采集到不同的电压值来判断是哪一个按键按下的。对于着ADC2的通道15。所以在使用扩展板按键时需要配置ADC2.
将配置adc2通道13即可。可参考博客:ADC
adc数据采集:
uint16_t getADC2(void)
{
uint16_t adc = 0;
HAL_ADC_Start(&hadc2);
adc = HAL_ADC_GetValue(&hadc2);
return adc;
}
ADC数字滤波处理
// adc中值值滤波算法
#define LEN 50
uint16_t filter(void)
{
uint8_t i=0,j=0;
uint16_t buf[LEN],temp;
// 连续采集数据
for(i=0;i<LEN;i++)
{
buf[i]=getADC2();
}
// 冒泡算法
for(i=0;i<LEN/2;i++)
{
for(j=0;j<LEN-i-1;j++)
{
if(buf[j+1] < buf[j])
{
temp = buf[j+1];
buf[j+1]= buf[j];
buf[j] = temp;
}
}
}
if(LEN%2==0) //数组长度为偶数,返回中间两个的平均值
{
return (buf[LEN/2-1]+buf[LEN/2])/2;
}
else
{
return buf[LEN/2];
}
}
按键扫描
uint8_t ADC_Key_Scan(void)
{
uint16_t val=0;
val = filter();
if(val < 0x0FFF/ 14) // 0fff --> 4095
{
return 1; // adc=0
}
else if((val > (0x0FFF /14)*1) && (val < (0x0FFF /14)*3))
{
return 2; // adc = 495
}
else if((val > (0x0FFF /14)*3) && (val < (0x0FFF /14)*5))
{
return 3; // adc = 1105
}
else if((val > (0x0FFF /14)*5) && (val < (0x0FFF /14)*7))
{
return 4; // adc = 1710
}
else if((val > (0x0FFF /14)*7) && (val < (0x0FFF /14)*9))
{
return 5;// adc = 2315
}
else if((val > (0x0FFF /14)*9) && (val < (0x0FFF /14)*11))
{
return 6;// adc = 2825
}
else if((val > (0x0FFF /14)*11) && (val < (0x0FFF /14)*13))
{
return 7;// adc = 3455
}
else if((val > (0x0FFF /14)*13) && (val < 0x0F6F))
{
return 8; // adc = 3926
}
else
{
return 0; // adc = 4040
}
}
按键处理
void key_proc(void)
{
if(key_uwTick - uwTick <200)return ;
key_uwTick = uwTick;
key_val = ADC_Key_Scan();
key_down = key_val &(key_old ^ key_val);
key_up = ~key_val &(key_old ^ key_val);
key_old = key_val;
if(key_down == 1)
{
ucled =1;
}
}