wenbo2005.online

学习记录 / STM32

Joystick

STM322024-02-12

采用PS2游戏摇杆模块(Joystick)更适合机器臂的控制//=================================https://zhuanlan.zhihu.com/p/81884920

VRX,VRY(x,y)输出模拟量,相当于两个电位器;(模拟量STM32无法识别,需要转换为数字量  ->  ADC)

SW(z)输出数字量,相当于按键,没按是为1,按下为0;

开启DMA可以减轻CPU负担

1,完成STM32Cubemx的基本配置(RCC,SYS,时钟树);

2,开启ADC1的6,7通道:

数据对齐方式 -> 右对齐扫描转换,连续转换 -> 激活转换次数 -> 2

六,七通道采样周期 -> 239.5//=============防止太快

再开启ADC的DMA:循环模式,从外设到内存,高速;

        Memory地址自增,Peripheral与Memory的数据宽度都是Word

把PB8作为输入引脚(GPIO_Input),命名为JOY_Z,并上拉;(可以开一个串口,打印相关参数)

3,给Joystick模块5.0V电压,STM32的AD转换为12bit,AD转换的结果2^12 = 4096;

     HAL_ADC_Start_DMA(&hadc1, JOY_VALUE, 2);//=========================================开启ADC

参数:

    uint32_t JOY_VALUE[2];//===============================================通过DMA通道转换得到的值
    __IO float ADC_VOL_VALUE[2];//=========================================保存转换计算后的电压值

    int JOY_X, JOY_Y, JOY_Z ;
        uint8_t key_value ;

        //电压
        ADC_VOL_VALUE[0] = (float)(JOY_VALUE[0] & 0xFFF) * 5.0 / 4096 ;//===================================取12bit数值;
        ADC_VOL_VALUE[1] = (float)(JOY_VALUE[1] & 0xFFF) * 5.0 / 4096 ;
        printf("x:%.2fv   y:%.2fv\n", ADC_VOL_VALUE[0], ADC_VOL_VALUE[1]);//=========================打印电压值(0~5.0V);
        //只取8位有效数据
        JOY_X = JOY_VALUE[0] & 0xFF;
        JOY_Y = JOY_VALUE[1] & 0xFF;
        JOY_Z = HAL_GPIO_ReadPin(JOY_Z_GPIO_Port, JOY_Z_Pin);
        printf("x:%d   y:%d  z:%d\n", JOY_X,    JOY_Y,    JOY_Z);//=============================打印X,Y值(0~255),Z值(0或1);

    //===========================================================对JOY_X,JOY_Y,JOY_Z的值进行判断,并实现相应程序

        //key_value = GET_KEY_VALUE(JOY_X, JOY_Y, JOY_Z);=======================附加程序
    HAL_Delay(200);//============================================防止打印过快

int fputc(int ch, FILE* file)//========================================定义printf的重定向函数fputc,满足串口调试打印(魔术棒 -> 开启USB)
{
    return HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 100);
}

//=====================================================================附加程序,显示当前状态============================================================\\

#define UP         0
#define DOWN       1
#define LEFT       2
#define RIGHT      3
#define LEFT_UP    4
#define LEFT_DOWN  5
#define RIGHT_UP   6
#define RIGHT_DONW 7
#define ENTER      8
#define UNKNOW_KEY 99

uint8_t GET_KEY_VALUE(int x, int y, int z)//========================获取摇杆键值,经过动手实践得出的6个方向的数值以及确定返回的键值的映射
{
    if((0 == x) && (y > 100 && y < 255))
        return UP;
    else if((255 == x) && (y > 0 && y < 255))
        return DOWN ;
    else if((x > 0 && x < 255) && (255 == y))
        return LEFT ;
    else if((x > 0 && x < 255) && (0 == y))
        return RIGHT ;
    else if((0 == x) && (255 == y))
        return LEFT_UP ;
    else if((255 == x) && (255 == y))
        return LEFT_DOWN ;
    else if((0 == x) && (0 == y))
        return RIGHT_UP ;
    else if((255 == x) && (0 == y))
        return RIGHT_DONW ;
    else if(x > 0 && y > 0 && 0 == z)
        return ENTER ;

    return UNKNOW_KEY ;
}

    switch(key_value)
        {
            case UP :
                printf("上\n");
                break ;

            case DOWN :
                printf("下\n");
                break ;

            case LEFT :
                printf("左\n");
                break ;

            case RIGHT  :
                printf("右\n");
                break ;

           case LEFT_UP:
                printf("左上\n");
                break ;

            case LEFT_DOWN:
                printf("左下\n");
                break ;

            case RIGHT_UP:
                printf("右上\n");
                break ;

            case RIGHT_DONW :
                printf("右下\n");
                break ;

            case ENTER :
                printf("确认\n");
                break ;

        default:
                break ;
     }