基于RTOS的STM32游戏机

news2025/2/6 1:19:09

1.游戏机的主要功能

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

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

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

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

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

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

2.需要的硬件

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

3.游戏机原理

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

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

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

4.实现代码

摇杆和按键的底层代码

#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);
	}
}

菜单任务逻辑

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();
    }
}

游戏任务逻辑

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);
		}
	}

}

查询任务状态和存档状态

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络——三种交换技术

目录 电路交换——用于电话网络 电路交换的优点&#xff1a; 电路交换的缺点&#xff1a; 报文交换——用于电报网络 报文交换的优点&#xff1a; 报文交换的缺点&#xff1a; 分组交换——用于现代计算机网络 分组交换的优点&#xff1a; 分组交换的缺点 电路交换——…

HTML5教程之标签(2)

HTML5 <b> 标签 实例 在HTML5中&#xff0c;你可以使用<b>标签来对某些文本实现加粗的效果&#xff0c;请参考下述的示例&#xff1a; <p>这是一个普通的文本- <b>这是一个加粗文本</b>。</p> 尝试一下 浏览器支持 所有主流浏览器都支…

Verilog基础(一):基础元素

verilog基础 我先说,看了肯定会忘,但是重要的是这个过程,我们知道了概念,知道了以后在哪里查询。语法都是术,通用的概念是术。所以如果你有相关的软件编程经验,那么其实开启这个学习之旅,你会感受到熟悉,也会感受到别致。 入门 - 如何开始 欢迎来到二进制的世界,数字…

Vue 图片引用方式详解:静态资源与动态路径访问

目录 前言1. 引用 public/ 目录2. assets/ 目录3. 远程服务器4. Vue Router 动态访问5. 总结6. 扩展&#xff08;图片不显示&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Vue 开发中&#x…

Qt网络相关

“ 所有生而孤独的人&#xff0c;葆有的天真 ” 为了⽀持跨平台, QT对⽹络编程的 API 也进⾏了重新封装。本章会上手一套基于QT的网络通信编写。 UDP Socket 在使用Qt进行网络编程前&#xff0c;需要在Qt项目中的.pro文件里添加对应的网络模块( network ). QT core gui net…

生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (上)

今天小李哥将开启全新的技术分享系列&#xff0c;为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来&#xff0c;生成式 AI 安全市场正迅速发展。据 IDC 预测&#xff0c;到 2025 年全球 AI 安全解决方案市场规模将突破 200 亿美元&#xff0c;年复合增长率超过 30%…

pytorch基于FastText实现词嵌入

FastText 是 Facebook AI Research 提出的 改进版 Word2Vec&#xff0c;可以&#xff1a; ✅ 利用 n-grams 处理未登录词 比 Word2Vec 更快、更准确 适用于中文等形态丰富的语言 完整的 PyTorch FastText 代码&#xff08;基于中文语料&#xff09;&#xff0c;包含&#xff1…

Docker技术相关学习三

一、Docker镜像仓库管理 1.docker仓库&#xff1a;用于存储和分发docker镜像的集中式存储库&#xff0c;开发者可以将自己创建的镜像推送到仓库中也可以从仓库中拉取所需要的镜像。 2.docker仓库&#xff1a; 公有仓库&#xff08;docker hub&#xff09;&#xff1a;任何人都可…

在Mac mini M4上部署DeepSeek R1本地大模型

在Mac mini M4上部署DeepSeek R1本地大模型 安装ollama 本地部署&#xff0c;我们可以通过Ollama来进行安装 Ollama 官方版&#xff1a;【点击前往】 Web UI 控制端【点击安装】 如何在MacOS上更换Ollama的模型位置 默认安装时&#xff0c;OLLAMA_MODELS 位置在"~/.o…

Python 网络爬虫实战:从基础到高级爬取技术

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 网络爬虫&#xff08;Web Scraping&#xff09;是一种自动化技术&#xff0c;利用程序从网页中提取数据&#xff0c;广泛…

python学opencv|读取图像(五十四)使用cv2.blur()函数实现图像像素均值处理

【1】引言 前序学习进程中&#xff0c;对图像的操作均基于各个像素点上的BGR值不同而展开。 对于彩色图像&#xff0c;每个像素点上的BGR值为三个整数&#xff0c;因为是三通道图像&#xff1b;对于灰度图像&#xff0c;各个像素上的BGR值是一个整数&#xff0c;因为这是单通…

控件【QT】

文章目录 控件QWidgetenabledgeometrysetGeometry qrcwindowOpacityQPixmapfonttoolTipfocusPolicystyleSheetQPushButtonRadio ButtionCheck Box显示类控件QProgressBarcalendarWidget 控件 Qt中已经提供了很多内置的控件了(按钮,文本框,单选按钮,复选按钮&#xff0c;下拉框…

STM32 串口发送与接收

接线图 代码配置 根据上一章发送的代码配置&#xff0c;在GPIO配置的基础上需要再配置PA10引脚做RX接收&#xff0c;引脚模式可以选择浮空输入或者上拉输入&#xff0c;在USART配置串口模式里加上RX模式。 配置中断 //配置中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE…

【Unity2D 2022:UI】创建滚动视图

一、创建Scroll View游戏对象 在Canvas画布下新建Scroll View游戏对象 二、为Content游戏对象添加Grid Layout Group&#xff08;网格布局组&#xff09;组件 选中Content游戏物体&#xff0c;点击Add Competent添加组件&#xff0c;搜索Grid Layout Group组件 三、调整Grid La…

Python sider-ai-api库 — 访问Claude、llama、ChatGPT、gemini、o1等大模型API

目前国内少有调用ChatGPT、Claude、Gemini等国外大模型API的库。 Python库sider_ai_api 提供了调用这些大模型的一个完整解决方案&#xff0c; 使得开发者能调用 sider.ai 的API&#xff0c;实现大模型的访问。 Sider是谷歌浏览器和Edge的插件&#xff0c;能调用ChatGPT、Clau…

密云生活的初体验

【】在《岁末随笔之碎碎念》里&#xff0c;我通告了自己搬新家的事情。乙巳年开始&#xff0c;我慢慢与大家分享自己买房装修以及在新家的居住体验等情况。 跳过买房装修的内容&#xff0c;今天先说说这三个月的生活体验。 【白河】 潮白河是海河水系五大河之一&#xff0c;贯穿…

Leetcode - 周赛434

目录 一、3432. 统计元素和差值为偶数的分区方案二、3433. 统计用户被提及情况三、3434. 子数组操作后的最大频率四、3435. 最短公共超序列的字母出现频率 一、3432. 统计元素和差值为偶数的分区方案 题目链接 本题可以直接模拟&#xff0c;这里再介绍一个数学做法&#xff0…

C32.【C++ Cont】静态实现双向链表及STL库的list

目录 1.知识回顾 2.静态实现演示图 3.静态实现代码 1.初始双向链表 2.头插 3.遍历链表 4.查找某个值 4.任意位置之后插入元素 5.任意位置之前插入元素 6.删除任意位置的元素 4.STL库的list 1.知识回顾 96.【C语言】数据结构之双向链表的初始化,尾插,打印和尾删 97.【C…

记录一次-Rancher通过UI-Create Custom- RKE2的BUG

一、下游集群 当你的下游集群使用Mysql外部数据库时&#xff0c;会报错&#xff1a; **他会检查ETCD。 但因为用的是Mysql外部数据库&#xff0c;这个就太奇怪了&#xff0c;而且这个检测不过&#xff0c;集群是咩办法被管理的。 二、如果不选择etcd,就选择控制面。 在rke2-…

51单片机入门_05_LED闪烁(常用的延时方法:软件延时、定时器延时;while循环;unsigned char 可以表示的数字是0~255)

本篇介绍编程实现LED灯闪烁&#xff0c;需要学到一些新的C语言知识。由于单片机执行的速度是非常快的&#xff0c;如果不进行延时的话&#xff0c;人眼是无法识别(停留时间要大于20ms)出LED灯是否在闪烁所以需要学习如何实现软件延时。另外IO口与一个字节位的数据对应关系。 文…