程序代码篇---PS2手柄控制


文章目录

  • 前言
  • 1. 头文件引入
  • 2. 红灯模式下的按键配置
  • 3. 绿灯模式下的按键配置
  • 4. 函数声明
  • 5. PS2设备控制初始化
  • 6. 循环执行工作
  • 7. 处理麦轮小车电机摇杆控制
  • 8. 处理手柄按键字符
  • 总结


前言

这段代码是一个用于控制PS2手柄的应用程序,主要功能是通过PS2手柄来控制一个小车的运动。代码分为几个部分,包括初始化、按键处理、电机控制等。下面我将逐句详细解释这段代码。


1. 头文件引入

#include "app_ps2.h"
#ifndef _APP_PS2_H_
#define _APP_PS2_H_
#include "main.h"

//保存ps2指令
typedef struct
{
	/******************** 按下指令 *******************/
    /* 左边4个按键 */
    char pressed_left_up[32];
    char pressed_left_right[32];
    char pressed_left_down[32];
    char pressed_left_left[32];

    /* 右边4个按键  */
    char pressed_right_up[32];
    char pressed_right_right[32];
    char pressed_right_down[32];
    char pressed_right_left[32];

    /* 中间两个按键  */
    char pressed_select[32];
    char pressed_start[32];

    /* 前面左右各两个按键  */
    char pressed_left_1[32];
    char pressed_left_2[32];
    char pressed_right_1[32];
    char pressed_right_2[32];
	
	char pressed_key_rocker_left[32];//摇杆按键
	char pressed_key_rocker_right[32];
	
	/******************** 释放指令 *******************/
    /* 左边4个按键 */
    char release_left_up[32];
    char release_left_right[32];
    char release_left_down[32];
    char release_left_left[32];

    /* 右边4个按键  */
    char release_right_up[32];
    char release_right_right[32];
    char release_right_down[32];
    char release_right_left[32];

    /* 中间两个按键  */
    char release_select[32];
    char release_start[32];

    /* 前面左右各两个按键  */
    char release_left_1[32];
    char release_left_2[32];
    char release_right_1[32];
    char release_right_2[32];
	
	char release_key_rocker_left[32];//摇杆按键
	char release_key_rocker_right[32];
} ps2_cmd_t;

void app_ps2_init(void);
void app_ps2_run(void);
#endif

这里引入了 app_ps2.h 头文件,该文件包含了与PS2手柄相关的函数声明、宏定义和数据结构。

2. 红灯模式下的按键配置

const char *pre_cmd_set_red[PSX_BUTTON_NUM] = {
	// 手柄按键功能字符串 红灯模式下使用
	"", // L2
	"", // R2
	"", // L1
	"", // R1
	"", // RU
	"", // RR
	"", // RD
	"", // RL
	"",					 // SE
	"",							 // AL
	"",							 // AR
	"",					 // ST
	"", // LU
	"", // LR
	"", // LD
	"", // LL
};

这是一个字符串数组,定义了在红灯模式下每个按键对应的命令字符串。每个字符串代表一个按键的功能,例如 L2、R2 等。

3. 绿灯模式下的按键配置

const char *pre_cmd_set_grn[PSX_BUTTON_NUM] = {
	// 绿灯模式下按键的配置
	"",			   // L2  左上500
	"",			   // R2	右上500
	"",		   // L1	左上1000
	"",		   // R1	右上1000
	"",	   // RU	前进1000
	"",   // RR	右平移1000
	"", // RD	后退1000
	"",   // RL	左平移1000
	"",									   // SE
	"",											   // AL
	"",											   // AR
	"",									   // ST
	"",		   // LU	前进500
	"",	   // LR	右转500
	"",	   // LD	后退500
	"",	   // LL	左转500
};

与红灯模式类似,这里定义了绿灯模式下每个按键对应的命令字符串。

4. 函数声明

void parse_psx_buf(unsigned char *buf, unsigned char mode);
void loop_ps2_car(void);

这里声明了两个函数,parse_psx_buf 用于解析PS2手柄的按键数据,loop_ps2_car 用于处理小车的电机控制

5. PS2设备控制初始化

void app_ps2_init(void)
{
	ps2_init(); /* PS2引脚初始化 */
}

app_ps2_init 函数用于初始化PS2手柄的引脚

6. 循环执行工作

void app_ps2_run(void)
{
	static unsigned char psx_button_bak[2] = {0};
	static u32 systick_ms_bak = 0;

	// 每50ms处理1次
	if (millis() - systick_ms_bak < 50)
		return;
	systick_ms_bak = millis();

	ps2_write_read(); /* 读取ps2数据 */

	loop_ps2_car(); /* 处理小车电机摇杆控制 */

	// 对比两次获取的按键值是否相同 ,相同就不处理,不相同则处理
	if ((psx_button_bak[0] == psx_buf[3]) && (psx_button_bak[1] == psx_buf[4]))
	{
	}
	else
	{
		// printf("parse_psx_buf\r\n");
		// 处理buf3和buf4两个字节,这两个字节存储这手柄16个按键的状态
		parse_psx_buf(psx_buf + 3, psx_buf[1]);
		psx_button_bak[0] = psx_buf[3];
		psx_button_bak[1] = psx_buf[4];
	}
}

app_ps2_run 函数是主循环函数,每50ms执行一次。它首先读取PS2手柄的数据,然后调用 loop_ps2_car 处理小车的电机控制。接着,它比较当前按键状态与上一次的状态,如果不同则调用 parse_psx_buf 处理按键事件。

7. 处理麦轮小车电机摇杆控制

void loop_ps2_car(void)
{
	float car_left1=0, car_right1=0, car_left2=0, car_right2=0;
	static float car_left1_bak = 0, car_right1_bak = 0, car_left2_bak = 0, car_right2_bak = 0;

	static u8 num = 10;

	if (psx_buf[1] != PS2_LED_RED)
		return;

	if (abs_int(127 - psx_buf[7]) > num)
	{
		car_left1=car_left1-(0x7f-psx_buf[7])*2;
		car_right1=car_right1+(0x7f-psx_buf[7])*2;
		car_left2=car_left2-(0x7f-psx_buf[7])*2;
		car_right2=car_right2+(0x7f-psx_buf[7])*2;
	}
	if (abs_int(127 - psx_buf[8]) > num)
	{
		car_left1=car_left1+(0x7f-psx_buf[8])*2;
		car_right1=car_right1+(0x7f-psx_buf[8])*2;
		car_left2=car_left2+(0x7f-psx_buf[8])*2;
		car_right2=car_right2+(0x7f-psx_buf[8])*2;
	}
	if (abs_int(127 - psx_buf[5]) > num)
	{
		car_left1=car_left1-(0x7f-psx_buf[5])*2;
		car_right1=car_right1+(0x7f-psx_buf[5])*2;
		car_left2=car_left2+(0x7f-psx_buf[5])*2;
		car_right2=car_right2-(0x7f-psx_buf[5])*2;
	}
	if (abs_int(127 - psx_buf[6]) > num)
	{
		car_left1=car_left1+(0x7f-psx_buf[6])*2;
		car_right1=car_right1+(0x7f-psx_buf[6])*2;
		car_left2=car_left2+(0x7f-psx_buf[6])*2;
		car_right2=car_right2+(0x7f-psx_buf[6])*2;
	}

	if ((car_left1_bak != car_left1) || (car_right1_bak != car_right1) || (car_left2_bak != car_left2) || (car_right2_bak != car_right2))
	{
		motor_speed_set(car_left1 / 1000, car_right1 / 1000, car_left2 / 1000, car_right2 / 1000);
	}
	car_left1_bak = car_left1;
	car_right1_bak = car_right1;

	car_left2_bak = car_left2;
	car_right2_bak = car_right2;
}

loop_ps2_car 函数用于处理小车的电机控制。它根据PS2手柄的摇杆数据计算小车的四个电机的速度,并调用 motor_speed_set 函数设置电机速度。

8. 处理手柄按键字符

void parse_psx_buf(unsigned char *buf, unsigned char mode)
{
	u8 i, pos = 0;
	static u16 bak = 0xffff, temp, temp2;
	temp = (buf[0] << 8) + buf[1];

	if (bak != temp)
	{
		temp2 = temp;
		temp &= bak;
		for (i = 0; i < 16; i++)
		{ // 16个按键一次轮询
			if ((1 << i) & temp)
			{
			}
			else
			{
				if ((1 << i) & bak)
				{ // press 表示按键按下了

					memset(uart_receive_buf, 0, sizeof(uart_receive_buf));
					if (mode == PS2_LED_RED)
					{
						memcpy((char *)uart_receive_buf, (char *)pre_cmd_set_red[i], strlen(pre_cmd_set_red[i]));
					}
					else if (mode == PS2_LED_GRN)
					{
						memcpy((char *)uart_receive_buf, (char *)pre_cmd_set_grn[i], strlen(pre_cmd_set_grn[i]));
					}
					else
						continue;
					// zx_uart_send_str(uart_receive_buf);
					pos = str_contain_str(uart_receive_buf, "^");
					if (pos)
						uart_receive_buf[pos - 1] = '\0';
					if (str_contain_str(uart_receive_buf, "$"))
					{
						uart1_close();
						uart_get_ok = 0;
						strcpy((char *)cmd_return, (char *)uart_receive_buf + 11);
						strcpy((char *)uart_receive_buf, (char *)cmd_return);
						uart_get_ok = 1;
						uart1_open();
						uart_mode = 1;
					}
					else if (str_contain_str(uart_receive_buf, "#"))
					{
						uart1_close();
						uart_get_ok = 0;
						strcpy((char *)cmd_return, (char *)uart_receive_buf + 11);
						strcpy((char *)uart_receive_buf, (char *)cmd_return);
						uart_get_ok = 1;
						uart1_open();
						uart_mode = 2;
					}
					bak = 0xffff;
				}
				else
				{ // release 表示按键松开了

					memset(uart_receive_buf, 0, sizeof(uart_receive_buf));
					if (mode == PS2_LED_RED)
					{
						memcpy((char *)uart_receive_buf, (char *)pre_cmd_set_red[i], strlen(pre_cmd_set_red[i]));
					}
					else if (mode == PS2_LED_GRN)
					{
						memcpy((char *)uart_receive_buf, (char *)pre_cmd_set_grn[i], strlen(pre_cmd_set_grn[i]));
					}
					else
						continue;

					pos = str_contain_str(uart_receive_buf, "^");
					if (pos)
					{
						if (str_contain_str(uart_receive_buf + pos, "$"))
						{
							// uart1_close();
							// uart_get_ok = 0;
							strcpy((char *)cmd_return, (char *)uart_receive_buf + pos);
							cmd_return[strlen((char *)cmd_return) - 1] = '\0';
							strcpy((char *)uart_receive_buf, (char *)cmd_return);
							parse_cmd(uart_receive_buf);
							// uart_get_ok = 1;
							// uart_mode = 1;
						}
						else if (str_contain_str(uart_receive_buf + pos, "#"))
						{
							// uart1_close();
							// uart_get_ok = 0;
							strcpy((char *)cmd_return, (char *)uart_receive_buf + pos);
							cmd_return[strlen((char *)cmd_return) - 1] = '\0';
							strcpy((char *)uart_receive_buf, (char *)cmd_return);
							parse_action(uart_receive_buf);
							// uart_get_ok = 1;
							// uart_mode = 2;
						}
						// uart1_send_str(uart_receive_buf);
					}
				}
			}
		}
		bak = temp2;
	}
	return;
}

parse_psx_buf 函数用于解析PS2手柄的按键数据。它根据按键的状态(按下或松开)以**及当前模式(红灯或绿灯)来执行相应的操作。**函数内部通过 str_contain_str 函数来解析命令字符串,并根据命令类型调用 parse_cmdparse_action 函数。

总结

这段代码的主要功能是通过PS2手柄来控制一个小车的运动。通过读取手柄的按键和摇杆数据,并根据不同的模式(红灯或绿灯)来执行相应的操作。代码中使用了大量的字符串处理和状态判断,以实现复杂的控制逻辑。




---



你可能感兴趣的:(嵌入式硬件篇,程序代码篇,数据库,PS2,麦克纳姆轮子)