博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
蓝桥杯STM32F103RB扩展板ADC按键
阅读量:629 次
发布时间:2019-03-14

本文共 4613 字,大约阅读时间需要 15 分钟。

STM32F103RB扩展板(ADC按键+数码管)

实验功能:

使用ADC按键(8个),键入值分别代表1-8,在三个数码管上通过键入值向左移动显示
eg:
默认数码管不显示,第一次键入3,在第一个数码管上显示3
第二次键入8,第一位数码管显示8,第二位数码管显示3
第三次键入6,第一位数码管显示6,第二位数码管显示8,第三位数码管显示3
………………


涨见识了,ADC按键这波操作是真服,通过判断ADC采集到的值,来确定按键,

原理图:

在这里插入图片描述

每段按键加上电阻,达到分压的效果,通过ADC转换,就可以测得不同按键按下的值

计算公式

转换值=4095R/(1000+R) 此处R1的值就是1000

eg:
S1:接GND采集到的值为0
S2:4095
R2/(R1+R2)
S6:按键按下采集到的值:4095*(R2+R3+R4+R5+R6)/(R1+R2+……+R6)
根据计算可以得到s1-s8按键按下采集到的值分别为:
s1 0
s2 534
s3 1149
s4 1755
s5 2367
s6 2880
s7 3507
s8 3984
对于采集到的值会存在一定的误差,这是不可避免的,通过比较中间值来处理这种也涨见识了
如:S1 ,S2采集到的值分别为 0 和 534 这时候取一个中间值267,,<267则作为按键S1按下,>267则作为按键S2按下.比较这个中间值可以避免采集值存在误差带来的问题。
所有计算结果如下:在这里插入图片描述

软件设计

ADC初始化

void ADC1_Init_AKEY(void){
GPIO_InitTypeDef GPIO_InitStruct; ADC_InitTypeDef ADC_InitStruct; // 运行GPIOA和ADC1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); // PA5-IN5模拟输入 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化ADC1 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); // 配置通道5 ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_1Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5); ADC_AutoInjectedConvCmd(ADC1, ENABLE); // 启动ADC1 ADC_Cmd(ADC1, ENABLE); // 校准ADC1 ADC_StartCalibration(ADC1);//ADC转化校准 while(ADC_GetCalibrationStatus(ADC1));}unsigned int ADC1_Conv(void){
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能软件触发 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//获取标志状态 return ADC_GetConversionValue(ADC1);//获取ADC转化值}unsigned int ADC1_InjeConv(void){
ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC)); ADC_ClearFlag(ADC1, ADC_FLAG_JEOC); return ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);}

按键扫描

unsigned char AKEY_Read(void){
unsigned char ucAkey_Val = 0; unsigned int uiAdc_Val = ADC1_Conv(); if(uiAdc_Val < 6000) {
Delay_AKEY(100); uiAdc_Val = ADC1_Conv(); if(uiAdc_Val < 4095) {
if(uiAdc_Val > 3745) ucAkey_Val = 8; else if(uiAdc_Val > 3193) ucAkey_Val = 7; else if(uiAdc_Val > 2623) ucAkey_Val = 6; else if(uiAdc_Val > 2061) ucAkey_Val = 5; else if(uiAdc_Val > 1452) ucAkey_Val = 4; else if(uiAdc_Val > 841) 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

这里注意这一段的配置

if(uiAdc_Val < 6000) 可以较大不能较小
{
Delay_AKEY(100);
uiAdc_Val = ADC1_Conv();
if(uiAdc_Val < 4095) 不能过大或过小

main.c程序

#include "key.h"#include "led.h"#include "lcd.h"#include "seg.h"#include "adc.h"#include "usart.h"unsigned char ucLed = 1;unsigned char ucAkey_Long;unsigned long ulTick_ms, ulAkey_Time;unsigned int key_number;//LCD显示unsigned char  pucStr[21];unsigned char ucDot;  //小数点int seg[3]={
17,17,17};void LCD_Proc(void);void AKEY_Proc(void);void ledAll_turn (void);void seg_left(void);int main(void){
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz) LED_Init(); STM3210B_LCD_Init(); LCD_Clear(Blue); LCD_SetBackColor(Blue); LCD_SetTextColor(White); ADC1_Init_AKEY(); SEG_Init(); while(1) {
AKEY_Proc(); LCD_Proc(); SEG_Disp(seg[2],seg[1],seg[0],ucDot); }}unsigned char ucAkey_Val;int jishu=0;void AKEY_Proc(void){
ucAkey_Val = AKEY_Read(); if(ucAkey_Val != ucAkey_Long) {
ucAkey_Long = ucAkey_Val; ulAkey_Time = ulTick_ms; } else ucAkey_Val = 0; if(ucAkey_Val) {
key_number=ucAkey_Val; ledAll_turn(); seg_left(); } }//函数功能:数码管数值每按一次左移一位void seg_left(void){
ucDot++; if(seg[0]) {
seg[2]=seg[1]; seg[1]=seg[0]; } seg[0]=ucAkey_Val;}//函数功能:LCD上显示键入值void LCD_Proc(void){
//注:使用sprintf需要加"usart.h" sprintf((char*)pucStr, " key number:%02d ", key_number); LCD_DisplayStringLine(Line4, pucStr);}//函数功能:控制所有LED翻转int ledall[8]={
1 ,2 ,4, 8, 16, 32, 64 ,128 };int i;void ledAll_turn (void){
i=ucAkey_Val;if(ucLed == ledall[i-1]) ucLed=0;else ucLed = ledall[i-1]; LED_Disp(ucLed);}// SysTick中断处理程序void SysTick_Handler(void){
ulTick_ms++;}

完整工程下载>>

选择第7个工程

作者:江多多(在校学生)

版权所有,欢迎保留原文链接进行转载:)

不忘初心,牢记使命,励志成为一名优秀的嵌入式工程师! (我的第七篇博客)

你可能感兴趣的文章