基于RTOS的STM32游戏机

1.游戏机的主要功能

所有游戏都来着B站JL单片机博主开源

这款游戏机具备存档与继续游戏功能,允许玩家在任何时候退出当前游戏并保存进度,以便日后随时并继续之前的冒险。不仅如此,游戏机还支持多任务处理,玩家可以在退出当前游戏后,无缝切换至其他游戏进行娱乐,而当再次回到之前的游戏时,进度将完好无损,确保游戏体验的连续性和完整性。

除了游戏功能外,这款游戏机还内置了视频播放功能。特别值得一提的是,游戏机内置了一段蔡徐坤打篮球的精彩视频,让玩家在享受游戏乐趣的同时,也能欣赏到偶像的风采。

在游戏内容方面,这款游戏机配备了6款精心挑选的游戏,涵盖了多种类型和风格。

有谷歌小恐龙游戏,贪吃蛇,2048,飞翔的小鸟,飞机大战,俄罗斯方块。

还拥有一个可以查询各个游戏状态的任务。

2.需要的硬件

|----------------|----|
| 材料 | 数量 |
| stm32c8t6最小系统板 | 1 |
| 按键 | 2 |
| 摇杆 | 2 |
| OLED屏幕 | 1 |

3.游戏机原理

基于RTOS系统创建一个菜单函数的任务,然后通过摇杆选择自己需要玩的游戏,再按下按键,

系统查询有没有创建该游戏任务,如果有就继续该任务,如果没有就参加一个新的任务。

进入游戏可以想退出时可以选择保存存档退出和直接退出返回到任务函数重新选择。菜单页面选择查询任务状态可以查看到那个游戏有存档,那个游戏没有存档。

4.实现代码

摇杆和按键的底层代码

cpp 复制代码
#include "stm32f10x.h" // Device header
#include "key.h"
#include "delay.h"
uint8_t Key_KeyNumber;
//**定时器扫描按键**//
//采样次数
#define SAMPLES         30
int xw,yw,xw2,yw2;
void Joystick_Init(void)
{
	//开始GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//将LDR引脚设为模拟输入
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/******************************************************************
 * 函 数 名 称:ADC_Joystick_Init
 * 函 数 说 明:初始化ADC功能
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/


void ADC_Joystick_Init(void)
{
	Joystick_Init();
	//开启ADC时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	
	//ADC频率进行6分频
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	//配置ADC结构体
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//独立模式
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//软件触发
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//单次转换
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//非扫描模式
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//总通道数
	ADC_Init(ADC1, &ADC_InitStructure);	//初始化ADC1
	
	//开启ADC1
	ADC_Cmd(ADC1, ENABLE);
	
	//进行ADC校准
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1) == SET);	
}
 

/******************************************************************
 * 函 数 名 称:Get_Adc_Joystick_Value
 * 函 数 说 明:对DMA保存的数据进行平均值计算后输出
 * 函 数 形 参:CHx 第几个扫描的数据
 * 函 数 返 回:对应扫描的ADC值
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned int Get_Adc_Joystick_Value(char CHx)
{
        uint32_t Data = 0;
        
        //设置采集通道
        ADC_RegularChannelConfig( ADC1, CHx, 1, ADC_SampleTime_55Cycles5 );
        
        //开始软件转换
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);
        
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); // 等待转换结束
        
        for(int i = 0; i < SAMPLES; i++)
        {
                Data += ADC_GetConversionValue(ADC1);
                
             //  Delay_ms(2);
        }
        
        Data = Data / SAMPLES;
        
        return Data;
}

/******************************************************************
 * 函 数 名 称:Get_MQ2_Percentage_value
 * 函 数 说 明:读取摇杆值,并且返回百分比
 * 函 数 形 参:0=读取摇杆左右值,1=读取摇杆上下值
 * 函 数 返 回:返回百分比
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned int Get_Joystick_Percentage_value(char dir)
{
    int adc_new = 0;
    int Percentage_value = 0;
        
        if( dir == 0)
        {
                adc_new = Get_Adc_Joystick_Value(ADC_Channel_0);
        }
        else
        {
                adc_new = Get_Adc_Joystick_Value(ADC_Channel_1);
        }

    Percentage_value = ((float)adc_new/4095.0f) * 100.f;
    return Percentage_value;
}
unsigned int Get_Joystick2_Percentage_value(char dir)
{
    int adc_new = 0;
    int Percentage_value = 0;
        
        if( dir == 0)
        {
                adc_new = Get_Adc_Joystick_Value(ADC_Channel_2);
        }
        else
        {
                adc_new = Get_Adc_Joystick_Value(ADC_Channel_3);
        }

    Percentage_value = ((float)adc_new/4095.0f) * 100.f;
    return Percentage_value;
}
void GPIO_KeyInit(void) // 初始化GPIO
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure3;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = key_r_push_pin| key_l_push_pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(key_r_back_and_push_port, &GPIO_InitStructure);

	GPIO_InitStructure3.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure3.GPIO_Pin = sw1_pin | sw2_pin;
	GPIO_InitStructure3.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(sw_port, &GPIO_InitStructure3);
}

void Timer_Init(void) // 初始化定时器
{
	TIM_TimeBaseInitTypeDef TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

	TIM_InternalClockConfig(TIM2);

	TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TimeBaseInitStructure.TIM_Period = 300 - 1;
	TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TimeBaseInitStructure);

	TIM_ClearFlag(TIM2, TIM_FLAG_Update);

	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);

	TIM_Cmd(TIM2, ENABLE);
}

uint8_t Key(void) // 获取按键值
{
	uint8_t Temp;
	Temp = Key_KeyNumber;
	Key_KeyNumber = 0;
	return Temp;
}


uint8_t Get_Key(void) // 获取电平变化
{
	uint8_t KeyNum = 0;
	

	if((xw<30))    KeyNum = r_front_key_value;
	if((xw>70))    KeyNum = r_back_key_value;
	if((yw>70))    KeyNum = r_right_key_value;
	if((yw<30))    KeyNum = r_left_key_value;
	
	if((xw2<30))  KeyNum =l_front_key_value;
	if((xw2>70))  KeyNum=l_back_key_value;
	if((yw2>70))  KeyNum=l_right_key_value;
	if((yw2<30))  KeyNum=l_left_key_value;
	if (GPIO_ReadInputDataBit(key_r_back_and_push_port, key_r_push_pin) == 0)
	{
		KeyNum = r_push_key_value;
	}
	if (GPIO_ReadInputDataBit(key_r_back_and_push_port, key_l_push_pin) == 0)
	{
		KeyNum = l_push_key_value;
	}
	if (GPIO_ReadInputDataBit(sw_port, sw1_pin) == 0)
	{
		KeyNum = sw1_key_value;
	}
	if (GPIO_ReadInputDataBit(sw_port, sw2_pin) == 0)
	{
		KeyNum = sw2_key_value;
	}
	return KeyNum;
}

void Loop_Key(void) // 扫描按键
{
	static uint8_t LastKey = 0, NowKey = 0;
	LastKey = NowKey;
	NowKey = Get_Key();
	if (LastKey == r_front_key_value && NowKey == 0)
	{
		Key_KeyNumber = r_front_key_value;
	}
	if (LastKey == r_back_key_value && NowKey == 0)
	{
		Key_KeyNumber = r_back_key_value;
	}
	if (LastKey == r_left_key_value && NowKey == 0)
	{
		Key_KeyNumber = r_left_key_value;
	}
	if (LastKey == r_right_key_value && NowKey == 0)
	{
		Key_KeyNumber = r_right_key_value;
	}
	if (LastKey == r_push_key_value && NowKey == 0)
	{
		Key_KeyNumber = r_push_key_value;
	}
	if (LastKey == l_front_key_value && NowKey == 0)
	{
		Key_KeyNumber = l_front_key_value;
	}
	if (LastKey == l_back_key_value && NowKey == 0)
	{
		Key_KeyNumber = l_back_key_value;
	}
	if (LastKey == l_left_key_value && NowKey == 0)
	{
		Key_KeyNumber = l_left_key_value;
	}
	if (LastKey == l_right_key_value && NowKey == 0)
	{
		Key_KeyNumber = l_right_key_value;
	}
	if (LastKey == l_push_key_value && NowKey == 0)
	{
		Key_KeyNumber = l_push_key_value;
	}
	if (LastKey == sw1_key_value && NowKey == 0)
	{
		Key_KeyNumber = sw1_key_value;
	}
	if (LastKey == sw2_key_value && NowKey == 0)
	{
		Key_KeyNumber = sw2_key_value;
	}

}

void Key_Init(void) // 按键初始化
{
	GPIO_KeyInit();
	Timer_Init();
	ADC_Joystick_Init();
}

void TIM2_IRQHandler(void) // 定时器扫描(30ms)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == 1)
	{
		xw=Get_Joystick_Percentage_value(0);
		yw=Get_Joystick_Percentage_value(1);
		xw2=Get_Joystick2_Percentage_value(0);
		yw2=Get_Joystick2_Percentage_value(1);
		Loop_Key();
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

菜单任务逻辑

cpp 复制代码
int menu(void)
{

    while (1)
    {
		//查询是否创建该任务
        vTaskGetInfo(game1_Handler, &game1_state, pdTRUE, eInvalid);
        vTaskGetInfo(game2_Handler, &game2_state, pdTRUE, eInvalid);
        vTaskGetInfo(game3_Handler, &game3_state, pdTRUE, eInvalid);
        vTaskGetInfo(game4_Handler, &game4_state, pdTRUE, eInvalid);
		vTaskGetInfo(game5_Handler, &game5_state, pdTRUE, eInvalid);
		vTaskGetInfo(game6_Handler, &game6_state, pdTRUE, eInvalid);
		vTaskGetInfo(game7_Handler, &game7_state, pdTRUE, eInvalid);
        vTaskGetInfo(  info_Handler, &info_state, pdTRUE, eInvalid);
		vTaskGetInfo(Video_Handler, &info_state, pdTRUE, eInvalid);
        B_OLED_Clear();
		//显示ui界面
		if(select<6)
		{
		B_OLED_ShowString(14, 20, "1", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 1, 20, "2", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 2, 20, "3", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 3, 20, "4", B_OLED_8X16);
        B_OLED_ShowString(35, 50, "freeRTOS", B_OLED_6X8);

        B_OLED_DrawRectangle(distance_x, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + length_x + distance_x, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + (length_x + distance_x) * 2, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + (length_x + distance_x) * 3, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x, length_y + distance_y2 + distance_y, length_x + (distance_x + length_x) * 3, length_y2, B_OLED_UNFILLED);
		if (select == 1)
        {
            sprintf(text_menu, "Menu:dragon");
            B_OLED_ReverseArea(distance_x, distance_y, length_x, length_y);
        }
        else if (select == 2)
        {
            sprintf(text_menu, "Menu:war");
            B_OLED_ReverseArea(distance_x + length_x + distance_x, distance_y, length_x, length_y);
        }
        else if (select == 3)
        {
            sprintf(text_menu, "Menu:bird");
            B_OLED_ReverseArea(distance_x + (length_x + distance_x) * 2, distance_y, length_x, length_y);
        }
        else if (select == 4)
        {
            sprintf(text_menu, "Menu:block");
            B_OLED_ReverseArea(distance_x + (length_x + distance_x) * 3, distance_y, length_x, length_y);
        }
        else if (select == 5)
        {
            sprintf(text_menu, "Menu:info");
            B_OLED_ReverseArea(distance_x, length_y + distance_y2 + distance_y, length_x + (distance_x + length_x) * 3, length_y2);
        }	
		}
        if(select>=6)
		{
		B_OLED_ShowString(14, 20, "6", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 1, 20, "7", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 2, 20, "8", B_OLED_8X16);
        B_OLED_ShowString(14 + (length_x + distance_x) * 3, 20, "9", B_OLED_8X16);
        B_OLED_ShowString(35, 50, "freeRTOS", B_OLED_6X8);

        B_OLED_DrawRectangle(distance_x, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + length_x + distance_x, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + (length_x + distance_x) * 2, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x + (length_x + distance_x) * 3, distance_y, length_x, length_y, B_OLED_UNFILLED);
        B_OLED_DrawRectangle(distance_x, length_y + distance_y2 + distance_y, length_x + (distance_x + length_x) * 3, length_y2, B_OLED_UNFILLED);
			            
        if (select == 6)     B_OLED_ReverseArea(distance_x, distance_y, length_x, length_y),sprintf(text_menu, "Menu:Snake");
	    if (select == 7)     B_OLED_ReverseArea(distance_x + length_x + distance_x, distance_y, length_x, length_y),sprintf(text_menu, "Menu:Video");
        if (select == 8)     B_OLED_ReverseArea(distance_x + (length_x + distance_x) * 2, distance_y, length_x, length_y),sprintf(text_menu, "Menu:2048");
		if (select == 9)     B_OLED_ReverseArea(distance_x + (length_x + distance_x) * 3, distance_y, length_x, length_y),sprintf(text_menu, "Menu:no");
		if (select == 10)    B_OLED_ReverseArea(distance_x, length_y + distance_y2 + distance_y, length_x + (distance_x + length_x) * 3, length_y2),sprintf(text_menu, "Menu:info");;
		}
		//判断改任务是否存在存在上面显示run
        if ((game1_state.eCurrentState == eRunning) || (game1_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 1)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
        if ((game2_state.eCurrentState == eRunning) || (game2_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + (length_x + distance_x) * 1 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 2)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
        if ((game3_state.eCurrentState == eRunning) || (game3_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + (length_x + distance_x) * 2 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 3)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
        if ((game4_state.eCurrentState == eRunning) || (game4_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + (length_x + distance_x) * 3 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 4)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
		 if ((game5_state.eCurrentState == eRunning) || (game5_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 6)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
		if ((game6_state.eCurrentState == eRunning) || (game6_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 8)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
		if ((game7_state.eCurrentState == eRunning) || (game7_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(15 + offset_state_x, 20 + offset_state_y, 2, B_OLED_UNFILLED);
            if (select == 9)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
        if ((info_state.eCurrentState == eRunning) || (info_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(35 + offset_state_x2, 50 + offset_state_y2, 2, B_OLED_UNFILLED);
            if (select == 5||select == 10)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }
		 if ((Video_state.eCurrentState == eRunning) || (Video_state.eCurrentState == eSuspended))
        {
            B_OLED_DrawCircle(35 + offset_state_x2, 50 + offset_state_y2, 2, B_OLED_UNFILLED);
            if (select == 7)
                B_OLED_ShowString(110, 0, "run", B_OLED_6X8);
        }

        B_OLED_ShowString(0, 0, text_menu, B_OLED_8X16);

        menu_key_num = Get_Key();
        if (menu_key_num != 0)
        {
            if ((menu_key_num == r_push_key_value) || (menu_key_num == l_push_key_value))
            {
                return select;
            }
            switch (menu_key_num)
            {
            case r_right_key_value:
                select++;
                break;
            case r_left_key_value:
                select--;
                break;
            case r_back_key_value:
                select += 4;
                break;
            case r_front_key_value:
                select -= 4;
            case l_right_key_value:
                select++;
                break;
            case l_left_key_value:
                select--;
                break;
            case l_back_key_value:
                select += 4;
                break;
            case l_front_key_value:
                select -= 4;
            default:
                break;
            }
            if (select > 10)
                select = 10;
            if (select < 1)
                select = 1;

            while (menu_key_num != 0)
            {
                menu_key_num = Get_Key();
            }
        }

        B_OLED_Update();
    }
}

游戏任务逻辑

cpp 复制代码
void startup()
{
	init();
	while(1)
	{
		B_OLED_Clear();
		FrameLoop();
//		KeyLoop();
		GameLoop();
		B_OLED_Update();
		if (get_key_status() == sw1_key_value)
		{
			vTaskResume(menuTask_Handler);
			vTaskSuspend(game6_Handler);
		}
		else if (get_key_status() == sw2_key_value)
		{
			vTaskResume(menuTask_Handler);
			vTaskDelete(game6_Handler);
		}
	}

}

查询任务状态和存档状态

cpp 复制代码
int infos(){
    B_OLED_Clear();
    vTaskGetInfo(game1_Handler, &game1_state, pdTRUE, eInvalid);
    vTaskGetInfo(game2_Handler, &game2_state, pdTRUE, eInvalid);
    vTaskGetInfo(game3_Handler, &game3_state, pdTRUE, eInvalid);
    vTaskGetInfo(game4_Handler, &game4_state, pdTRUE, eInvalid);
	vTaskGetInfo(game1_Handler, &game5_state, pdTRUE, eInvalid);
    vTaskGetInfo(game2_Handler, &game6_state, pdTRUE, eInvalid);
    vTaskGetInfo(game3_Handler, &game7_state, pdTRUE, eInvalid);
    vTaskGetInfo(game4_Handler, &Video_state, pdTRUE, eInvalid);
    B_OLED_ShowString(0, 0, "game1", B_OLED_6X8);
    switch (game1_state.eCurrentState)
    {
    case eRunning:
        B_OLED_ShowString(0, text_height+1, "eRunning", B_OLED_6X8);
        break;
    case eReady:
        B_OLED_ShowString(0, text_height + 1, "eReady", B_OLED_6X8);
        break;
    case eBlocked:
        B_OLED_ShowString(0, text_height + 1, "eBlocked", B_OLED_6X8);
        break;
    case eSuspended:
        B_OLED_ShowString(0, text_height + 1, "eSuspended", B_OLED_6X8);
        break;
    case eDeleted:
        B_OLED_ShowString(0, text_height + 1, "eDeleted", B_OLED_6X8);
        break;
    case eInvalid:
        B_OLED_ShowString(0, text_height + 1, "eInvalid", B_OLED_6X8);
        break;
    default:
        break;
    }
    sprintf(text, "pro:%1d", game1_state.uxBasePriority);
    B_OLED_ShowString(0, 2 * text_height + 1, text, B_OLED_6X8);
    // sprintf(text, "stack:%1d", game1_state.usStackHighWaterMark);
    // B_OLED_ShowString(0, 3 * text_height + 1, text, B_OLED_6X8);

    B_OLED_ShowString(0, 4 * text_height + 1, "game2", B_OLED_6X8);
    switch (game2_state.eCurrentState)
    {
    case eRunning:
        B_OLED_ShowString(0, 5 * text_height + 1, "eRunning", B_OLED_6X8);
        break;
    case eReady:
        B_OLED_ShowString(0, 5 * text_height + 1, "eReady", B_OLED_6X8);
        break;
    case eBlocked:
        B_OLED_ShowString(0, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
        break;
    case eSuspended:
        B_OLED_ShowString(0, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
        break;
    case eDeleted:
        B_OLED_ShowString(0, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
        break;
    case eInvalid:
        B_OLED_ShowString(0, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
        break;
    default:
        break;
    }
    sprintf(text, "pro:%1d", game2_state.uxBasePriority);
    B_OLED_ShowString(0, 6 * text_height + 1, text, B_OLED_6X8);
    // sprintf(text, "stack:%1d", game2_state.usStackHighWaterMark);
    // B_OLED_ShowString(0, 7 * text_height + 1, text, B_OLED_6X8);

    B_OLED_ShowString(half, 0, "game3", B_OLED_6X8);
    switch (game3_state.eCurrentState)
    {
    case eRunning:
        B_OLED_ShowString(half, text_height + 1, "eRunning", B_OLED_6X8);
        break;
    case eReady:
        B_OLED_ShowString(half, text_height + 1, "eReady", B_OLED_6X8);
        break;
    case eBlocked:
        B_OLED_ShowString(half, text_height + 1, "eBlocked", B_OLED_6X8);
        break;
    case eSuspended:
        B_OLED_ShowString(half, text_height + 1, "eSuspended", B_OLED_6X8);
        break;
    case eDeleted:
        B_OLED_ShowString(half, text_height + 1, "eDeleted", B_OLED_6X8);
        break;
    case eInvalid:
        B_OLED_ShowString(half, text_height + 1, "eInvalid", B_OLED_6X8);
        break;
    default:
        break;
    }
    sprintf(text, "pro:%1d", game3_state.uxBasePriority);
    B_OLED_ShowString(half, 2 * text_height + 1, text, B_OLED_6X8);
    // sprintf(text, "stack:%1d", game3_state.usStackHighWaterMark);
    // B_OLED_ShowString(half, 3 * text_height + 1, text, B_OLED_6X8);

    B_OLED_ShowString(half, 4 * text_height + 1, "game4", B_OLED_6X8);
    switch (game4_state.eCurrentState)
    {
    case eRunning:
        B_OLED_ShowString(half, 5 * text_height + 1, "eRunning", B_OLED_6X8);
        break;
    case eReady:
        B_OLED_ShowString(half, 5 * text_height + 1, "eReady", B_OLED_6X8);
        break;
    case eBlocked:
        B_OLED_ShowString(half, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
        break;
    case eSuspended:
        B_OLED_ShowString(half, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
        break;
    case eDeleted:
        B_OLED_ShowString(half, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
        break;
    case eInvalid:
        B_OLED_ShowString(half, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
        break;
    default:
        break;
    }
    sprintf(text, "pro:%1d", game4_state.uxBasePriority);
    B_OLED_ShowString(half, 6 * text_height + 1, text, B_OLED_6X8);
    // sprintf(text, "stack:%1d", game4_state.usStackHighWaterMark);
    // B_OLED_ShowString(half, 7 * text_height + 1, text, B_OLED_6X8);


    B_OLED_Update();
	int a=0;
    while (1)
    {
		if (((get_key_status() == l_right_key_value)||(get_key_status() ==r_right_key_value))&&(a==0))
        { 
			a=1;
			B_OLED_Clear();
		    B_OLED_ShowString(0, 0, "game5", B_OLED_6X8);
			switch (game5_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(0, text_height+1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(0, text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(0, text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(0, text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(0, text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(0, text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game5_state.uxBasePriority);
			B_OLED_ShowString(0, 2 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game1_state.usStackHighWaterMark);
			// B_OLED_ShowString(0, 3 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(0, 4 * text_height + 1, "game6", B_OLED_6X8);
			switch (game6_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(0, 5 * text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(0, 5 * text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(0, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(0, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(0, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(0, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game6_state.uxBasePriority);
			B_OLED_ShowString(0, 6 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game2_state.usStackHighWaterMark);
			// B_OLED_ShowString(0, 7 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(half, 0, "game7", B_OLED_6X8);
			switch (game7_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(half, text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(half, text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(half, text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(half, text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(half, text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(half, text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game7_state.uxBasePriority);
			B_OLED_ShowString(half, 2 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game3_state.usStackHighWaterMark);
			// B_OLED_ShowString(half, 3 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(half, 4 * text_height + 1, "Video", B_OLED_6X8);
			switch (Video_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(half, 5 * text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(half, 5 * text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(half, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(half, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(half, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(half, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", Video_state.uxBasePriority);
			B_OLED_ShowString(half, 6 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game4_state.usStackHighWaterMark);
			// B_OLED_ShowString(half, 7 * text_height + 1, text, B_OLED_6X8);
			 B_OLED_Update();
			        
        }
        if (((get_key_status() == l_left_key_value)||(get_key_status() ==r_left_key_value))&&(a==1))
		{
			a=0;
			B_OLED_Clear();
			B_OLED_ShowString(0, 0, "game1", B_OLED_6X8);
			switch (game1_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(0, text_height+1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(0, text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(0, text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(0, text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(0, text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(0, text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game1_state.uxBasePriority);
			B_OLED_ShowString(0, 2 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game1_state.usStackHighWaterMark);
			// B_OLED_ShowString(0, 3 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(0, 4 * text_height + 1, "game2", B_OLED_6X8);
			switch (game2_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(0, 5 * text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(0, 5 * text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(0, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(0, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(0, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(0, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game2_state.uxBasePriority);
			B_OLED_ShowString(0, 6 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game2_state.usStackHighWaterMark);
			// B_OLED_ShowString(0, 7 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(half, 0, "game3", B_OLED_6X8);
			switch (game3_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(half, text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(half, text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(half, text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(half, text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(half, text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(half, text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game3_state.uxBasePriority);
			B_OLED_ShowString(half, 2 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game3_state.usStackHighWaterMark);
			// B_OLED_ShowString(half, 3 * text_height + 1, text, B_OLED_6X8);

			B_OLED_ShowString(half, 4 * text_height + 1, "game4", B_OLED_6X8);
			switch (game4_state.eCurrentState)
			{
			case eRunning:
				B_OLED_ShowString(half, 5 * text_height + 1, "eRunning", B_OLED_6X8);
				break;
			case eReady:
				B_OLED_ShowString(half, 5 * text_height + 1, "eReady", B_OLED_6X8);
				break;
			case eBlocked:
				B_OLED_ShowString(half, 5 * text_height + 1, "eBlocked", B_OLED_6X8);
				break;
			case eSuspended:
				B_OLED_ShowString(half, 5 * text_height + 1, "eSuspended", B_OLED_6X8);
				break;
			case eDeleted:
				B_OLED_ShowString(half, 5 * text_height + 1, "eDeleted", B_OLED_6X8);
				break;
			case eInvalid:
				B_OLED_ShowString(half, 5 * text_height + 1, "eInvalid", B_OLED_6X8);
				break;
			default:
				break;
			}
			sprintf(text, "pro:%1d", game4_state.uxBasePriority);
			B_OLED_ShowString(half, 6 * text_height + 1, text, B_OLED_6X8);
			// sprintf(text, "stack:%1d", game4_state.usStackHighWaterMark);
			// B_OLED_ShowString(half, 7 * text_height + 1, text, B_OLED_6X8);


			B_OLED_Update();
		}
		if (get_key_status() == sw1_key_value)
        {
			B_OLED_Clear();B_OLED_Update();
            vTaskResume(menuTask_Handler);
            vTaskSuspend(info_Handler);

        }
        else if (get_key_status() == sw2_key_value)
        {
			B_OLED_Clear();B_OLED_Update();
            vTaskResume(menuTask_Handler);
            vTaskDelete(info_Handler);

        }
    }
    
}

-----------------------欢迎大家指正交流,有空可以一起讨论代码啊。--------------------------------

通过网盘分享的文件:stm32_FreeRTOS_Game-master.zip

链接: https://pan.baidu.com/s/1UAAb-8cHPl7ZP1pRVyJMAA 提取码: qpgg

相关推荐
智者知已应修善业1 小时前
【51单片机用数码管显示流水灯的种类是按钮控制数码管加一和流水灯】2022-6-14
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
智商偏低7 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen9 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森11 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白11 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D11 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术14 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt15 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘15 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang15 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c