一、实现的功能
ADC按键电路原路图:
- ①实时检测ADC键盘的S按键,并显示到3位数码管上面;
- ②只使用到ADC扫描键盘的单击功能,屏蔽长按功能;
- ③通过电路原理图,计算每个按键按下检测到的ADC值;
二、根据功能实现代码
1、主文件main.c
#include"key.h"
#include"led.h"
#include"lcd.h"
#include"stdio.h"
#include <stm32f10x.h>
#include"seg.h"
#include "adc.h"
unsigned int uiSeg;
unsigned char ucDot,ucAkey_Long;
unsigned long ulTick_ms,ulAkey_Time;
void AKEY_Proc(void);
int main(void)
{
SysTick_Config(72000);
KEY_Init();
LED_Init();
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
ADC1_Init_AKEY();
SEG_Init();
SEG_Disp(0,0,0,0);
while(1)
{
AKEY_Proc();
SEG_Disp((uiSeg&0xf00)>>8,(uiSeg&0xf0)>>4,uiSeg&0xf,ucDot++);
}
}
void AKEY_Proc(void)
{
unsigned char ucAkey_Val;
ucAkey_Val = AKEY_Read();
if(ucAkey_Val != ucAkey_Long)
{
ucAkey_Long = ucAkey_Val;
ulAkey_Time = ulTick_ms;
}
else
ucAkey_Val = 0;
if(ucAkey_Val)
{
uiSeg = (uiSeg << 4) + ucAkey_Val;
ucDot++;
}
}
void SysTick_Handler(void)
{
ulTick_ms++;
}
主函数分析:?? ?? ??
- 把ADC_KEY对应的PA5配置为ADC模拟量输入模式;
- 检测ADC的那个按键按下,然后第一位数码管显示对应的按键,再次按下的话上一次的按键值左移,在第一位再显示新按下的值;
- 定义一个全局变量保存上一次的按下的按键,如果不相等,则保存当前按下的键值,否则将当前按键值置0(防止长按),最后根据当前键值进行对应数码管的显示;
2、ADC按键程序的头文件“adc.h”
void ADC1_Init_AKEY(void);
unsigned char AKEY_Read(void);
void Delay_AKEY(unsigned int ms);
简要分析:?? ??
- 把AKEY进行GPIO和ADC1的配置;
- 返回ADC键盘的按键值;
- 定义一个粗延时进行按键消抖;
3、ADC按键程序的源文件“adc.c”
void ADC1_Init_AKEY(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStruct);
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_1Cycles5);
ADC_Cmd(ADC1,ENABLE);
while(ADC_GetCalibrationStatus(ADC1));
}
unsigned char AKEY_Read(void)
{
unsigned char ucAkey_Val = 0;
unsigned int uiAdc_Val = ADC1_Conv();
if(uiAdc_Val < 4040)
{
Delay_AKEY(100);
uiAdc_Val = ADC1_Conv();
if(uiAdc_Val < 4040)
{
if(uiAdc_Val > 3746)
ucAkey_Val = 8;
else if(uiAdc_Val > 3194)
ucAkey_Val = 7;
else if(uiAdc_Val > 2624)
ucAkey_Val = 6;
if(uiAdc_Val > 2061)
ucAkey_Val = 5;
else if(uiAdc_Val > 1452)
ucAkey_Val = 4;
else if(uiAdc_Val > 842)
ucAkey_Val = 3;
else if(uiAdc_Val > 267)
ucAkey_Val = 2;
else
ucAkey_Val = 1;
}
}
return ucAkey_Val;
}
void Delay_AKEY(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<792;j++);
}
简要分析:?? ??
- ADC的初始化和配置可参考: 嵌入式设计与开发项目-ADC应用程序设计
- ADC转换值 = 4095 * 电阻值 /(1000 + 电阻值)串联分压
- 电阻之比 = 电压之比 = 转换值之比;
- ADC键盘通过延时100ms更新获取的ADC进行消抖处理;
三、实现功能过程的注意与学习点
1、注意点
- 计算ADC键盘扫描的转换值时,其它通道采集ADC容易引起多通道冲突,可配置为注入通道;
- ADC会随电压的有一定的波动性,可通过串口打印ADC值确定好每个按键的ADC值区间;
2、学习的知识点
- ①熟练ADC模拟输入模式的初始化配置;
- ②计算电阻串联分压单片机采集的ADC转换值;
- ③学会ADC键盘扫描原理以及程序的实现;
- ④数码管进行特定数字的显示;
?? ?? ?? ?? ?? ??
|