目录
1、前言
2、电路原理
3、代码编写
3.1 读取Btn电压
3.2 检索按键
3.3 main文件编写
3.3.1 进行变量定义
3.3.2 AD_Key函数
3.3.3 LCD函数
3.3.4 main函数
3.3.5 完整代码
4、测试
5、总结
1、前言
本文进行拓展板按键程序设计,拓展板的按键是通过采集模拟量来判断具体按键的,所以通过配置AD资源,通过模拟量转数字量获取相应的AD值,即可判断具体按下的按键编号。
2、电路原理
蓝桥杯的扩展板与核心板的引脚图如下:
ADC_KEY与PA5引脚连接即可通过PA5引脚捕获ADC_KEY的电压值。
下图为ADC_KEY的电路示意图,当按下不同的按键,电阻的分压是不同的,所以可以根据读取到的电压值进行判断不同的按键被按下。
3、代码编写
3.1 读取Btn电压
进行获取按键的电压值,并进行中值滤波设计,采集一组AD数据,通过冒泡排序即可找到其中的中值,用其来作为本轮检测滤波后的AD值。
如上图所示,获取采集到的AD数组取中值为按键AD的滤波值。
#define BTN_BUFF_LEN 50
uint16_t Read_Btn(void)
{
uint16_t Btn_Buffer[BTN_BUFF_LEN] = {0};
int i,j;
for(i=0;i<BTN_BUFF_LEN;i++)
{
Btn_Buffer[i] = getADC2();
}
uint16_t temp;
for(i=0;i<BTN_BUFF_LEN/2;i++)
{
for(j=0;j<BTN_BUFF_LEN-i-1;i++)
{
if(Btn_Buffer[j+1]<Btn_Buffer[j])
{
temp = Btn_Buffer[j+1];
Btn_Buffer[j+1] = Btn_Buffer[j];
Btn_Buffer[j] = temp;
}
}
}
if(BTN_BUFF_LEN%2==0)
return ((Btn_Buffer[BTN_BUFF_LEN/2-1]+Btn_Buffer[BTN_BUFF_LEN/2])/2);
else
return Btn_Buffer[BTN_BUFF_LEN/2];
}
3.2 检索按键
通过读取Btn电压,根据按键电路计算经验值,通过if-else语句进行判断 ,返回对应的按键值。
uint8_t Scan_Btn(void)
{
uint16_t BtnAd = Read_Btn();
if(BtnAd < (0xFFF*1/14))
return 1;
else if((BtnAd > (0xFFF*1/14)) && (BtnAd < (0xFFF*3/14)))
return 2;
else if((BtnAd > (0xFFF*3/14)) && (BtnAd < (0xFFF*5/14)))
return 3;
else if((BtnAd > (0xFFF*5/14)) && (BtnAd < (0xFFF*7/14)))
return 4;
else if((BtnAd > (0xFFF*7/14)) && (BtnAd < (0xFFF*9/14)))
return 5;
else if((BtnAd > (0xFFF*9/14)) && (BtnAd < (0xFFF*11/14)))
return 6;
else if((BtnAd > (0xFFF*11/14)) && (BtnAd < (0xFFF*13/14)))
return 7;
else if((BtnAd > (0xFFF*13/14)) && (BtnAd < (0xF6E)))
return 8;
else
return 0;
}
3.3 main文件编写
3.3.1 进行变量定义
减速变量控制Key_Proc和Led_Proc的执行速度
Lcd_Disp_String为显示LCD的字符串
Btn_Num 为AD_Key的按键值
//*减速变量
__IO uint32_t uwTick_Key_Set_Point = 0;//控制Key_Proc的执行速度
__IO uint32_t uwTick_Led_Set_Point = 0;//控制Led_Proc的执行速度
//*LCD显示专用变量
unsigned char Lcd_Disp_String[22];
//AD_Key变量
uint8_t Btn_Num = 0;
3.3.2 AD_Key函数
AD_Key函数去执行AD模块的Scan_Btn();
void AD_Key_Proc(void)
{
Btn_Num = Scan_Btn();
}
3.3.3 LCD函数
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100)return;//减速处理
uwTick_Lcd_Set_Point = uwTick;
sprintf((char*)Lcd_Disp_String,"AD_Key:%d",Btn_Num);
LCD_DisplayStringLine(Line2,Lcd_Disp_String);
}
3.3.4 main函数
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/*bsp资源的初始化*/
AD_Key_Init();
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
while (1)
{
Lcd_Proc();
}
}
3.3.5 完整代码
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "RCC\bsp_rcc.h"
#include "LCD\bsp_lcd.h"
#include "ADC\bsp_adc.h"
//***全局变量声明区
//*减速变量
__IO uint32_t uwTick_Lcd_Set_Point = 0;//控制Lcd_Proc的执行速度
//*LCD显示专用变量
unsigned char Lcd_Disp_String[22];
//AD_Key变量
uint8_t Btn_Num = 0;
//***子函数声明区
void Lcd_Proc(void);
void AD_Key_Proc(void);
//***系统主函数
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/*bsp资源的初始化*/
AD_Key_Init();
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
while (1)
{
AD_Key_Proc();
Lcd_Proc();
}
}
//***LCD子函数
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100)return;//减速处理
uwTick_Lcd_Set_Point = uwTick;
sprintf((char*)Lcd_Disp_String,"AD_Key:%d",Btn_Num);
LCD_DisplayStringLine(Line2,Lcd_Disp_String);
}
void AD_Key_Proc(void)
{
Btn_Num = Scan_Btn();
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
4、测试
使用开发板通过杜邦线连接扩展版,进行AD_Key模块的按键测试。可以看到在按不同按键时,LCD屏幕显示了对应的按键值。
5、总结
本文通过AD采集并滤波的方式获取到按键电压,再根据不同按键产生不同电压范围的电路原理进行按键的判断,通过代码测试成功。