博客
关于我
蓝桥杯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个工程

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

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

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

你可能感兴趣的文章
multisim变压器反馈式_穿过隔离栅供电:认识隔离式直流/ 直流偏置电源
查看>>
mysql csv import meets charset
查看>>
multivariate_normal TypeError: ufunc ‘add‘ output (typecode ‘O‘) could not be coerced to provided……
查看>>
MySQL DBA 数据库优化策略
查看>>
multi_index_container
查看>>
MySQL DBA 进阶知识详解
查看>>
Mura CMS processAsyncObject SQL注入漏洞复现(CVE-2024-32640)
查看>>
Mysql DBA 高级运维学习之路-DQL语句之select知识讲解
查看>>
mysql deadlock found when trying to get lock暴力解决
查看>>
MuseTalk如何生成高质量视频(使用技巧)
查看>>
mutiplemap 总结
查看>>
MySQL DELETE 表别名问题
查看>>
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>
Mysql group by
查看>>
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>