基于RTOS的STM32游戏机
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//开启ADC1ADC_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");;}//判断改任务是否存在存在上面显示runif ((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
相关文章:

基于RTOS的STM32游戏机
1.游戏机的主要功能 所有游戏都来着B站JL单片机博主开源 这款游戏机具备存档与继续游戏功能,允许玩家在任何时候退出当前游戏并保存进度,以便日后随时并继续之前的冒险。不仅如此,游戏机还支持多任务处理,玩家可以在退出当前游戏…...

【CPP】CPP经典面试题
文章目录 引言1. C 基础1.1 C 中的 const 关键字1.2 C 中的 static 关键字 2. 内存管理2.1 C 中的 new 和 delete2.2 内存泄漏 3. 面向对象编程3.1 继承和多态3.2 多重继承 4. 模板和泛型编程4.1 函数模板4.2 类模板 5. STL 和标准库5.1 容器5.2 迭代器 6. 高级特性6.1 移动语义…...

WPF基础03——InitializeComponent()函数解释
总述 InitializeComponent(),是MainWindow中的构造函数,实际写项目过程中,多多少少都会碰到该函数报错的情况,现在对InitializeComponent()做一些理解和说明。 在 WPF 中,XAML 文件和代码后台…...

如何在自己mac电脑上私有化部署deep seek
在 Mac 电脑上私有化部署 DeepSeek 的步骤如下: 1. 环境准备 安装 Homebrew(如果尚未安装): Homebrew 是 macOS 上的包管理工具,用于安装依赖。 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com…...

iOS 老项目适配 #Preview 预览功能
前言 iOS 开发者 最憋屈的就是UI 布局慢,一直以来没有实时预览功能,虽然swiftUI 早就支持了,但是目前主流还是使用UIKit在布局,iOS 17 苹果推出了 #Preview 可以支持UIKit 实时预览,但是仅仅是 iOS 17,老项目怎么办呢?于是就有了这篇 老项目适配 #Preview 预览 的文章,…...

7 与mint库对象互转宏(macros.rs)
macros.rs代码定义了一个Rust宏mint_vec,它用于在启用mint特性时,为特定的向量类型实现与mint库中对应类型的相互转换。mint库是一个提供基本数学类型(如点、向量、矩阵等)的Rust库,旨在与多个图形和数学库兼容。这个宏…...

pytorch实现变分自编码器
人工智能例子汇总:AI常见的算法和例子-CSDN博客 变分自编码器(Variational Autoencoder, VAE)是一种生成模型,属于深度学习中的无监督学习方法。它通过学习输入数据的潜在分布(Latent Distribution)&…...

Node.js与嵌入式开发:打破界限的创新结合
文章目录 一、Node.js的本质与核心优势1.1 什么是Node.js?1.2 嵌入式开发的范式转变二、Node.js与嵌入式结合的四大技术路径2.1 硬件交互层2.2 物联网协议栈2.3 边缘计算架构2.4 轻量化运行时方案三、实战案例:智能农业监测系统3.1 硬件配置3.2 软件架构3.3 核心代码片段四、…...

Noise Conditional Score Network
NCSN p σ ( x ~ ∣ x ) : N ( x ~ ; x , σ 2 I ) p_\sigma(\tilde{\mathrm{x}}|\mathrm{x}) : \mathcal{N}(\tilde{\mathrm{x}}; \mathrm{x}, \sigma^2\mathbf{I}) pσ(x~∣x):N(x~;x,σ2I) p σ ( x ~ ) : ∫ p d a t a ( x ) p σ ( x ~ ∣ x ) d x p_\sigma(\mathrm…...

低代码系统-产品架构案例介绍、蓝凌(十三)
蓝凌低代码系统,依旧是从下到上,从左至右的顺序。 技术平台h/iPaas 指低层使用了哪些技术,例如:微服务架构,MySql数据库。个人认为,如果是市场的主流,就没必要赘述了。 新一代门户 门户设计器&a…...

51单片机 02 独立按键
一、独立按键控制LED亮灭 轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 #include <STC89C5xRC.H> void main() { // P20xFE;while(1){…...

2021.3.1的android studio版本就很好用
使用最新版的studio有个问题就是gradle版本也比较高,这样就容易出现之前项目不兼容问题,配置gradle可能会出现很多问题比较烦,所以干脆就用老版本的studio...

CSV数据分析智能工具(基于OpenAI API和streamlit)
utils.py: from langchain_openai import ChatOpenAI from langchain_experimental.agents.agent_toolkits import create_csv_agent import jsonPROMPT_TEMPLATE """你是一位数据分析助手,你的回应内容取决于用户的请求内容。1. 对于文…...

移除元素-双指针(下标)
题目 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:…...

蓝桥杯备赛题目练习(一)
目录 一. 口算练习题 代码如下 代码解读(简略重点): 代码解读(详细): 二. 小乐乐改数字 代码(1):当做整数读取 代码(2):当做字符…...

FortiOS 存在身份验证绕过导致命令执行漏洞(CVE-2024-55591)
免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

【多线程】线程池核心数到底如何配置?
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. 前置回顾2. 动态线程池2.1 JMX 的介绍2.1.1 MBeans 介绍 2.2 使用 JMX jconsole 实现动态修改线程池2.2.…...

Windows图形界面(GUI)-QT-C/C++ - Qt Combo Box
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 一、概述 1.1 基本概念 1.2 应用场景对比 二、核心属性详解 2.1 行为控制 2.2 显示配置 三、数据操作与访问 3.1 基础数据管理 3.2 高级数据访问 四、用户交互处理 4.1 信号处…...

开源AI智能名片2 + 1链动模式S2B2C商城小程序:内容价值创造与传播新引擎
摘要:本文聚焦于信息爆炸时代下,内容价值的创造与传播。随着用户角色的转变,其在内容生产与传播中的价值日益凸显。同时,深入探讨开源AI智能名片2 1链动模式S2B2C商城小程序这一创新商业模式,如何借助用户创造内容并传…...

python读取excel工具:openpyxl | AI应用开发
python读取excel工具:openpyxl | AI应用开发 openpyxl 是一个 Python 库,专门用于读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件。它是处理 Excel 文件的强大工具,可以让你在不需要安装 Excel 软件的情况下,对 Excel 文件进行创建、…...

堆的基本概念
1.1 堆的基本概念 虚拟机所在目录 E:\ctf\pwn-self 进入虚拟机的pwndocker环境 holyeyesubuntu:~$ pwd /home/holyeyes holyeyesubuntu:~$ sudo ./1run.sh IDA分析 int __fastcall main(int argc, const char **argv, const char **envp) { void *v4; // [rsp20h] [rbp-1…...

Android车机DIY开发之软件篇(九) NXP AutomotiveOS编译
Android车机DIY开发之软件篇(十一) NXP AutomotiveOS编译 Google 在汽车上也提供了用于汽车的 Google 汽车服务(GAS,Google Automotive Service),包含有 Google 地图、应用市场、Google 汽车助理等等。Google 汽车服务同样没有开…...

嵌入式工程师必学(143):模拟信号链基础
概述: 我们每天使用的许多电子设备,以及我们赖以生存的电子设备,如果不使用电子工程师设计的实际输入信号,就无法运行。 模拟信号链由四个主要元件组成:传感器、放大器、滤波器和模数转换器 (ADC)。这些传感器用于检测、调节模拟信号并将其转换为适合由微控制器或其他数…...

《LLM大语言模型深度探索与实践:构建智能应用的新范式,融合代理与数据库的高级整合》
文章目录 Langchain的定义Langchain的组成三个核心组件实现整个核心组成部分 为什么要使用LangchainLangchain的底层原理Langchain实战操作LangSmithLangChain调用LLM安装openAI库-国内镜像源代码运行结果小结 使用Langchain的提示模板部署Langchain程序安装langserve代码请求格…...

e2studio开发RA2E1(5)----GPIO输入检测
e2studio开发RA2E1.5--GPIO输入检测 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置GPIO口配置按键口配置按键口&Led配置R_IOPORT_PortRead()函数原型R_IOPORT_PinRead()函数原型代码 概述 本篇文章主要介绍如何…...

Spring @Lazy:延迟初始化,为应用减负
在Spring框架中,Lazy注解的作用非常直观,它就是用来告诉Spring容器:“嘿,这个Bean嘛,先别急着创建和初始化,等到真正需要用到的时候再弄吧!” 默认情况下,Spring容器在启动时会立即创…...

将OneDrive上的文件定期备份到移动硬盘
背景: 我在oneDrive上存了很多文件,分布在多个文件夹中,也有套了好几层文件夹的情况。我希望每隔一段时间,将oneDrive上的所有文件向移动硬盘上拷贝一份,但是我只想将距离上一次向移动硬盘拷贝的文件相比,发…...

从0开始,来看看怎么去linux排查Java程序故障
一,前提准备 最基本前提:你需要有liunx环境,如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。 有了虚拟机之后,你还需要安装jdk和配置环境变量 1. 安装JDK(以OpenJDK 17为例) 下载JDK…...

DeepSeek-V3:开源多模态大模型的突破与未来
目录 引言 一、DeepSeek-V3 的概述 1.1 什么是 DeepSeek-V3? 1.2 DeepSeek-V3 的定位 二、DeepSeek-V3 的核心特性 2.1 多模态能力 2.2 开源与可扩展性 2.3 高性能与高效训练 2.4 多语言支持 2.5 安全与伦理 三、DeepSeek-V3 的技术架构 3.1 模型架构 3…...

Deep Sleep 96小时:一场没有硝烟的科技保卫战
2025年1月28日凌晨3点,当大多数人还沉浸在梦乡时,一场没有硝烟的战争悄然打响。代号“Deep Sleep”的服务器突遭海量数据洪流冲击,警报声响彻机房,一场针对中国关键信息基础设施的网络攻击来势汹汹! 面对美国发起的这场…...