双轴xy摇杆按键
+5V:接电源
VRx:输出x轴的模拟量
VRy:输出x轴的模拟量
SW:z轴的按键,需将R5焊接一个限流电阻才能使用,拉高,低电平触发
CubeMX配置
PB1接VRx,PB0接VRy,PB8接SW
PB8输出模式上拉,PB0为ADC1_IN8,PB1为ADC1_IN9
ADC配置参考:我的文章《ADC多通道采样》的DMA部分:
https://blog.csdn.net/weixin_60301126/article/details/131730675
采样时间按需求配置,这里不过多介绍。
以及串口和定时器的使用也参考我的文章进行使用:
https://blog.csdn.net/weixin_60301126/article/details/131327438
使用
uint16_t g_iAdcx[2];//缓存ADC采样值
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)g_iAdcx, sizeof(g_iAdcx) / sizeof(g_iAdcx[0]));
//我的连接方式g_iAdcx[0]采集y轴模拟量,g_iAdcx[1]采集x轴模拟量
u_RockerKey.h
#ifndef _U_ROCKERKEY_H_
#define _U_ROCKERKEY_H_
#include "main.h"
/*************************************/
// 说明
// PB0用于ADC1_IN8,连接摇杆VRy
// PB1用于ADC1_IN9,连接摇杆VRx
// PB8连接遥感SW
// 实现18种按键状态
/*************************************/
typedef struct
{
uint32_t Y;
uint32_t X;
uint32_t Z;
}xyzVal_struct; //xyz轴值结构体
typedef enum
{
KEYSTOP = 0, //摇杆不动 /* 0 */
KEYUP, //摇杆上推 /* 1 */
KEYSUP, //摇杆慢上推 /* 2 */
KEYDOWN, //摇杆下推 /* 3 */
KEYSDOWN, //摇杆慢下推 /* 4 */
KEYLEFT, //摇杆左推 /* 5 */
KEYSLEFT, //摇杆慢左推 /* 6 */
KEYRIGHT, //摇杆右推 /* 7 */
KEYSRIGHT, //摇杆慢右推 /* 8 */
KEYPRESS, //摇杆按下 /* 9 */
KEYUPLF, //摇杆上左推 /* 10 */
KEYSUPLF, //摇杆慢上左推 /* 11 */
KEYUPRI, //摇杆上右推 /* 12 */
KEYSUPRI, //摇杆慢上左推 /* 13 */
KEYDOWNLF, //摇杆下左推 /* 14 */
KEYSDOWNLF, //摇杆慢下左推 /* 15 */
KEYDOWNRI, //摇杆下右推 /* 16 */
KEYSDOWNRI, //摇杆慢下右推 /* 17 */
KEYState_MAX /* 18 */
}E_RKEYState;
typedef enum
{
Yup = 0, //y轴上位 /* y0 */
Ysup, //y轴慢上位 /* y1 */
Ysp, //y轴中位 /* y2 */
Ydn, //y轴下位 /* y4 */
Ysdn //y轴慢下位 /* y3 */
}E_YaxleState;
typedef enum
{
Xlf = 0, //x轴左位 /* x0 */
Xslf, //x轴慢左位 /* x1 */
Xsp, //x轴中位 /* x2 */
Xri, //x轴右位 /* x4 */
Xsri //x轴慢右位 /* x3 */
}E_XaxleState;
typedef enum
{
Zup = 0, //z轴上位 /* z0 */
Zdn //z轴下位 /* z1 */
}E_ZaxleState;
void Get_xyzVal(void); //获取xy轴的值
E_RKEYState Get_KeyState(void); //获取摇杆的状态
void Test(E_RKEYState state); //测试摇杆功能
#endif //_U_ROCKERKEY_H_
u_RockerKey.c
#include "u_RockerKey.h"
#include "u_print.h"
xyzVal_struct xyzVal;
uint16_t g_iAdcx[2];
/*函数名称:获取xyz轴的值*/
/*形参:无 */
/*返回值:无 */
void Get_xyzVal(void)
{
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)g_iAdcx, sizeof(g_iAdcx) / sizeof(g_iAdcx[0]));
// PrintfDebug("Y = %d\r\nX = %d\r\n", g_iAdcx[0], g_iAdcx[1]);
if(g_iAdcx[0]<1000 && g_iAdcx[0]>0) //y0
xyzVal.Y = Yup;
else if(g_iAdcx[0]<1800 && g_iAdcx[0]>1000) //y1
xyzVal.Y = Ysup;
else if(g_iAdcx[0]<2200 && g_iAdcx[0]>1800) //y2
xyzVal.Y = Ysp;
else if(g_iAdcx[0]<3000 && g_iAdcx[0]>2200) //y3
xyzVal.Y = Ysdn;
else if(g_iAdcx[0]<4200 && g_iAdcx[0]>3000) //y4
xyzVal.Y = Ydn;
if(g_iAdcx[1]<1000 && g_iAdcx[1]>0) //x0
xyzVal.X = Xlf;
else if(g_iAdcx[1]<1800 && g_iAdcx[1]>1000) //x1
xyzVal.X = Xslf;
else if(g_iAdcx[1]<2200 && g_iAdcx[1]>1800) //x2
xyzVal.X = Xsp;
else if(g_iAdcx[1]<3000 && g_iAdcx[1]>2200) //x3
xyzVal.X = Xsri;
else if(g_iAdcx[1]<4200 && g_iAdcx[1]>3000) //x4
xyzVal.X = Xri;
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)
xyzVal.Z = Zdn;
else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
xyzVal.Z = Zup;
// PrintfDebug("xyzVal.X = %d\r\nxyzVal.Y = %d\r\nxyzVal.Z = %d\r\n", xyzVal.X, xyzVal.Y, xyzVal.Z);
}
/*函数名称:获取摇杆的状态 */
/*形参:无 */
/*返回值:keystate */
/*说明:keystate为E_RKEYState的变量,返回按键状态值*/
E_RKEYState Get_KeyState(void)
{
E_RKEYState keystate;
Get_xyzVal();
// PrintfDebug("%d %d\r\n", xyzVal.X, xyzVal.Y); //摇杆状态编码
if((xyzVal.Y == Ysp) && (xyzVal.X == Xsp) && (xyzVal.Z == Zup)) //x2 y2 z0 0
keystate = KEYSTOP;
else if((xyzVal.Y == Yup) && (xyzVal.X == Xsp)) //x2 y0 z0 1
keystate = KEYUP;
else if((xyzVal.Y == Ysup) && (xyzVal.X == Xsp)) //x2 y1 z0 2
keystate = KEYSUP;
else if((xyzVal.Y == Ydn) && (xyzVal.X == Xsp)) //x2 y4 z0 3
keystate = KEYDOWN;
else if((xyzVal.Y == Ysdn) && (xyzVal.X == Xsp)) //x2 y3 z0 4
keystate = KEYSDOWN;
else if((xyzVal.Y == Ysp) && (xyzVal.X == Xlf)) //x0 y2 z0 5
keystate = KEYLEFT;
else if((xyzVal.Y == Ysp) && (xyzVal.X == Xslf)) //x1 y2 z0 6
keystate = KEYSLEFT;
else if((xyzVal.Y == Ysp) && (xyzVal.X == Xri)) //x4 y2 z0 7
keystate = KEYRIGHT;
else if((xyzVal.Y == Ysp) && (xyzVal.X == Xsri)) //x3 y2 z0 8
keystate = KEYSRIGHT;
else if(xyzVal.Z == Zdn) //x2 y2 z1 9
keystate = KEYPRESS;
else if(((xyzVal.Y==Yup)&&(xyzVal.X==Xlf))||((xyzVal.Y==Yup)&&(xyzVal.X==Xslf))||((xyzVal.Y==Ysup)&&(xyzVal.X==Xlf))) //x01 y01 z0 10
keystate = KEYUPLF;
else if((xyzVal.Y == Ysup) && (xyzVal.X == Xslf)) //x1 y1 z0 11
keystate = KEYSUPLF;
else if(((xyzVal.Y==Yup)&&(xyzVal.X==Xri))||((xyzVal.Y==Yup)&&(xyzVal.X==Xsri))||((xyzVal.Y==Ysup)&&(xyzVal.X==Xri))) //x34 y01 z0 12
keystate = KEYUPRI;
else if((xyzVal.Y == Ysup) && (xyzVal.X == Xsri)) //x3 y1 z0 13
keystate = KEYSUPRI;
else if(((xyzVal.Y==Ydn)&&(xyzVal.X==Xlf))||((xyzVal.Y==Ydn)&&(xyzVal.X==Xslf))||((xyzVal.Y==Ysdn)&&(xyzVal.X==Xlf))) //x01 y34 z0 14
keystate = KEYDOWNLF;
else if((xyzVal.Y == Ysdn) && (xyzVal.X == Xslf)) //x1 y3 z0 15
keystate = KEYSDOWNLF;
else if(((xyzVal.Y==Ydn)&&(xyzVal.X==Xri))||((xyzVal.Y==Ydn)&&(xyzVal.X==Xsri))||((xyzVal.Y==Ysdn)&&(xyzVal.X==Xri))) //x34 y34 z0 16
keystate = KEYDOWNRI;
else if((xyzVal.Y == Ysdn) && (xyzVal.X == Xsri)) //x3 y3 z0 17
keystate = KEYSDOWNRI;
else
keystate = KEYState_MAX;
// PrintfDebug("keystate = %d\r\n", keystate);
return keystate;
}
/*函数名称:测试摇杆功能 */
/*形参:E_RKEYState state */
/*返回值:无 */
void Test(E_RKEYState state)
{
switch(state)
{
case KEYSTOP:PrintfDebug("No State\r\n");
break;
case KEYUP:PrintfDebug("Key Up\r\n");
break;
case KEYSUP:PrintfDebug("Key Slowly Up\r\n");
break;
case KEYDOWN:PrintfDebug("Key Down\r\n");
break;
case KEYSDOWN:PrintfDebug("Key Slowly Down\r\n");
break;
case KEYLEFT:PrintfDebug("Key Left\r\n");
break;
case KEYSLEFT:PrintfDebug("Key Slowly Left\r\n");
break;
case KEYRIGHT:PrintfDebug("Key Right\r\n");
break;
case KEYSRIGHT:PrintfDebug("Key Slowly Right\r\n");
break;
case KEYPRESS:PrintfDebug("Press Key\r\n");
break;
case KEYUPLF:PrintfDebug("Key Up Left\r\n");
break;
case KEYSUPLF:PrintfDebug("Key Slowly Up Left\r\n");
break;
case KEYUPRI:PrintfDebug("Key Up Right\r\n");
break;
case KEYSUPRI:PrintfDebug("Key Slowly Up Right\r\n");
break;
case KEYDOWNLF:PrintfDebug("Key Down Left\r\n");
break;
case KEYSDOWNLF:PrintfDebug("Key Slowly Down Left\r\n");
break;
case KEYDOWNRI:PrintfDebug("Key Down Right\r\n");
break;
case KEYSDOWNRI:PrintfDebug("Key Slowly Down Right\r\n");
break;
case KEYState_MAX:PrintfDebug("State\r\n");
break;
default:
break;
}
}
main.c
static void Proc1sTask(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
MX_TIM6_Init();
PrintfDebug("OK\r\n");
while (1)
{
Proc100msTask();
}
}
static void Proc100msTask(void) //1s任务
{
if(Get100msFlag())
{
Test(Get_KeyState());
Clr100msFlag();
}
}