[IDE] 【RISC-V MCU CH32V103测评】+摇杆驱动程序

[复制链接]
 楼主| qjp1988113 发表于 2020-11-30 09:52 | 显示全部楼层 |阅读模式
本帖最后由 qjp1988113 于 2020-11-30 09:52 编辑

今天我们来调试一下摇杆,想以前打街机时,摇杆可是很爽的存在。估计也就80,90小时候会玩这玩意,00后的估计都很少见。
不废话了。摇杆其实就是2个电位器加一个按键的集合体。我这有现成的摇杆模块,引出5个引脚:GND VCC VRX(x方向判断) VRY(y方向判断) SW(Z方向判断)。
X,Y方向输出电位器对应的ADC值,Z方向仅0或1与按键类似。
好,我们开始程序搭建:
引脚定义:
ADCCH1-->PB0          (joy_y)
ADCCH2-->PB1          (joy_x)
GPIO_intput-->PB3     (joy_z)

joy.h:(我们之前调试过2路ADC,此时正好派上用处了)
  1. #ifndef JOY_H_
  2. #define JOY_H_

  3. #include "adc_timtrig.h"
  4. //定义判断的按键值
  5. #define UP         0
  6. #define DOWN       1
  7. #define LEFT       2
  8. #define RIGHT      3
  9. #define LEFT_UP    4
  10. #define LEFT_DOWN  5
  11. #define RIGHT_UP   6
  12. #define RIGHT_DONW 7
  13. #define ENTER      8
  14. #define UNKNOW_KEY 99

  15. //Z-->PB3
  16. #define JOY_Z_Value    GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3)

  17. extern u16  JOY_X, JOY_Y, JOY_Z ;

  18. void JOY_GPIO_Init(void);
  19. void GET_KEY_Basedata(void);
  20. uint8_t GET_KEY_VALUE(int x, int y, int z);


  21. #endif /* JOY_H_ */
joy.c:
  1. /*
  2. * joy.c
  3. *
  4. *  Created on: Nov 27, 2020
  5. *      Author: Administrator
  6. */

  7. #include "joy.h"
  8. #include "debug.h"


  9. //保存转换计算后的电压值
  10. float ADC_VOL_VALUE[2];
  11. //最终值
  12. u16  JOY_X, JOY_Y, JOY_Z ;

  13. //GPIO初始化,主要是Z PB3
  14. void JOY_GPIO_Init(void)
  15. {
  16.     GPIO_InitTypeDef  GPIO_InitStructure;

  17.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  18.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  19.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //内部上拉

  20.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  21. }

  22. //获取摇杆X,Y对应的ADC值   Z输入状态0或1
  23. //X-->PB0   Y-->PB1 Z-->PB3(按键仅0或1)
  24. void GET_KEY_Basedata(void)
  25. {
  26.     //3.3V位AD转换的参考电压值,STM32的AD转换为12bit,所以2^12=4096
  27.    //故当输入参考电压为3.3V时,AD转换的结果为4096
  28.    //取12bit数值
  29.     Get_Adc_Average(1);
  30.     //printf("X is :%d ,Y is :%d ",ADC_DATA[0],ADC_DATA[1]);
  31.     ADC_VOL_VALUE[0]= (float)(ADC_DATA[0] & 0xFFF) * 3.3 / 4096 ;
  32.     ADC_VOL_VALUE[1]= (float)(ADC_DATA[0] & 0xFFF) * 3.3 / 4096 ;
  33.     //printf("x:%.2fv   y:%.2fv\n", ADC_VOL_VALUE[0], ADC_VOL_VALUE[1]);
  34.     //只取高8位有效数据
  35.     JOY_X = ADC_DATA[0]>>4;
  36.     JOY_Y = ADC_DATA[1]>>4;
  37.     JOY_Z = JOY_Z_Value;

  38. }

  39. //获取摇杆键值
  40. uint8_t GET_KEY_VALUE(int x, int y, int z)
  41. {
  42.     if((0 == x) && (y > 100 && y < 255))
  43.         return RIGHT;//TEST
  44.     else if((255 == x) && (y > 0 && y < 255))
  45.         return LEFT ;//TEST
  46.     else if((x > 0 && x < 255) && (255 == y))
  47.         return DOWN ;//TEST
  48.     else if((x > 0 && x < 255) && (0 == y))
  49.         return UP ;//TEST
  50.     else if((0 == x) && (255 == y))
  51.         return RIGHT_DONW ;//
  52.     else if((255 == x) && (255 == y))
  53.         return LEFT_DOWN ;
  54.     else if((0 == x) && (0 == y))
  55.         return RIGHT_UP ;
  56.     else if((255 == x) && (0 == y))
  57.         return LEFT_UP ;//
  58.     else if(x > 0 && y > 0 && 0 == z)
  59.         return ENTER ;

  60.     return UNKNOW_KEY ;
  61. }
ADC相关的文件:
ADC.H
  1. /*
  2. * adc_timtrig.h
  3. *
  4. *  Created on: Nov 21, 2020
  5. *      Author: Administrator
  6. */

  7. #ifndef ADC_TIMTRIG_H_
  8. #define ADC_TIMTRIG_H_

  9. #include "ch32v10x.h"

  10. //PB0-->ADC_IN8
  11. //PB1-->ADC_IN9
  12. extern u16 tmpadcbuf[2];
  13. extern u16 ADC_DATA[2];

  14. void ADC_Function_Init(void);
  15. void TIM1_PWM_In( u16 arr, u16 psc, u16 ccp );
  16. u16* GetADC(void);
  17. u16* Get_Adc_Average(u8 times);

  18. #endif /* ADC_TIMTRIG_H_ */
ADC.C
  1. /*
  2. * adc_timtrig.c
  3. *
  4. *  Created on: Nov 21, 2020
  5. *      Author: Administrator
  6. */

  7. #include "adc_timtrig.h"
  8. #include "debug.h"


  9. u16 tmpadcbuf[2]={0};
  10. u16 ADC_DATA[2]={0};
  11. /*******************************************************************************
  12. * Function Name  : ADC_Function_Init
  13. * Description    : Initializes ADC collection.
  14. * Input          : None
  15. * Return         : None
  16. *******************************************************************************/
  17. void ADC_Function_Init(void)
  18. {
  19.     ADC_InitTypeDef ADC_InitStructure;
  20.     GPIO_InitTypeDef GPIO_InitStructure;

  21.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );
  22.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
  23.     RCC_ADCCLKConfig(RCC_PCLK2_Div8);
  24.     //PB0-->AD_IN8
  25.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  26.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  27.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  28.     //PB1-->AD_IN9
  29.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  30.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  31.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  32.     ADC_DeInit(ADC1);
  33.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  34.     ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  35.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  36.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_T1_CC4;
  37.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  38.     ADC_InitStructure.ADC_NbrOfChannel = 2;
  39.     ADC_Init(ADC1, &ADC_InitStructure);

  40.     ADC_InjectedSequencerLengthConfig(ADC1, 2);
  41.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);
  42.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5);

  43.     ADC_DiscModeChannelCountConfig( ADC1, 1);
  44.     ADC_InjectedDiscModeCmd(ADC1 , ENABLE);
  45.     ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);
  46.     ADC_Cmd(ADC1, ENABLE);

  47.     ADC_ResetCalibration(ADC1);
  48.     while(ADC_GetResetCalibrationStatus(ADC1));
  49.     ADC_StartCalibration(ADC1);
  50.     while(ADC_GetCalibrationStatus(ADC1));
  51. }

  52. /*******************************************************************************
  53. * Function Name  : TIM1_PWM_In
  54. * Description    : Initializes TIM1 PWM output.
  55. * Input          : arr: the period value.
  56. *                  psc: the prescaler value.
  57. *                                    ccp: the pulse value.
  58. * Return         : None
  59. *******************************************************************************/
  60. void TIM1_PWM_In( u16 arr, u16 psc, u16 ccp )
  61. {
  62.     GPIO_InitTypeDef GPIO_InitStructure;
  63.     TIM_OCInitTypeDef TIM_OCInitStructure;
  64.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

  65.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

  66.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  67.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  68.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  69.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  70.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  71.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  72.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  73.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  74.     TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);

  75.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  76.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  77.     TIM_OCInitStructure.TIM_Pulse = ccp;
  78.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  79.     TIM_OC4Init( TIM1, &TIM_OCInitStructure );

  80.     TIM_CtrlPWMOutputs(TIM1, ENABLE );
  81.     TIM_OC4PreloadConfig( TIM1, TIM_OCPreload_Disable );
  82.     TIM_ARRPreloadConfig( TIM1, ENABLE );
  83.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update );
  84.     TIM_Cmd( TIM1, ENABLE );
  85. }


  86. u16* GetADC(void)
  87. {

  88.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
  89.     ADC_ClearFlag( ADC1, ADC_FLAG_EOC);
  90.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC ));
  91.     ADC_ClearFlag( ADC1, ADC_FLAG_JEOC);

  92.     tmpadcbuf[0]=ADC1->IDATAR1;
  93.     tmpadcbuf[1]=ADC1->IDATAR2;

  94.     return tmpadcbuf;
  95. }

  96. u16* Get_Adc_Average(u8 times)
  97. {
  98.     u32 temp_val[2]={0,0};
  99.     u8 t;
  100.     for(t=0;t<times;t++)
  101.     {
  102.         GetADC();
  103.         temp_val[0]+=tmpadcbuf[0];
  104.         temp_val[1]+=tmpadcbuf[1];
  105.         Delay_Ms(5);
  106.     }
  107.     ADC_DATA[0]=temp_val[0]/times;
  108.     ADC_DATA[1]=temp_val[1]/times;

  109.     return ADC_DATA;
  110. }
在main.c初始化JOY相关引脚:
  1. ADC_Function_Init();
  2. TIM1_PWM_In( 1000, 48000-1, 500 );
  3. JOY_GPIO_Init();
在while里面查询。判断键值方向,并串口打印出:
  1. GET_KEY_Basedata();
  2.         key_value = GET_KEY_VALUE(JOY_X, JOY_Y, JOY_Z);
  3.         printf("x:%d   y:%d  z:%d\n", JOY_X,JOY_Y,JOY_Z);

  4.         switch(key_value)
  5.         {
  6.             case UP :
  7.                 printf("UP\n");
  8.                 break ;

  9.             case DOWN :
  10.                 printf("DOWN\n");
  11.                 break ;

  12.             case LEFT :
  13.                 printf("LEFT\n");
  14.                 break ;

  15.             case RIGHT  :
  16.                 printf("RIGHT\n");
  17.                 break ;

  18.             case LEFT_UP:
  19.                 printf("LEFT_UP\n");
  20.                 break ;

  21.             case LEFT_DOWN:
  22.                 printf("LEFT_DOWN\n");
  23.                 break ;

  24.             case RIGHT_UP:
  25.                 printf("RIGHT_UP\n");
  26.                 break ;

  27.             case RIGHT_DONW :
  28.                 printf("RIGHT_DONW\n");
  29.                 break ;

  30.             case ENTER :
  31.                 printf("ENTER\n");
  32.                 break ;

  33.             default:
  34.                 break ;
  35.         }
编译下载,对摇杆进行不同方向的操作,看串口输出:
QQQ.png 这样我们的摇杆就能正常控制了,里游戏移植又近了一步了。





w494143467 发表于 2020-11-30 15:14 | 显示全部楼层
大学玩小车的时候用的就是摇杆控制小车。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部