
五個引腳分別為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:最好設置個延時)
