博客
关于我
蓝桥杯STM32F103RB扩展板ADC按键
阅读量:632 次
发布时间:2019-03-14

本文共 4594 字,大约阅读时间需要 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个工程

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

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

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

你可能感兴趣的文章
MySQL中ON DUPLICATE KEY UPDATE的介绍与使用、批量更新、存在即更新不存在则插入
查看>>
MYSQL中TINYINT的取值范围
查看>>
MySQL中UPDATE语句的神奇技巧,让你操作数据库如虎添翼!
查看>>
Mysql中varchar类型数字排序不对踩坑记录
查看>>
MySQL中一条SQL语句到底是如何执行的呢?
查看>>
MySQL中你必须知道的10件事,1.5万字!
查看>>
MySQL中使用IN()查询到底走不走索引?
查看>>
Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
查看>>
MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
查看>>
mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
查看>>
mysql中出现Unit mysql.service could not be found 的解决方法
查看>>
mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
查看>>
Mysql中各类锁的机制图文详细解析(全)
查看>>