本程序编写基于秉火霸道STM32F103ZET6运行环境。
今天来玩一个PS2游戏摇杆模块,也被称为Joystick,根据模块提供的手册,下面来了解下工作原理以及如何来应用。
看到这里我们就明白了,x,y是模拟量,而z是一个二值数据,在这里,可以利用STM32的ADC控制器来读取X,Y的输出,Z轴就很简单了,把它当作普通按键就可以了。
一、打开CubeMX进行基础配置
1.1、配置外部时钟
1.2、配置调试器
1.3、配置串口调试,默认即可
1.4、配置ADC
关于ADC输入通道在STM32F103ZET6这款MCU里的分配表
设置数据右对齐、使能扫描和连续转换,间断转换模式关闭,使能通道,这里选择两个通道,分别是通道6和通道7,设置好两个通道的转换周期,默认为最大。
使能DMA,这样可以为CPU减负。
设置ADC1的DMA1通道1,外设到内存方向,循环模式,地址自增及数据宽度。
1.5、配置Z轴输入IO
1.6、生成基本工程
二、增加软件逻辑
//定义printf的重定向函数fputc,满足串口调试打印
int fputc(int ch, FILE* file)
{
return HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 100);
}
//通过DMA通道转换得到的值
uint32_t JOY_VALUE[2];
//保存转换计算后的电压值
__IO float ADC_VOL_VALUE[2];
#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)
{
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 ;
}
以上的GET_KEY_VALUE是经过动手实践得出的6个方向的数值以及确定返回的键值的映射。
主函数实现:
int main(void)
{
/* USER CODE BEGIN 1 */
int JOY_X, JOY_Y, JOY_Z ;
uint8_t key_value ;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1, JOY_VALUE, 2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//3.3V位AD转换的参考电压值,STM32的AD转换为12bit,所以2^12=4096
//故当输入参考电压为3.3V时,AD转换的结果为4096
//取12bit数值
ADC_VOL_VALUE[0] = (float)(JOY_VALUE[0] & 0xFFF) * 3.3 / 4096 ;
ADC_VOL_VALUE[1] = (float)(JOY_VALUE[1] & 0xFFF) * 3.3 / 4096 ;
printf("x:%.2fv y:%.2fv\n", ADC_VOL_VALUE[0], ADC_VOL_VALUE[1]);
//只取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);
key_value = GET_KEY_VALUE(JOY_X, JOY_Y, JOY_Z);
printf("x:%d y:%d z:%d\n", JOY_X, JOY_Y, JOY_Z);
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 ;
}
HAL_Delay(200);
}
/* USER CODE END 3 */
}
三、实验结果
当没有拨动摇杆时:
当拨动档杆向左时:
当按下确认时候,Z轴输出为0