本程序对应的开发板为蓝桥杯嵌入式开发板stm32f103rbt6,为中型mcu。开发板的矩阵键盘采用adc实现,电路图如下
通过测量adc测量电压从而得出按键位置。这里给出一个各按键对应的电压值和转换值的表[转换值=4095*电压值/(10000+电压值)]
按键 s1 s2 s3 s4 s5 s6 s7 s8
电阻值 0 510 1710 3310 5110 8110 12810 22810
转换值 0 198 597 1018 1384 1833 2299 2846
表中的转换值只是理论计算值,扩展板个按键的实际转换值可能与表中不同,具体转换值可通过实际的adc值进行获取。
连接
P4.5(PA5)-P5.5(AKEY)
#include "stm32f10x.h"
#include "lcd.h"
#include "stdio.h"
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
void SEG_Init(void);
void SEG_Dis(unsigned char data1,unsigned char data2,unsigned char data3,unsigned char dot);
unsigned int Seg=0;
unsigned char Sec=0,Sec1=0,dot=0,AKEY_Long;
unsigned long Tick_ms=0,AKEY_Time;
u8 string[20];
void ADC1_Init_AKEY(void);
unsigned char AKEY_Read(void);
void Delay_AKEY(unsigned int ms);
void AKEY_Proc(void);
unsigned int ADC1_Conv(void);
int main(void)
{
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
SEG_Init();
SEG_Dis(0x10,0x10,0x10,0);
ADC1_Init_AKEY();
LCD_DisplayStringLine(Line0," ");
LCD_DisplayStringLine(Line1," ");
LCD_DisplayStringLine(Line2," ");
LCD_DisplayStringLine(Line3," ");
LCD_DisplayStringLine(Line4," ");
LCD_DisplayStringLine(Line5," ");
LCD_DisplayStringLine(Line6," ");
LCD_DisplayStringLine(Line7," ");
LCD_DisplayStringLine(Line8," ");
LCD_DisplayStringLine(Line9," ");
while (1)
{
AKEY_Proc();
SEG_Dis(16,16,Seg,0);
}
}
void SEG_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2| GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void SEG_Dis(unsigned char data1,unsigned char data2,unsigned char data3,unsigned char dot)
{
unsigned char i;
unsigned long data;
unsigned char code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
data=((code[data3]<<16)+(code[data2]<<8)+(code[data1]));
data+=(dot&1)<<23;
data+=(dot&2)<<14;
data+=(dot%4)<<5;
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
for(i=0;i<24;i++)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_3);
if(data&0x800000)
GPIO_SetBits(GPIOA,GPIO_Pin_1);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
data<<=1;
GPIO_SetBits(GPIOA,GPIO_Pin_3);
}
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void AKEY_Proc(void)
{
unsigned int AKey_Val;
AKey_Val=AKEY_Read();
sprintf((char*)string, " Button Value:%d", AKey_Val);
LCD_DisplayStringLine(Line7,string);
if(AKey_Val!=AKEY_Long)
{
AKEY_Long=AKey_Val;
AKEY_Time=Tick_ms;
}
else
AKey_Val=0;
if(AKey_Val)
{
Seg=AKey_Val;
}
}
void ADC1_Init_AKEY(void){
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC1 Configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel14 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_13Cycles5);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
unsigned int ADC1_Conv(void)
{
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
unsigned char AKEY_Read(void)
{
unsigned char AKey_Val=0;
unsigned int ADC_Val= ADC1_Conv();
sprintf((char*)string," Button ADC:%04X", ADC_Val);
LCD_DisplayStringLine(Line6,string);
if(ADC_Val<3470)
{
Delay_AKEY(100);
ADC_Val=ADC1_Conv();
if(ADC_Val<3470)
{
if(ADC_Val>2572)
AKey_Val=8;
else if(ADC_Val>2066)
AKey_Val=7;
else if(ADC_Val>1608)
AKey_Val=6;
else if(ADC_Val>1201)
AKey_Val=5;
else if(ADC_Val>807)
AKey_Val=4;
else if(ADC_Val>498)
AKey_Val=3;
else if(ADC_Val>99)
AKey_Val=2;
else
AKey_Val=1;
}
}
return AKey_Val;
}
void Delay_AKEY(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<7992;j++);
}
该程序在数码管的基础上进行修改的,具体实现功能是,显示adc的值,与按键的值,同时将按键的值通过数码管显示。 |