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

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

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

加入了ADC按键和数码管的功能扩展板,实现了通过ADC采集按键值并显示在数码管上。板子共配备8个ADC按键,分别对应数字1到8,通过键入不同的值可以实现数码管向左移动显示的效果。

实验功能:

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

原理图:ADC按键通过接上电阻,形成不同的分压电路,通过ADC转换后可以测得不同按键按下的值。每段按键加上电阻,达到分压的效果,通过ADC转换,就可以测得不同按键按下的值。

计算公式:转换值=4095×R/(1000+R)

此处R1的值就是1000
eg:
S1:接GND采集到的值为0
S2:4095
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 < ms; i++) {        for(j = 0; j < 1000000; j++) {        }    }}

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;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个工程

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

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

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

你可能感兴趣的文章
Objective-C实现SVM支持向量机算法(附完整源码)
查看>>
Objective-C实现sylvester西尔维斯特方程算法(附完整源码)
查看>>
Objective-C实现tabu search禁忌搜索算法(附完整源码)
查看>>
Objective-C实现tanh函数功能(附完整源码)
查看>>
Objective-C实现TCP Server 多线程同时连接多个客户端(附完整源码)
查看>>
Objective-C实现TCP拥塞控制(附完整源码)
查看>>
Objective-C实现Tenengrad梯度函数(附完整源码)
查看>>
Objective-C实现ternary search三元搜索算法(附完整源码)
查看>>
Objective-C实现TernarySearch三分查找算法(附完整源码)
查看>>
Objective-C实现The Game of Life 生命游戏算法(附完整源码)
查看>>
Objective-C实现tim sort排序算法(附完整源码)
查看>>
Objective-C实现Timsort算法(附完整源码)
查看>>
Objective-C实现TOPK算法(附完整源码)
查看>>
Objective-C实现topological sort拓扑排序算法(附完整源码)
查看>>
Objective-C实现topologicalSort拓扑排序算法(附完整源码)
查看>>
Objective-C实现trapezoidal rule梯形法则算法(附完整源码)
查看>>
Objective-C实现Trapping Rain Water捕获雨水问题算法(附完整源码)
查看>>
Objective-C实现Travelling Salesman算法(附完整源码)
查看>>
Objective-C实现tree sort树排序算法(附完整源码)
查看>>
Objective-C实现UDP内网穿透(附完整源码)
查看>>