标签:mod key art oid 原理 one 使用 测试 static
五个引脚分别为GND +5V x y z(按下)
原理:
ps2摇杆 游戏摇杆模块 电子积木标准接口 及2.54mm插针 接口引出。
1、十字摇杆为一个双向的10k电阻器,随着摇杆方向不同,抽头的阻值随着变化。
2、本模块使用5v供电,原始状态下x,y读出电压为2.5v左右,当随箭头方向按下,读 电压值随着增加,最大到5v;箭头相反方向按下,读出电压值减少,最小为0v。
也就是说XY坐标可以通过ADC判断电压来确定位置!z是一个KEY
思路:
用两个ADC通道读取xy电压 一个I/O口来检测是否按下
ADC配置
1 void Adc_Init(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 ADC_InitTypeDef ADC_InitStruct; 5 6 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE); 7 8 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2; 9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 11 GPIO_Init(GPIOA, &GPIO_InitStructure); 12 13 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC的时钟,6分频,72m/6=12m<14m 14 ADC_DeInit(ADC1);//复位ADC1 15 16 ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//不开启连续转换(故为单次转换) 17 ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//数据右对齐 18 ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发方式为软件触发,所以设置为None 19 ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//独立模式 20 ADC_InitStruct.ADC_NbrOfChannel=2;//一个通道 21 ADC_InitStruct.ADC_ScanConvMode=DISABLE;//扫描模式关闭 22 ADC_Init(ADC1,&ADC_InitStruct); 23 24 ADC_Cmd(ADC1,ENABLE);//使能ADC1 25 26 //校准 27 ADC_ResetCalibration(ADC1);//使能复位校准 28 while(ADC_GetResetCalibrationStatus(ADC1));//等待使能复位校准结束 29 ADC_StartCalibration(ADC1);//开始校准 30 while(ADC_GetCalibrationStatus(ADC1));//等待结束校准 31 32 } 33 //获得ADC值 34 //ch:通道值 0~3 35 u16 Get_Adc(u8 ch) 36 { 37 ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); 38 /*ADC规则通道配置函数 ADC1的某个通道,第1个转换,采样周期239.5 39 如果有多个规则通道,需要多次配置此函数*/ 40 41 ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件转换启动 42 43 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//转换标志位,转换完成结束循环 44 45 return ADC_GetConversionValue(ADC1);//返回转换结果 46 } 47 48 u16 Get_Adc_Average(u8 ch,u8 times) 49 { 50 u32 temp_val=0; 51 u8 t; 52 for(t=0;t<times;t++) 53 { 54 temp_val+=Get_Adc(ch); 55 delay_ms(5); 56 } 57 return temp_val/times; 58 }
KEY配置
void key_init()//key--PC0 { GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //配置引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOC } int KEY_Scan(int mode) { static u8 key_up=1; if(mode) key_up=1; if(key_up && (KEY==1)) { delay_ms(10); key_up=0; if(KEY==1) return 1; } else if(KEY==0) key_up=1; return 0; }
经过测试发现位置个电压之间存在如下关系
(视情况而定)
故写出如下判断函数
void Jok_boy() { float tempx,tempy; u8 x,y,key,z; u16 adcx,adcy; key=KEY_Scan(0);//不支持连按 if(key) z=1; else z=0; adcx=Get_Adc_Average(ADC_Channel_1,2); adcy=Get_Adc_Average(ADC_Channel_2,2); tempx=(float)adcx*(3.3/4096);/*12位adc所以最大将3.3v电压分成4096份*/ tempy=(float)adcy*(3.3/4096); x=tempx;y=tempy; if(x==2&&y==3) printf("Up"); else if(x==3&&y==3) printf("Up to Left"); else if(x==3&&y==2) printf("Left"); else if(x==3&&y==0) printf("Down to Left"); else if(x==2&&y==0) printf("Down"); else if(x==0&&y==0) printf("Down to Right"); else if(x==0&&y==2) printf("Right"); else if(x==0&&y==3) printf("Up to Right"); if(z==1)//按下key printf("ENTER\r\n"); else printf("输入ing……\r\n"); }
主函数如下
#include "delay.h" #include "sys.h" #include "usart.h" #include "JOK_BOY.h" int main(void) { delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200); Adc_Init(); key_init(); while(1) { Jok_boy(); } }
结果如下
(ps:最好设置个延时)
标签:mod key art oid 原理 one 使用 测试 static
原文地址:https://www.cnblogs.com/yasina/p/12430139.html