活动介绍

make: *** [Drivers/STM32F1xx_HAL_Driver/Src/subdir.mk:49: Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.o] Error 87 make: *** Waiting for unfinished jobs....怎么解决

时间: 2025-05-26 10:39:26 浏览: 41
### STM32F1xx_HAL_Driver 编译错误分析 在处理 `STM32F1xx_HAL_Driver` 的编译过程中,如果遇到 `Error 87` 并且涉及文件如 `stm32f1xx_hal_exti.o` 和 `subdir.mk`,这通常表明存在配置或依赖项方面的问题。以下是可能的原因以及解决方案: #### 可能原因一:宏定义冲突 某些情况下,`STM32 HAL Driver` 中的头文件可能存在重复定义或者未正确定义的关键字。例如,在 `stm32f1xx_hal_conf.h` 文件中,如果没有正确设置外设的相关选项,可能会引发此类错误。 建议检查以下内容: - 确认 `stm32f1xx_hal_conf.h` 是否被正确包含并修改。 - 如果项目中有自定义的宏定义,请确保它们不会与标准库中的宏发生冲突[^1]。 #### 解决方案代码示例 ```c // 在 stm32f1xx_hal_conf.h 中确认是否启用了 EXTI 外设支持 #define USE_FULL_ASSERT 0 // 或者根据需求调整此值 ``` --- #### 可能原因二:Makefile 配置不匹配 `make` 工具链中的 `subdir.mk` 文件负责管理目标对象文件(如 `.o` 文件)的生成过程。如果该文件未能正确识别源文件路径或链接器脚本,则可能导致类似的错误。 具体操作如下: - 打开项目的根目录下的 `Makefile` 文件,查找是否存在针对 `stm32f1xx_hal_exti.c` 的编译规则。 - 确保所有必要的源文件均已列入编译列表中,并验证其相对路径无误[^2]。 #### Makefile 调整实例 ```makefile # 添加缺失的目标文件到 SRCS 定义中 SRCS += \ Src/stm32f1xx_hal_msp.c \ Src/stm32f1xx_hal_gpio.c \ Src/stm32f1xx_hal_exti.c ``` --- #### 可能原因三:工具链版本兼容性问题 有时,使用的 GCC ARM 工具链版本较旧或过新都可能引起编译失败。特别是当工具链更新后引入了新的语法检查机制时,一些原本可以忽略的小瑕疵会被标记为严重错误。 推荐措施包括: - 更新至最新稳定版的 GNU Arm Embedded Toolchain。 - 使用 `-Wall -Wextra` 参数重新运行编译命令以捕获潜在警告信息[^3]。 #### 命令行调试技巧 ```bash arm-none-eabi-gcc --version make clean && make all CFLAGS="-Og -ggdb -Wall -Wextra" ``` --- #### 总结 通过以上方法逐一排查,应能找到导致 `Error 87` 的根本原因。无论是由于宏定义不当还是构建环境配置失误,均需仔细核对相关文档资料来解决问题。
阅读全文

相关推荐

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ RGBColor ledStrip[4][LED_PER_CHAIN]; /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.h * @brief : Header for main.c file. * This file contains the common defines of the application. ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __MAIN_H #define __MAIN_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f1xx_hal.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ /* USER CODE BEGIN ET */ /* USER CODE END ET */ /* Exported constants --------------------------------------------------------*/ /* USER CODE BEGIN EC */ /* USER CODE END EC */ /* Exported macro ------------------------------------------------------------*/ /* USER CODE BEGIN EM */ /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ void Error_Handler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ /* Private defines -----------------------------------------------------------*/ /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ #ifdef __cplusplus } #endif #endif /* __MAIN_H */ #ifndef WS2812_H#include "ws2812.h" #include "math.h" // 亮度调整参数 static uint8_t global_brightness = 100; // 亮度因子 static float brightness_factor = 1.0f; // 占空比定义 (72MHz时钟@ARR=71) #define PWM_HIGH 50 // 0.7µs高电平 #define PWM_LOW 25 // 0.35µs高电平 #define PWM_RESET 0 // 复位电平 // PWM数据缓冲区(按通道分组) static uint16_t pwmData[4][PWM_BUFFER_SIZE]; // Timer和DMA句柄 static TIM_HandleTypeDef* htim; static DMA_HandleTypeDef* hdma; static volatile uint8_t dma_busy = 0; // 通道配置 const WS2812_Channel channels[4] = { {NULL, TIM_CHANNEL_1, GPIO_PIN_0, GPIOA}, // PA0 {NULL, TIM_CHANNEL_2, GPIO_PIN_1, GPIOA}, // PA1 {NULL, TIM_CHANNEL_3, GPIO_PIN_2, GPIOA}, // PA2 {NULL, TIM_CHANNEL_4, GPIO_PIN_3, GPIOA} // PA3 }; // 初始化WS2812控制器 void WS2812_Init(TIM_HandleTypeDef* htim, DMA_HandleTypeDef* hdma) { htim = htim; hdma = hdma; // 设置所有通道初始状态 for (int i = 0; i < 4; i++) { HAL_GPIO_WritePin(channels[i].port, channels[i].pin, GPIO_PIN_RESET); } // 清除DMA状态 dma_busy = 0; } // 设置LED颜色(带亮度调整) void WS2812_SetColor(uint8_t ch, uint16_t index, RGBColor color) { if (ch >= 4 || index >= LED_PER_CHAIN) return; // 应用全局亮度 RGBColor adjColor = { .r = (uint8_t)(color.r * brightness_factor), .g = (uint8_t)(color.g * brightness_factor), .b = (uint8_t)(color.b * brightness_factor) }; // 转换为GRB格式 uint32_t grb = ((adjColor.g << 16) | (adjColor.r << 8) | adjColor.b); uint16_t* buf = pwmData[ch] + index * BIT_PER_LED; // 生成波形数据(高位先出) for(int i = 0; i < BIT_PER_LED; i++) { buf[i] = (grb & 0x800000) ? PWM_HIGH : PWM_LOW; grb <<= 1; } } // 设置全局亮度 (0-100) void WS2812_SetBrightness(uint8_t brightness) { if (brightness > 100) brightness = 100; global_brightness = brightness; // 亮度调整公式: // $$ \text{brightness_factor} = \sqrt{\frac{\text{brightness}}{100}} $$ brightness_factor = sqrtf((float)brightness / 100.0f); } // 启动DMA传输 void WS2812_StartDMATransfer(void) { // 配置DMA传输(TIM2_CCR寄存器连续地址) HAL_DMA_Start_IT( hdma, (uint32_t)&pwmData[0][0], (uint32_t)&htim->Instance->CCR1, DMA_TRANSFER_SIZE ); // 启用DMA请求 __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1 | TIM_DMA_CC2 | TIM_DMA_CC3 | TIM_DMA_CC4); __HAL_TIM_ENABLE(htim); dma_busy = 1; } // 更新LED显示 void WS2812_Update(void) { if (dma_busy) return; WS2812_StartDMATransfer(); } // 检查是否忙状态 uint8_t WS2812_IsBusy(void) { return dma_busy; } // DMA传输完成回调 void WS2812_DMACompleteCallback(void) { // 关闭定时器和DMA __HAL_TIM_DISABLE(htim); __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1 | TIM_DMA_CC2 | TIM_DMA_CC3 | TIM_DMA_CC4); // 所有引脚置低电平(产生复位信号) for (int i = 0; i < 4; i++) { HAL_GPIO_WritePin(channels[i].port, channels[i].pin, GPIO_PIN_RESET); } dma_busy = 0; } 22:42:50 **** 项目dengguang配置Debug的增量构建 **** make -j16 all arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.o" arm-none-eabi-gcc "../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.d" -MT"Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.o" arm-none-eabi-gcc "../Core/Src/gpio.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/gpio.d" -MT"Core/Src/gpio.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/gpio.o" arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o" arm-none-eabi-gcc "../Core/Src/stm32f1xx_hal_msp.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/stm32f1xx_hal_msp.d" -MT"Core/Src/stm32f1xx_hal_msp.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/stm32f1xx_hal_msp.o" arm-none-eabi-gcc "../Core/Src/stm32f1xx_it.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/stm32f1xx_it.d" -MT"Core/Src/stm32f1xx_it.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/stm32f1xx_it.o" arm-none-eabi-gcc "../Core/Src/syscalls.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/syscalls.d" -MT"Core/Src/syscalls.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/syscalls.o" ../Core/Src/main.c:25:1: error: unknown type name 'RGBColor' 25 | RGBColor ledStrip[4][LED_PER_CHAIN]; | ^~~~~~~~ ../Core/Src/main.c:25:22: error: 'LED_PER_CHAIN' undeclared here (not in a function) 25 | RGBColor ledStrip[4][LED_PER_CHAIN]; | ^~~~~~~~~~~~~ make: *** [Core/Src/subdir.mk:40: Core/Src/main.o] Error 1 make: *** Waiting for unfinished jobs.... "make -j16 all"以退出代码2结尾。构建可能不完整。 22:42:51 构建失败。 4 错误,0 警告。 (使用1s.155ms) #define WS2812_H #include "stm32f1xx_hal.h" // 每路LED数量(根据内存调整) #define LED_PER_CHAIN 30 // 每LED数据位数 (24位GRB) #define BIT_PER_LED 24 // PWM缓冲大小 #define PWM_BUFFER_SIZE (LED_PER_CHAIN * BIT_PER_LED) // 单个通道数据总数 #define DMA_TRANSFER_SIZE (PWM_BUFFER_SIZE * 4) // 4通道共享同一DMA请求 // LED颜色结构 typedef struct { uint8_t r; uint8_t g; uint8_t b; } RGBColor; // 通道配置结构 typedef struct { TIM_HandleTypeDef* timer; uint32_t channel; uint16_t pin; GPIO_TypeDef* port; } WS2812_Channel; // 初始化函数 void WS2812_Init(TIM_HandleTypeDef* htim, DMA_HandleTypeDef* hdma); // 设置LED颜色 void WS2812_SetColor(uint8_t ch, uint16_t index, RGBColor color); // 设置全局亮度 (0-100) void WS2812_SetBrightness(uint8_t brightness); // 更新LED显示 void WS2812_Update(void); // 复位完成标志 uint8_t WS2812_IsBusy(void); // DMA传输完成回调 void WS2812_DMACompleteCallback(void); #endif

我遇到了如下报错10:49:06 **** Incremental Build of configuration Debug for project test1 **** make -j12 all arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o" arm-none-eabi-gcc "../Core/Src/n3310.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/n3310.d" -MT"Core/Src/n3310.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/n3310.o" ../Core/Src/main.c: In function 'main': ../Core/Src/main.c:106:9: warning: implicit declaration of function 'GPIO_PinRemapConfig' [-Wimplicit-function-declaration] 106 | GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); | ^~~~~~~~~~~~~~~~~~~ ../Core/Src/main.c:106:29: error: 'GPIO_Remap_SWJ_JTAGDisable' undeclared (first use in this function) 106 | GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); | ^~~~~~~~~~~~~~~~~~~~~~~~~~ ../Core/Src/main.c:106:29: note: each undeclared identifier is reported only once for each function it appears in make: *** [Core/Src/subdir.mk:37: Core/Src/main.o] Error 1 make: *** Waiting for unfinished jobs.... ../Core/Src/n3310.c: In function 'LcdInit': ../Core/Src/n3310.c:26:9: error: 'GPIO_InitStruct' undeclared (first use in this function); did you mean 'GPIO_InitStructure'? 26 | GPIO_InitStruct

09:02:49 **** Incremental Build of configuration Debug for project ov2640_AI **** make -j20 all arm-none-eabi-gcc "../Core/Src/ov2640_gpio.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/ov2640_gpio.d" -MT"Core/Src/ov2640_gpio.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/ov2640_gpio.o" ../Core/Src/ov2640_gpio.c: In function 'OV2640_GPIO_Init': ../Core/Src/ov2640_gpio.c:125:7: warning: implicit declaration of function 'OV2640_LoadConfig' [-Wimplicit-function-declaration] 125 | if (OV2640_LoadConfig(hov, ov2640_init_regs) != HAL_OK) return HAL_ERROR; | ^~~~~~~~~~~~~~~~~ ../Core/Src/ov2640_gpio.c: At top level: ../Core/Src/ov2640_gpio.c:140:26: error: conflicting types for 'OV2640_LoadConfig'; have 'HAL_StatusTypeDef(OV2640_GPIO_HandleTypeDef *, const uint8_t (*)[2])' {aka 'HAL_StatusTypeDef(OV2640_GPIO_HandleTypeDef *, const unsigned char (*)[2])'} 140 | static HAL_StatusTypeDef OV2640_LoadConfig(OV2640_GPIO_HandleTypeDef *hov, const uint8_t (*regs)[2]) { | ^~~~~~~~~~~~~~~~~ ../Core/Src/ov2640_gpio.c:125:7: note: previous implicit declaration of 'OV2640_LoadConfig' with type 'int()' 125 | if (OV2640_LoadConfig(hov, ov2640_init_regs) != HAL_OK) return HAL_ERROR; | ^~~~~~~~~~~~~~~~~ make: *** [Core/Src/subdir.mk:40: Core/Src/ov2640_gpio.o] Error 1 "make -j20 all" terminated with exit code 2. Build might be incomplete. 09:02:49 Build Failed. 2 errors, 1 warnings. (took 216ms)

/* * menu.c * * Created on: Jul 10, 2025 * Author: 徐思恬 */ #include "stm32f1xx_hal.h" #include <string.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> // Device header #include "../../icode/oled/oled.h" #include "../../icode/key/key.h" #include "../../icode/flash/flash.h" #include "../../icode/menu/menu.h" #define EH1_CURSOR 0xFFCFFC #define EH2_CURSOR 0xFFCFF8 #define SH_CURSOR 0xFFDFEC #define MFH1_CURSOR 0xFFDFF0 #define MFH2_CURSOR 0xFFDFF8 // 定义全局变量 int EH1 = 0; int EH2 = 0; int FUSE1_ON_TIME = 0; int FUSE2_ON_TIME = 0; SystemParams sysParams; // 编辑相关全局变量 char editBuffer[12] = {0}; // 编辑缓冲区,大小12 char editTitle[20] = {0}; // 编辑标题 int *editTarget = NULL; // 指向要编辑的变量 /** * @brief 计算参数校验和 * @param params: 参数结构体指针 * @retval 校验和 */ uint32_t calculate_checksum(SystemParams *params) { uint32_t sum = 0; uint8_t *data = (uint8_t*)params; size_t len = sizeof(SystemParams) - sizeof(params->checksum); for(size_t i = 0; i < len; i++) { sum = (sum << 3) + data[i]; // 简单但有效的校验算法 } return sum; } /** * @brief 保存参数到Flash * @retval 0:成功, 1:失败 */ uint8_t save_params_to_flash(void) { // 更新系统参数 sysParams.EH1 = EH1; sysParams.EH2 = EH2; sysParams.FUSE1_ON_TIME = FUSE1_ON_TIME; sysParams.FUSE2_ON_TIME = FUSE2_ON_TIME; // 设置魔数和校验和 sysParams.magic = PARAMS_MAGIC; sysParams.checksum = calculate_checksum(&sysParams); // 擦除扇区 W25QXX_Erase_Sector(PARAMS_SECTOR_ADDR / 4096); W25QXX_Wait_Busy(); // 写入数据 W25QXX_Write((uint8_t*)&sysParams, PARAMS_SECTOR_ADDR, sizeof(SystemParams)); // 验证写入 SystemParams verify; W25QXX_Read((uint8_t*)&verify, PARAMS_SECTOR_ADDR, sizeof(SystemParams)); if(memcmp(&sysParams, &verify, sizeof(SystemParams)) != 0) { return 1; // 写入失败 } return 0; // 成功 } /** * @brief 从Flash加载参数 * @retval 0:成功, 1:失败 */ uint8_t load_params_from_flash(void) { // 读取参数 W25QXX_Read((uint8_t*)&sysParams, PARAMS_SECTOR_ADDR, sizeof(SystemParams)); // 检查魔数 if(sysParams.magic != PARAMS_MAGIC) { return 1; // 魔数错误 } // 检查校验和 uint32_t calc_checksum = calculate_checksum(&sysParams); if(sysParams.checksum != calc_checksum) { return 2; // 校验和错误 } // 加载到全局变量 EH1 = sysParams.EH1; EH2 = sysParams.EH2; FUSE1_ON_TIME = sysParams.FUSE1_ON_TIME; FUSE2_ON_TIME = sysParams.FUSE2_ON_TIME; return 0; // 成功 } /** * @brief 初始化参数系统 */ void init_params_system(void) { // 尝试加载参数 if(load_params_from_flash() != 0) { // 加载失败,使用默认值 EH1 = 0; EH2 = 0; FUSE1_ON_TIME = 0; FUSE2_ON_TIME = 0; // 保存默认值 save_params_to_flash(); } } // 定义菜单状态枚举 enum MenuState { MAIN_MENU, SUB_MENU, EDIT_MENU, DISPLAY_MENU }; enum MenuState currentMenu = MAIN_MENU; // 定义菜单选项 int selectedMainMenu = 0; // 一级菜单选项 int selectedSubMenu = 0; // 二级菜单选项 // 全局变量 uint8_t KeyNum; // 用于存储键码值 //int EH1 = 0; // 默认高度(cm) //int EH2 = 0; //int FUSE1_ON_TIME = 0; // 默认时间(s) //int FUSE2_ON_TIME = 0; //char editBuffer[5]; // 编辑缓冲区 //// 编辑相关全局变量 //int* editTarget = NULL; // 指向要修改的变量 //// 全局变量修改 //char editBuffer[12] = {0}; // 初始化缓冲区 /** * @brief 数值编辑函数 - 修复版本 * @param value: 要编辑的变量的指针 * @param title: 编辑界面的标题 * @retval 无 */ void edit_value(int *value, const char *title) { editTarget = value; strncpy(editTitle, title, sizeof(editTitle)-1); editTitle[sizeof(editTitle)-1] = '\0'; // 安全初始化编辑缓冲区 memset(editBuffer, 0, sizeof(editBuffer)); // 清空缓冲区 snprintf(editBuffer, sizeof(editBuffer), "%d", *value); // 安全格式化 } /** * @brief 数据展示函数 - 三级菜单 * @param title: 显示标题 * @param value1: 第一个值 * @param value2: 第二个值 * @retval 无 */ void display_data(const char* title, int value1, int value2) { OLED_Clear(); OLED_ShowString(5, 5, title, OLED_8X16); char displayStr[20]; snprintf(displayStr, sizeof(displayStr), "EH1: %d cm", value1); OLED_ShowString(5, 16, displayStr, OLED_8X16); snprintf(displayStr, sizeof(displayStr), "EH2: %d cm", value2); OLED_ShowString(5, 32, displayStr, OLED_8X16); OLED_ShowString(5, 48, "<- Back", OLED_8X16); OLED_Update(); currentMenu = DISPLAY_MENU; } /** * @brief 处理编辑菜单 * @param 无 * @retval 无 */ //void handle_edit_menu(void) { // while(1) { // // 显示编辑界面 // OLED_Clear(); // OLED_ShowString(5, 0, editTitle, OLED_8X16); // // // 显示当前编辑值 // char valueStr[20]; // snprintf(valueStr, sizeof(valueStr), "Value: %s", editBuffer); // OLED_ShowString(5, 16, valueStr, OLED_8X16); // // // 显示操作提示 // OLED_ShowString(5, 32, "4:Del 8:Confirm", OLED_8X16); // OLED_ShowString(5, 48, "0-9:Input C:Cancel", OLED_8X16); // OLED_Update(); // // KeyNum = Key_GetNum(); // // // 处理数字输入 // if(KeyNum >= 0 && KeyNum <= 9) { // if(strlen(editBuffer) < 10) { // char numChar = '0' + KeyNum; // strncat(editBuffer, &numChar, 1); // } // } // // 删除字符 // else if(KeyNum == 20) { // size_t len = strlen(editBuffer); // if(len > 0) // editBuffer[len-1] = '\0'; // } // // 确认保存 // else if(KeyNum == 21) { // *editTarget = atoi(editBuffer); //// save_params_to_flash(); // currentMenu = SUB_MENU; // return; // } // // 取消编辑 // else if(KeyNum == 12) { // currentMenu = SUB_MENU; // return; // } // } //} /** * @brief 处理编辑菜单 - 完整实现 * @param 无 * @retval 无 */ void handle_edit_menu(void) { // 记录原始值用于取消操作 int original_value = *editTarget; uint8_t cursor_pos = strlen(editBuffer); uint8_t max_length = sizeof(editBuffer) - 1; uint32_t last_key_time = HAL_GetTick(); uint8_t blink_state = 1; // 光标闪烁状态 while(1) { // 获取当前时间 uint32_t current_time = HAL_GetTick(); // 每500ms更新光标闪烁状态 if(current_time - last_key_time > 500) { blink_state = !blink_state; last_key_time = current_time; } // 显示编辑界面 OLED_Clear(); // 显示标题 OLED_ShowString(5, 0, editTitle, OLED_8X16); // 显示当前编辑值 char valueStr[20]; snprintf(valueStr, sizeof(valueStr), "Value: %s", editBuffer); OLED_ShowString(5, 16, valueStr, OLED_8X16); // 显示光标 if(blink_state) { // 计算光标位置 uint8_t cursor_x = 5 + (strlen("Value: ") + cursor_pos) * 6; // 6px per char (8x16 font) OLED_DrawRectangle(cursor_x, 32, cursor_x + 6, 32 + 2, WHITE); } // 显示操作提示 OLED_ShowString(5, 32, "4:Del 8:Confirm", OLED_8X16); OLED_ShowString(5, 48, "0-9:Input C:Cancel", OLED_8X16); OLED_Update(); // 非阻塞方式获取按键 KeyNum = Key_GetNum_NonBlocking(); // 处理数字输入 if(KeyNum >= 0 && KeyNum <= 9) { size_t len = strlen(editBuffer); if(len < max_length) { editBuffer[len] = '0' + KeyNum; editBuffer[len + 1] = '\0'; cursor_pos = len + 1; blink_state = 1; // 重置光标状态 last_key_time = current_time; } } // 删除字符 else if(KeyNum == 20) { size_t len = strlen(editBuffer); if(len > 0) { editBuffer[len - 1] = '\0'; cursor_pos = len - 1; blink_state = 1; // 重置光标状态 last_key_time = current_time; } } // 确认保存 else if(KeyNum == 21) { // 转换缓冲区内容为整数 int new_value = atoi(editBuffer); // 输入验证 if(new_value < 0 || new_value > 9999) { show_message("Invalid value!"); HAL_Delay(1000); continue; } // 更新目标值 *editTarget = new_value; // 保存到Flash FlashStatus status = save_params_to_flash(); if(status == FLASH_OK) { show_message("Saved!"); } else { show_error_message(status); } // 返回二级菜单 currentMenu = SUB_MENU; return; } // 取消编辑 else if(KeyNum == 12) { // 恢复原始值 *editTarget = original_value; currentMenu = SUB_MENU; return; } // 左右移动光标 else if(KeyNum == 13) { // 左键 if(cursor_pos > 0) { cursor_pos--; blink_state = 1; last_key_time = current_time; } } else if(KeyNum == 15) { // 右键 size_t len = strlen(editBuffer); if(cursor_pos < len) { cursor_pos++; blink_state = 1; last_key_time = current_time; } } // 防止CPU占用过高 HAL_Delay(50); } } // 辅助函数实现 void show_message(const char *msg) { OLED_Clear(); OLED_ShowString(5, 16, msg, OLED_8X16); OLED_ShowString(5, 48, "Press any key", OLED_8X16); OLED_Update(); while(Key_GetNum() == 0); // 等待按键 } void show_error_message(FlashStatus status) { OLED_Clear(); switch(status) { case FLASH_ERASE_FAILED: OLED_ShowString(5, 16, "Erase Failed!", OLED_8X16); break; case FLASH_WRITE_FAILED: OLED_ShowString(5, 16, "Write Failed!", OLED_8X16); break; case FLASH_VERIFY_FAILED: OLED_ShowString(5, 16, "Verify Failed!", OLED_8X16); break; case FLASH_CHECKSUM_MISMATCH: OLED_ShowString(5, 16, "Checksum Error!", OLED_8X16); break; case FLASH_MAGIC_INVALID: OLED_ShowString(5, 16, "Invalid Data!", OLED_8X16); break; default: OLED_ShowString(5, 16, "Unknown Error!", OLED_8X16); } OLED_ShowString(5, 48, "Press BACK to return", OLED_8X16); OLED_Update(); while(Key_GetNum() != 12); // 等待返回键 } // 非阻塞按键检测函数 uint8_t Key_GetNum_NonBlocking(void) { static uint8_t last_key = 0; static uint32_t last_time = 0; uint8_t current_key = Key_GetNum(); // 按键消抖处理 if(current_key != 0) { if(current_key == last_key && HAL_GetTick() - last_time < 200) { return 0; // 消抖期内返回0 } last_key = current_key; last_time = HAL_GetTick(); return current_key; } last_key = 0; return 0; } /** * @brief 一级菜单函数,用于显示一级菜单八行选项 * @param 无 * @retval 返回当前行是第几行 */ int menu1(void) { uint8_t flag=1; currentMenu = MAIN_MENU; /*初始显示*/ OLED_ShowString(5,0,"Servo ",OLED_8X16); OLED_ShowString(5,16,"High ",OLED_8X16); OLED_ShowString(5,32,"Flash ",OLED_8X16); OLED_ShowString(5,48,"Time ",OLED_8X16); OLED_Update(); while(1) { KeyNum = Key_GetNum(); if(KeyNum == 20) { //上一项 flag--; if(flag == 0) { flag = 8; } } if(KeyNum == 21) { //下一项 flag++; if(flag == 9) { flag = 1; } } if(KeyNum == 12) { //确认 OLED_Clear(); OLED_Update(); selectedMainMenu = flag; // 记录选择的一级菜单项 currentMenu = SUB_MENU; // 进入二级菜单 return flag; } // 根据当前选项高亮显示 OLED_Clear(); // 显示前4项 if (flag <= 4) { OLED_ShowString(5,0,"Servo ",OLED_8X16); OLED_ShowString(5,16,"High ",OLED_8X16); OLED_ShowString(5,32,"Flash ",OLED_8X16); OLED_ShowString(5,48,"Time ",OLED_8X16); // 高亮当前选项 switch(flag) { case 1: OLED_ReverseArea(5,0,128,16); break; case 2: OLED_ReverseArea(5,16,128,16); break; case 3: OLED_ReverseArea(5,32,128,16); break; case 4: OLED_ReverseArea(5,48,128,16); break; } } else { // 显示后4项 OLED_ShowString(5,0,"fuse ",OLED_8X16); OLED_ShowString(5,16,"buzzer ",OLED_8X16); OLED_ShowString(5,32,"music ",OLED_8X16); OLED_ShowString(5,48,"Settings ",OLED_8X16); // 高亮当前选项 switch(flag) { case 5: OLED_ReverseArea(5,0,128,16); break; case 6: OLED_ReverseArea(5,16,128,16); break; case 7: OLED_ReverseArea(5,32,128,16); break; case 8: OLED_ReverseArea(5,48,128,16); break; } } OLED_Update(); } } /*-----------------------------------二级舵机菜单------------------------------------------------*/ /** * @brief 舵机二级菜单函数 * @param 无 * @retval 0:返回主菜单,1:进入三级菜单 */ int menu2_Servo(void) { uint8_t moflag = 1;//默认在第一行 currentMenu = SUB_MENU; while(1) { OLED_Clear(); OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"Angle setting ",OLED_8X16); OLED_ShowString(5,32,"Time setting ",OLED_8X16); OLED_ShowString(5,48,"High setting ",OLED_8X16); // 高亮当前选项 switch(moflag) { case 1: OLED_ReverseArea(0,0,128,16); break; case 2: OLED_ReverseArea(0,16,128,16); break; case 3: OLED_ReverseArea(0,32,128,16); break; case 4: OLED_ReverseArea(0,48,128,16); break; } OLED_Update(); KeyNum = Key_GetNum(); if(KeyNum == 20) moflag = (moflag == 1) ? 4 : moflag - 1; // 上一项 if(KeyNum == 21) moflag = (moflag % 4) + 1; // 下一项 if(KeyNum == 12) { // 确认 switch(moflag) { case 1: // 返回 currentMenu = MAIN_MENU; return 0; case 2: // 进入角度设置 // 这里可以添加角度设置的三级菜单 // 例如: edit_value(&angle, "Set Angle"); return 1; case 3: // 时间设置 // 例如: edit_value(&time, "Set Time"); return 1; case 4: // 高度设置 // 例如: edit_value(&height, "Set Height"); return 1; } } } } ///*-----------------------------------二级高度菜单-----------------------------------------*/ ///** // * @brief 高度二级菜单函数 // * @param 无 // * @retval 0:返回主菜单,1:进入三级菜单 // */ int menu2_high(void) { uint8_t adflag = 1;//默认在第一行 currentMenu = SUB_MENU; while(1) { OLED_Clear(); OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"high1 setting ",OLED_8X16); OLED_ShowString(5,32,"high2 setting ",OLED_8X16); OLED_ShowString(5,48,"Data display ",OLED_8X16); // 高亮当前选项 switch(adflag) { case 1: OLED_ReverseArea(0,0,128,16); break; case 2: OLED_ReverseArea(0,16,128,16); break; case 3: OLED_ReverseArea(0,32,128,16); break; case 4: OLED_ReverseArea(0,48,128,16); break; } OLED_Update(); KeyNum = Key_GetNum(); if(KeyNum == 20) adflag = (adflag == 1) ? 4 : adflag - 1; // 上一项 if(KeyNum == 21) adflag = (adflag % 4) + 1; // 下一项 if(KeyNum == 12) { // 确认 switch(adflag) { case 1: // 返回 currentMenu = MAIN_MENU; return 0; case 2: // 编辑EH1 edit_value(&EH1, "Set Height 1"); return 1; // 进入编辑状态 case 3: // 编辑EH2 edit_value(&EH2, "Set Height 2"); return 1; case 4: // 数据显示 display_data("Height Data", EH1, EH2); return 1; } } } } /*-----------------------------二级闪存芯片数据菜单-----------------------------------------*/ /** * @brief 闪存芯片数据二级菜单函数 * @param 无 * @retval 0:返回主菜单 */ int menu2_flash(void) { uint8_t ygflag = 1; // 默认在第一行 currentMenu = SUB_MENU; while(1) { OLED_Clear(); OLED_ShowString(5,0,"<- Back ",OLED_8X16); OLED_ShowString(5,16,"Read Flash Info ",OLED_8X16); OLED_ShowString(5,32,"Read Parameters ",OLED_8X16); OLED_ShowString(5,48,"Write Parameters ",OLED_8X16); // 高亮当前选项 switch(ygflag) { case 1: OLED_ReverseArea(0,0,128,16); break; case 2: OLED_ReverseArea(0,16,128,16); break; case 3: OLED_ReverseArea(0,32,128,16); break; case 4: OLED_ReverseArea(0,48,128,16); break; } OLED_Update(); KeyNum = Key_GetNum(); if(KeyNum == 20) // 上一项 ygflag = (ygflag == 1) ? 4 : ygflag - 1; if(KeyNum == 21) // 下一项 ygflag = (ygflag % 4) + 1; if(KeyNum == 12) // 确认 { switch(ygflag) { case 1: // 返回 currentMenu = MAIN_MENU; return 0; case 2: // 读取Flash信息 // display_flash_info(); break; case 3: // 读取参数数据 // display_flash_data(); break; case 4: // 写入参数 // 这里可以添加写入参数的函数,或者直接调用保存函数 // save_params_to_flash(); // 可以显示保存成功或失败的提示 OLED_Clear(); // if(save_params_to_flash() == 0) { // OLED_ShowString(5, 0, "Save Success!", OLED_8X16); // } else { // OLED_ShowString(5, 0, "Save Failed!", OLED_8X16); // } // OLED_ShowString(5, 48, "Press BACK to return", OLED_8X16); // OLED_Update(); while(Key_GetNum() != 12); // 等待返回 break; } } } } /** * @brief 显示Flash存储的参数数据 */ void display_flash_data(void) { // 从Flash中读取参数 SystemParams params; W25QXX_Read((uint8_t*)¶ms, PARAMS_SECTOR_ADDR, sizeof(SystemParams)); // 验证数据有效性 uint8_t valid = 1; if(params.magic != PARAMS_MAGIC) { valid = 0; } else { uint32_t calc_checksum = calculate_checksum(¶ms); if(params.checksum != calc_checksum) { valid = 0; } } // 显示参数 OLED_Clear(); if(valid) { OLED_ShowString(0, 0, "Flash Parameters:", OLED_8X16); char buffer[30]; snprintf(buffer, sizeof(buffer), "EH1: %d cm", params.EH1); OLED_ShowString(0, 16, buffer, OLED_8X16); snprintf(buffer, sizeof(buffer), "EH2: %d cm", params.EH2); OLED_ShowString(0, 32, buffer, OLED_8X16); snprintf(buffer, sizeof(buffer), "Time1: %d s", params.FUSE1_ON_TIME); OLED_ShowString(0, 48, buffer, OLED_8X16); } else { OLED_ShowString(0, 16, "Invalid Data!", OLED_8X16); OLED_ShowString(0, 32, "Check Flash or Reset", OLED_8X16); } OLED_ShowString(0, 48, "Press BACK to return", OLED_8X16); OLED_Update(); // 等待返回键 while(Key_GetNum() != 12) { HAL_Delay(100); } } // //// 显示Flash芯片信息 //void display_flash_info(void) //{ // OLED_Clear(); // // // 显示芯片信息 // uint16_t flash_id = W25QXX_ReadID(); // char id_str[20]; // snprintf(id_str, sizeof(id_str), "ID: 0x%04X", flash_id); // OLED_ShowString(0, 0, id_str, OLED_8X16); // // // 显示容量信息 // const char *size_str = "Unknown"; // switch(W25QXX_TYPE) { // case W25Q80: size_str = "1MB (8Mb)"; break; // case W25Q16: size_str = "2MB (16Mb)"; break; // case W25Q32: size_str = "4MB (32Mb)"; break; // case W25Q64: size_str = "8MB (64Mb)"; break; // case W25Q128: size_str = "16MB (128Mb)"; break; // case W25Q256: size_str = "32MB (256Mb)"; break; // } // char size_info[30]; // snprintf(size_info, sizeof(size_info), "Size: %s", size_str); // OLED_ShowString(0, 16, size_info, OLED_8X16); // // // 显示状态寄存器 // uint8_t sr1 = W25QXX_ReadSR(1); // uint8_t sr2 = W25QXX_ReadSR(2); // uint8_t sr3 = W25QXX_ReadSR(3); // char sr_str[40]; // snprintf(sr_str, sizeof(sr_str), "SR: %02X %02X %02X", sr1, sr2, sr3); // OLED_ShowString(0, 32, sr_str, OLED_8X16); // // // 显示使用情况统计 // char usage_str[30]; // uint32_t total_sectors = get_total_sectors(); // uint32_t used_sectors = get_used_sectors(); // snprintf(usage_str, sizeof(usage_str), "Used: %lu/%lu sectors", // used_sectors, total_sectors); // OLED_ShowString(0, 48, usage_str, OLED_8X16); // // OLED_Update(); // // // 等待返回键 // while(Key_GetNum() != 12) { // HAL_Delay(100); // } //} /*---------------------------------二级时间菜单------------------------------------------*/ /** * @brief 时间二级菜单函数 * @param 无 * @retval 0:返回主菜单,1:进入三级菜单 */ // 显示时间参数的详细视图 void display_time_detail(void) { OLED_Clear(); // 标题 OLED_ShowString(5, 0, "FUSE Timing Details", OLED_8X16); // 分割线 // OLED_DrawLine(0, 16, 128, 16, WHITE); // FUSE1信息 char fuse1Str[40]; snprintf(fuse1Str, sizeof(fuse1Str), "FUSE1 Time: %d s", FUSE1_ON_TIME); OLED_ShowString(5, 20, fuse1Str, OLED_8X16); // FUSE2信息 char fuse2Str[40]; snprintf(fuse2Str, sizeof(fuse2Str), "FUSE2 Time: %d s", FUSE2_ON_TIME); OLED_ShowString(5, 36, fuse2Str, OLED_8X16); // 总时间 int totalTime = FUSE1_ON_TIME + FUSE2_ON_TIME; char totalStr[40]; snprintf(totalStr, sizeof(totalStr), "Total Time: %d s", totalTime); OLED_ShowString(5, 52, totalStr, OLED_8X16); OLED_Update(); // 等待返回键 while(Key_GetNum() != 12) { HAL_Delay(100); } } // 显示时间数据 void display_time_data(void) { OLED_Clear(); OLED_ShowString(5, 0, "Time Settings:", OLED_8X16); char timeStr[30]; snprintf(timeStr, sizeof(timeStr), "FUSE1: %d seconds", FUSE1_ON_TIME); OLED_ShowString(5, 16, timeStr, OLED_8X16); snprintf(timeStr, sizeof(timeStr), "FUSE2: %d seconds", FUSE2_ON_TIME); OLED_ShowString(5, 32, timeStr, OLED_8X16); // 显示操作提示 OLED_ShowString(5, 48, "8:Detail 12:Back", OLED_8X16); OLED_Update(); // 等待用户操作 while(1) { KeyNum = Key_GetNum(); if(KeyNum == 12) { // 返回键 break; } else if(KeyNum == 21) { // 查看详情 display_time_detail(); // 返回后重新显示基本数据 OLED_Clear(); OLED_ShowString(5, 0, "Time Settings:", OLED_8X16); snprintf(timeStr, sizeof(timeStr), "FUSE1: %d seconds", FUSE1_ON_TIME); OLED_ShowString(5, 16, timeStr, OLED_8X16); snprintf(timeStr, sizeof(timeStr), "FUSE2: %d seconds", FUSE2_ON_TIME); OLED_ShowString(5, 32, timeStr, OLED_8X16); OLED_ShowString(5, 48, "8:Detail 12:Back", OLED_8X16); OLED_Update(); } HAL_Delay(50); } } int menu2_time(void) { uint8_t mpuflag = 1;//默认在第一行 currentMenu = SUB_MENU; while(1) { OLED_Clear(); OLED_ShowString(5,0,"<- Back ",OLED_8X16); OLED_ShowString(5,16,"Set FUSE1 Time ",OLED_8X16); OLED_ShowString(5,32,"Set FUSE2 Time ",OLED_8X16); OLED_ShowString(5,48,"Time Data Display",OLED_8X16); // 高亮当前选项 switch(mpuflag) { case 1: OLED_ReverseArea(0,0,128,16); break; case 2: OLED_ReverseArea(0,16,128,16); break; case 3: OLED_ReverseArea(0,32,128,16); break; case 4: OLED_ReverseArea(0,48,128,16); break; } OLED_Update(); KeyNum = Key_GetNum(); if(KeyNum == 20) mpuflag = (mpuflag == 1) ? 4 : mpuflag - 1; // 上一项 if(KeyNum == 21) mpuflag = (mpuflag % 4) + 1; // 下一项 if(KeyNum == 12) { // 确认 switch(mpuflag) { case 1: // 返回 currentMenu = MAIN_MENU; return 0; case 2: // 编辑时间1 edit_value(&FUSE1_ON_TIME, "Set FUSE1 Time"); return 1; case 3: // 编辑时间2 edit_value(&FUSE2_ON_TIME, "Set FUSE2 Time"); return 1; case 4: // 数据显示 display_time_data(); return 1; } } } } /*--------------------------------------------------------------------------------------*/ /*---------------------------------二级fuse菜单------------------------------------------*/ /** * @brief fuse二级菜单函数 * @param 无 * @retval */ int menu2_fuse(void) { int menu3_PPID; uint8_t pidflag = 1;//默认在第一行 OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_Update(); while(1) { KeyNum = Key_GetNum(); if(KeyNum == 20)//上一项 { pidflag--; if(pidflag == 0){pidflag = 4;}//共四行 } if(KeyNum == 21)//下一项 { pidflag++; if(pidflag == 5){pidflag = 1;} } if(KeyNum == 12)//确认 { OLED_Clear(); OLED_Update(); menu3_PPID = pidflag; } if(menu3_PPID == 1){return 0;}//返回0,退到第一级菜单 if(menu3_PPID == 2){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_PPID == 3){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_PPID == 4){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) switch(pidflag) { //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 1: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,0,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 2: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,16,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 3: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,32,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 4: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } } } } /*--------------------------------------------------------------------------------------*/ /*---------------------------------二级蜂鸣器菜单-----------------------------------------*/ /** * @brief 蜂鸣器二级菜单函数 * @param 无 * @retval */ int menu2_buzzer(void) { int menu3_PPID; uint8_t pidflag = 1;//默认在第一行 OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_Update(); while(1) { KeyNum = Key_GetNum(); if(KeyNum == 20)//上一项 { pidflag--; if(pidflag == 0){pidflag = 4;}//共四行 } if(KeyNum == 21)//下一项 { pidflag++; if(pidflag == 5){pidflag = 1;} } if(KeyNum == 12)//确认 { OLED_Clear(); OLED_Update(); menu3_PPID = pidflag; } if(menu3_PPID == 1){return 0;}//返回0,退到第一级菜单 if(menu3_PPID == 2){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_PPID == 3){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_PPID == 4){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) switch(pidflag) { //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 1: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,0,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 2: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,16,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 3: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,32,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 4: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"RESET ",OLED_8X16); OLED_ShowString(5,32,"SET ",OLED_8X16); OLED_ShowString(5,48,"CLOSE ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } } } } /*--------------------------------------------------------------------------------------*/ /*---------------------------------二级音乐菜单-----------------------------------------*/ /** * @brief 音乐二级菜单函数 * @param 无 * @retval */ int menu2_Music(void) { int menu3_MMusic; uint8_t musicflag = 1;//默认在第一行 OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"老男孩 ",OLED_8X16); OLED_ShowString(0,32,"七里香 ",OLED_8X16); OLED_ShowString(0,48,"我记得 ",OLED_8X16); OLED_Update(); while(1) { KeyNum = Key_GetNum(); if(KeyNum == 20)//上一项 { musicflag--; if(musicflag == 0){musicflag = 6;}//共四行 } if(KeyNum == 21)//下一项 { musicflag++; if(musicflag == 7){musicflag = 1;} } if(KeyNum == 12)//确认 { OLED_Clear(); OLED_Update(); menu3_MMusic = musicflag; } if(menu3_MMusic == 1){return 0;}//返回0,退到第一级菜单 if(menu3_MMusic == 2){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_MMusic == 3){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_MMusic == 4){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_MMusic == 5){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_MMusic == 6){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) switch(musicflag) { //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 1: { OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"老男孩 ",OLED_8X16); OLED_ShowString(0,32,"七里香 ",OLED_8X16); OLED_ShowString(0,48,"我记得 ",OLED_8X16); OLED_ReverseArea(0,0,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 2: { OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"老男孩 ",OLED_8X16); OLED_ShowString(0,32,"七里香 ",OLED_8X16); OLED_ShowString(0,48,"我记得 ",OLED_8X16); OLED_ReverseArea(0,16,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 3: { OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"老男孩 ",OLED_8X16); OLED_ShowString(0,32,"七里香 ",OLED_8X16); OLED_ShowString(0,48,"我记得 ",OLED_8X16); OLED_ReverseArea(0,32,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 4: { OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"老男孩 ",OLED_8X16); OLED_ShowString(0,32,"七里香 ",OLED_8X16); OLED_ShowString(0,48,"我记得 ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } case 5: { OLED_ShowString(0,0,"老男孩 ",OLED_8X16); OLED_ShowString(0,16,"七里香 ",OLED_8X16); OLED_ShowString(0,32,"我记得 ",OLED_8X16); OLED_ShowString(0,48,"晴天 ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } case 6: { OLED_ShowString(0,0,"七里香 ",OLED_8X16); OLED_ShowString(0,16,"我记得 ",OLED_8X16); OLED_ShowString(0,32,"晴天 ",OLED_8X16); OLED_ShowString(0,48,"卡农 ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } } } } /*--------------------------------------------------------------------------------------*/ /*---------------------------------二级设置菜单-----------------------------------------*/ /** * @brief 设置控制二级菜单函数 * @param 无 * @retval */ int menu2_Set(void) { int menu3_SSet; uint8_t setflag = 1;//默认在第一行 OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"mode setting ",OLED_8X16); OLED_ShowString(5,32,"animation ",OLED_8X16); OLED_ShowString(5,48,"language ",OLED_8X16); OLED_Update(); while(1) { KeyNum = Key_GetNum(); if(KeyNum == 20)//上一项 { setflag--; if(setflag == 0){setflag = 5;} } if(KeyNum == 21)//下一项 { setflag++; if(setflag == 6){setflag = 1;} } if(KeyNum == 12)//确认 { OLED_Clear(); OLED_Update(); menu3_SSet = setflag; } if(menu3_SSet == 1){return 0;}//返回0,退到第一级菜单 if(menu3_SSet == 2){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_SSet == 3){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_SSet == 4){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) if(menu3_SSet == 5){return 0;}//返回0,退到第一级菜单(因为还没写三级菜单函数) switch(setflag) { //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 1: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"mode setting ",OLED_8X16); OLED_ShowString(5,32,"animation ",OLED_8X16); OLED_ShowString(5,48,"language ",OLED_8X16); OLED_ReverseArea(0,0,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 2: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"mode setting ",OLED_8X16); OLED_ShowString(5,32,"animation ",OLED_8X16); OLED_ShowString(5,48,"language ",OLED_8X16); OLED_ReverseArea(0,16,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 3: { OLED_ShowString(0,0,"<- ",OLED_8X16); OLED_ShowString(0,16,"mode setting ",OLED_8X16); OLED_ShowString(0,32,"animation ",OLED_8X16); OLED_ShowString(0,48,"language ",OLED_8X16); OLED_ReverseArea(0,32,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 4: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"mode setting ",OLED_8X16); OLED_ShowString(5,32,"animation ",OLED_8X16); OLED_ShowString(5,48,"language ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } //再次显示,解决乱码和闪烁问题(确保反相前是亮的状态) case 5: { OLED_ShowString(5,0,"<- ",OLED_8X16); OLED_ShowString(5,16,"mode setting ",OLED_8X16); OLED_ShowString(5,32,"animation ",OLED_8X16); OLED_ShowString(5,48,"language ",OLED_8X16); OLED_ReverseArea(0,48,128,16); OLED_Update(); break; } } } } /** * @brief 主菜单循环 * @param 无 * @retval 无 */ void menu_main_loop(void) { // load_params_from_flash(); while(1) { switch(currentMenu) { case MAIN_MENU: menu1(); // 调用一级菜单,返回后selectedMainMenu被设置 break; case SUB_MENU: // 根据一级菜单的选择调用对应的二级菜单 switch(selectedMainMenu) { case 1: if (menu2_Servo() == 0) currentMenu = MAIN_MENU; break; case 2: if (menu2_high() == 0) currentMenu = MAIN_MENU; break; case 3: if (menu2_flash() == 0) currentMenu = MAIN_MENU; break; case 4: if (menu2_time() == 0) currentMenu = MAIN_MENU; break; case 5: if (menu2_fuse() == 0) currentMenu = MAIN_MENU; break; case 6: if (menu2_buzzer() == 0) currentMenu = MAIN_MENU; break; case 7: if (menu2_Music() == 0) currentMenu = MAIN_MENU; break; case 8: if (menu2_Set() == 0) currentMenu = MAIN_MENU; break; } break; case EDIT_MENU: handle_edit_menu(); break; case DISPLAY_MENU: // 等待返回键 KeyNum = Key_GetNum(); if(KeyNum == 12) { // 按下返回键 currentMenu = SUB_MENU; } break; } } } 19:53:21 **** Incremental Build of configuration Debug for project zhongduan **** make -j20 all arm-none-eabi-gcc "../icode/menu/menu.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"icode/menu/menu.d" -MT"icode/menu/menu.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "icode/menu/menu.o" arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o" ../icode/menu/menu.c: In function 'display_data': ../icode/menu/menu.c:178:27: warning: passing argument 3 of 'OLED_ShowString' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 178 | OLED_ShowString(5, 5, title, OLED_8X16); | ^~~~~ In file included from ../icode/menu/menu.c:14: ../icode/menu/../../icode/oled/oled.h:38:50: note: expected 'char *' but argument is of type 'const char *' 38 | void OLED_ShowString(int16_t X, int16_t Y, char *String, uint8_t FontSize); | ~~~~~~^~~~~~ ../icode/menu/menu.c: In function 'handle_edit_menu': ../icode/menu/menu.c:280:68: error: 'WHITE' undeclared (first use in this function) 280 | OLED_DrawRectangle(cursor_x, 32, cursor_x + 6, 32 + 2, WHITE); | ^~~~~ ../icode/menu/menu.c:280:68: note: each undeclared identifier is reported only once for each function it appears in ../icode/menu/menu.c:289:18: warning: implicit declaration of function 'Key_GetNum_NonBlocking' [-Wimplicit-function-declaration] 289 | KeyNum = Key_GetNum_NonBlocking(); | ^~~~~~~~~~~~~~~~~~~~~~ ../icode/menu/menu.c:319:17: warning: implicit declaration of function 'show_message' [-Wimplicit-function-declaration] 319 | show_message("Invalid value!"); | ^~~~~~~~~~~~ ../icode/menu/menu.c:332:17: warning: implicit declaration of function 'show_error_message' [-Wimplicit-function-declaration] 332 | show_error_message(status); | ^~~~~~~~~~~~~~~~~~ ../icode/menu/menu.c: At top level: ../icode/menu/menu.c:369:6: warning: conflicting types for 'show_message'; have 'void(const char *)' 369 | void show_message(const char *msg) { | ^~~~~~~~~~~~ ../icode/menu/menu.c:319:17: note: previous implicit declaration of 'show_message' with type 'void(const char *)' 319 | show_message("Invalid value!"); | ^~~~~~~~~~~~ ../icode/menu/menu.c: In function 'show_message': ../icode/menu/menu.c:371:28: warning: passing argument 3 of 'OLED_ShowString' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 371 | OLED_ShowString(5, 16, msg, OLED_8X16); | ^~~ ../icode/menu/../../icode/oled/oled.h:38:50: note: expected 'char *' but argument is of type 'const char *' 38 | void OLED_ShowString(int16_t X, int16_t Y, char *String, uint8_t FontSize); | ~~~~~~^~~~~~ ../icode/menu/menu.c: At top level: ../icode/menu/menu.c:378:6: warning: conflicting types for 'show_error_message'; have 'void(FlashStatus)' 378 | void show_error_message(FlashStatus status) { | ^~~~~~~~~~~~~~~~~~ ../icode/menu/menu.c:332:17: note: previous implicit declaration of 'show_error_message' with type 'void(FlashStatus)' 332 | show_error_message(status); | ^~~~~~~~~~~~~~~~~~ ../icode/menu/menu.c:406:9: error: conflicting types for 'Key_GetNum_NonBlocking'; have 'uint8_t(void)' {aka 'unsigned char(void)'} 406 | uint8_t Key_GetNum_NonBlocking(void) { | ^~~~~~~~~~~~~~~~~~~~~~ ../icode/menu/menu.c:289:18: note: previous implicit declaration of 'Key_GetNum_NonBlocking' with type 'int()' 289 | KeyNum = Key_GetNum_NonBlocking(); | ^~~~~~~~~~~~~~~~~~~~~~ make: *** [icode/menu/subdir.mk:19: icode/menu/menu.o] Error 1 make: *** Waiting for unfinished jobs.... "make -j20 all" terminated with exit code 2. Build might be incomplete. 19:53:22 Build Failed. 4 errors, 7 warnings. (took 1s.536ms) 解决错误

zip

最新推荐

recommend-type

langchain4j-anthropic-spring-boot-starter-0.31.0.jar中文文档.zip

1、压缩文件中包含: 中文文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。
recommend-type

TMS320F28335电机控制程序详解:BLDC、PMSM无感有感及异步VF源代码与开发资料

TMS320F28335这款高性能数字信号处理器(DSP)在电机控制领域的应用,涵盖了BLDC(无刷直流电机)、PMSM(永磁同步电机)的无感有感控制以及异步VF(变频调速)程序。文章不仅解释了各类型的电机控制原理,还提供了完整的开发资料,包括源代码、原理图和说明文档,帮助读者深入了解其工作原理和编程技巧。 适合人群:从事电机控制系统开发的技术人员,尤其是对TMS320F28335感兴趣的工程师。 使用场景及目标:适用于需要掌握TMS320F28335在不同电机控制应用场景下具体实现方法的专业人士,旨在提高他们对该微控制器的理解和实际操作能力。 其他说明:文中提供的开发资料为读者提供了从硬件到软件的全面支持,有助于加速项目开发进程并提升系统性能。
recommend-type

基于爬山搜索法的风力发电MPPT控制Simulink仿真:定步长与变步长算法性能对比 - 爬山搜索法 最新版

基于爬山搜索法的风力发电最大功率点追踪(MPPT)控制的Simulink仿真模型,重点比较了定步长和变步长算法在不同风速条件下的表现。文中展示了两种算法的具体实现方法及其优缺点。定步长算法虽然结构简单、计算量小,但在风速突变时响应较慢,存在明显的稳态振荡。相比之下,变步长算法能够根据功率变化动态调整步长,表现出更快的响应速度和更高的精度,尤其在风速突变时优势明显。实验数据显示,变步长算法在风速从8m/s突增至10m/s的情况下,仅用0.3秒即可稳定,功率波动范围仅为±15W,而定步长算法则需要0.8秒,功率波动达到±35W。 适合人群:从事风力发电研究的技术人员、对MPPT控制感兴趣的工程技术人员以及相关专业的高校师生。 使用场景及目标:适用于风力发电系统的设计与优化,特别是需要提高系统响应速度和精度的场合。目标是在不同风速条件下,选择合适的MPPT算法以最大化风能利用率。 其他说明:文章还讨论了定步长算法在风速平稳情况下的优势,提出了根据不同应用场景灵活选择或组合使用这两种算法的建议。
recommend-type

基于MatlabSimulink的风电场调频策略研究:虚拟惯性、超速减载与下垂控制的协调优化

内容概要:本文详细探讨了在Matlab/Simulink环境下,针对风电场调频的研究,尤其是双馈风机调频策略的应用及其与其他调频策略的协调工作。文中介绍了三种主要的调频策略——虚拟惯性、超速减载和下垂控制,并基于三机九节点系统进行了改进,模拟了四组风电机组的协同调频过程。研究指出,虚拟惯性的应用虽然可以提供短期频率支持,但也可能导致频率二次跌落的问题。因此,需要通过超速减载和下垂控制来进行补偿,以维持电网的稳定。此外,文章还展示了在变风速条件下,风电机组对电网频率支撑能力的显著提升,尤其是在高比例风电并网渗透的情况下,频率最低点提高了50%,验证了调频策略的有效性。 适合人群:从事电力系统、风电场运营管理和调频技术研发的专业人士,以及对风电调频感兴趣的科研人员和技术爱好者。 使用场景及目标:适用于希望深入理解风电场调频机制及其优化方法的人群。目标是掌握不同调频策略的工作原理及其协调工作的关键点,提高风电场的运行效率和稳定性。 其他说明:本文通过具体的案例研究和仿真数据,展示了调频策略的实际效果,强调了合理运用调频策略对于风电场稳定运行的重要意义。同时,也为未来的风电调频技术创新提供了理论依据和实践经验。
recommend-type

三菱QL系列PLC在3C-FPC组装机中的定位与伺服控制及触摸屏应用解析

三菱Q系列和L系列PLC在3C-FPC组装机中的具体应用,涵盖硬件架构、软件编程以及实际操作技巧。主要内容包括:使用QX42数字输入模块和QY42P晶体管输出模块进行高效信号处理;采用JE系列伺服控制系统实现高精度四轴联动;利用SFC(顺序功能图)和梯形图编程方法构建稳定可靠的控制系统;通过触摸屏实现多用户管理和权限控制;并分享了一些实用的调试和维护技巧,如流水线节拍控制和工程师模式进入方法。最终,该系统的设备综合效率(OEE)达到了92%以上。 适合人群:从事自动化控制领域的工程师和技术人员,尤其是对三菱PLC有初步了解并希望深入了解其高级应用的人群。 使用场景及目标:适用于需要高精度、高效能的工业生产设备控制场合,旨在帮助用户掌握三菱PLC及其相关组件的应用技能,提高生产效率和产品质量。 其他说明:文中提供了详细的编程实例和操作指南,有助于读者更好地理解和实践。同时提醒使用者在调试过程中应注意伺服刚性参数调整,避免不必要的机械损伤。
recommend-type

Visual C++.NET编程技术实战指南

根据提供的文件信息,可以生成以下知识点: ### Visual C++.NET编程技术体验 #### 第2章 定制窗口 - **设置窗口风格**:介绍了如何通过编程自定义窗口的外观和行为。包括改变窗口的标题栏、边框样式、大小和位置等。这通常涉及到Windows API中的`SetWindowLong`和`SetClassLong`函数。 - **创建六边形窗口**:展示了如何创建一个具有特殊形状边界的窗口,这类窗口不遵循标准的矩形形状。它需要使用`SetWindowRgn`函数设置窗口的区域。 - **创建异形窗口**:扩展了定制窗口的内容,提供了创建非标准形状窗口的方法。这可能需要创建一个不规则的窗口区域,并将其应用到窗口上。 #### 第3章 菜单和控制条高级应用 - **菜单编程**:讲解了如何创建和修改菜单项,处理用户与菜单的交互事件,以及动态地添加或删除菜单项。 - **工具栏编程**:阐述了如何使用工具栏,包括如何创建工具栏按钮、分配事件处理函数,并实现工具栏按钮的响应逻辑。 - **状态栏编程**:介绍了状态栏的创建、添加不同类型的指示器(如文本、进度条等)以及状态信息的显示更新。 - **为工具栏添加皮肤**:展示了如何为工具栏提供更加丰富的视觉效果,通常涉及到第三方的控件库或是自定义的绘图代码。 #### 第5章 系统编程 - **操作注册表**:解释了Windows注册表的结构和如何通过程序对其进行读写操作,这对于配置软件和管理软件设置非常关键。 - **系统托盘编程**:讲解了如何在系统托盘区域创建图标,并实现最小化到托盘、从托盘恢复窗口的功能。 - **鼠标钩子程序**:介绍了钩子(Hook)技术,特别是鼠标钩子,如何拦截和处理系统中的鼠标事件。 - **文件分割器**:提供了如何将文件分割成多个部分,并且能够重新组合文件的技术示例。 #### 第6章 多文档/多视图编程 - **单文档多视**:展示了如何在同一个文档中创建多个视图,这在文档编辑软件中非常常见。 #### 第7章 对话框高级应用 - **实现无模式对话框**:介绍了无模式对话框的概念及其应用场景,以及如何实现和管理无模式对话框。 - **使用模式属性表及向导属性表**:讲解了属性表的创建和使用方法,以及如何通过向导性质的对话框引导用户完成多步骤的任务。 - **鼠标敏感文字**:提供了如何实现点击文字触发特定事件的功能,这在阅读器和编辑器应用中很有用。 #### 第8章 GDI+图形编程 - **图像浏览器**:通过图像浏览器示例,展示了GDI+在图像处理和展示中的应用,包括图像的加载、显示以及基本的图像操作。 #### 第9章 多线程编程 - **使用全局变量通信**:介绍了在多线程环境下使用全局变量进行线程间通信的方法和注意事项。 - **使用Windows消息通信**:讲解了通过消息队列在不同线程间传递信息的技术,包括发送消息和处理消息。 - **使用CriticalSection对象**:阐述了如何使用临界区(CriticalSection)对象防止多个线程同时访问同一资源。 - **使用Mutex对象**:介绍了互斥锁(Mutex)的使用,用以同步线程对共享资源的访问,保证资源的安全。 - **使用Semaphore对象**:解释了信号量(Semaphore)对象的使用,它允许一个资源由指定数量的线程同时访问。 #### 第10章 DLL编程 - **创建和使用Win32 DLL**:介绍了如何创建和链接Win32动态链接库(DLL),以及如何在其他程序中使用这些DLL。 - **创建和使用MFC DLL**:详细说明了如何创建和使用基于MFC的动态链接库,适用于需要使用MFC类库的场景。 #### 第11章 ATL编程 - **简单的非属性化ATL项目**:讲解了ATL(Active Template Library)的基础使用方法,创建一个不使用属性化组件的简单项目。 - **使用ATL开发COM组件**:详细阐述了使用ATL开发COM组件的步骤,包括创建接口、实现类以及注册组件。 #### 第12章 STL编程 - **list编程**:介绍了STL(标准模板库)中的list容器的使用,讲解了如何使用list实现复杂数据结构的管理。 #### 第13章 网络编程 - **网上聊天应用程序**:提供了实现基本聊天功能的示例代码,包括客户端和服务器的通信逻辑。 - **简单的网页浏览器**:演示了如何创建一个简单的Web浏览器程序,涉及到网络通信和HTML解析。 - **ISAPI服务器扩展编程**:介绍了如何开发ISAPI(Internet Server API)服务器扩展来扩展IIS(Internet Information Services)的功能。 #### 第14章 数据库编程 - **ODBC数据库编程**:解释了ODBC(开放数据库互联)的概念,并提供了使用ODBC API进行数据库访问的示例。 - **ADO编程**:介绍了ADO(ActiveX Data Objects)技术,讲解了如何使用ADO进行数据库的增删改查等操作。 #### 第15章 HTML帮助系统编程 - **创建HTML帮助文件**:讲解了如何创建HTML帮助文件(.chm),这是微软帮助系统的一种形式。 - **区分上下文帮助**:提供了在应用程序中实现上下文敏感帮助的技术示例。 #### 第16章 安装和部署项目 - **用安装程序向导创建安装项目**:介绍了如何使用Visual Studio中的安装和部署项目向导,快速创建安装程序。 - **部署应用程序**:阐述了部署应用程序到目标系统的过程,以及如何确保应用程序的正确安装和运行。 以上内容涵盖了Visual C++.NET编程技术体验一书中涉及的各个技术点,并对每个章节中的示例做了详细的说明。这些知识点对于理解和掌握Visual C++.NET编程非常重要,并能够帮助读者在实际项目开发中应用这些技术。
recommend-type

HarmonyOS内核深度探秘:优化自由行旅游系统的策略

# 1. HarmonyOS内核概述与旅游系统需求分析 ## 1.1 HarmonyOS内核概述 HarmonyOS(鸿蒙操作系统)是由华为开发的一个分布式操作系统,旨在提供跨多种设备的无缝体验。其内核设计理念强调高效、安全和模块化,以微内核架构和分布式能力
recommend-type

tkinter模块所有控件

<think>好的,我现在需要回答用户关于Tkinter模块中所有控件列表的问题。首先,我需要回忆Tkinter的基础知识,确保自己了解各个控件的名称和用途。用户希望得到所有支持的控件列表,所以必须全面覆盖,不能遗漏。 首先,我应该从Tkinter的标准控件开始。常见的控件包括Label、Button、Entry这些基础部件。然后是Frame,用于布局,还有Canvas用于绘图。接下来是Checkbutton、Radiobutton,这些属于选择类控件。Listbox和Scrollbar通常一起使用,处理滚动内容。还有Scale(滑块)、Spinbox、Menu、Menubutton这些可能
recommend-type

局域网五子棋游戏:娱乐与聊天的完美结合

标题“网络五子棋”和描述“适合于局域网之间娱乐和聊天!”以及标签“五子棋 网络”所涉及的知识点主要围绕着五子棋游戏的网络版本及其在局域网中的应用。以下是详细的知识点: 1. 五子棋游戏概述: 五子棋是一种两人对弈的纯策略型棋类游戏,又称为连珠、五子连线等。游戏的目标是在一个15x15的棋盘上,通过先后放置黑白棋子,使得任意一方先形成连续五个同色棋子的一方获胜。五子棋的规则简单,但策略丰富,适合各年龄段的玩家。 2. 网络五子棋的意义: 网络五子棋是指可以在互联网或局域网中连接进行对弈的五子棋游戏版本。通过网络版本,玩家不必在同一地点即可进行游戏,突破了空间限制,满足了现代人们快节奏生活的需求,同时也为玩家们提供了与不同对手切磋交流的机会。 3. 局域网通信原理: 局域网(Local Area Network,LAN)是一种覆盖较小范围如家庭、学校、实验室或单一建筑内的计算机网络。它通过有线或无线的方式连接网络内的设备,允许用户共享资源如打印机和文件,以及进行游戏和通信。局域网内的计算机之间可以通过网络协议进行通信。 4. 网络五子棋的工作方式: 在局域网中玩五子棋,通常需要一个客户端程序(如五子棋.exe)和一个服务器程序。客户端负责显示游戏界面、接受用户输入、发送落子请求给服务器,而服务器负责维护游戏状态、处理玩家的游戏逻辑和落子请求。当一方玩家落子时,客户端将该信息发送到服务器,服务器确认无误后将更新后的棋盘状态传回给所有客户端,更新显示。 5. 五子棋.exe程序: 五子棋.exe是一个可执行程序,它使得用户可以在个人计算机上安装并运行五子棋游戏。该程序可能包含了游戏的图形界面、人工智能算法(如果支持单机对战AI的话)、网络通信模块以及游戏规则的实现。 6. put.wav文件: put.wav是一个声音文件,很可能用于在游戏进行时提供声音反馈,比如落子声。在网络环境中,声音文件可能被用于提升玩家的游戏体验,尤其是在局域网多人游戏场景中。当玩家落子时,系统会播放.wav文件中的声音,为游戏增添互动性和趣味性。 7. 网络五子棋的技术要求: 为了确保多人在线游戏的顺利进行,网络五子棋需要具备一些基本的技术要求,包括但不限于稳定的网络连接、高效的数据传输协议(如TCP/IP)、以及安全的数据加密措施(如果需要的话)。此外,还需要有一个良好的用户界面设计来提供直观和舒适的用户体验。 8. 社交与娱乐: 网络五子棋除了是一个娱乐游戏外,它还具有社交功能。玩家可以通过游戏内的聊天系统进行交流,分享经验和策略,甚至通过网络寻找新的朋友。这使得网络五子棋不仅是一个个人娱乐工具,同时也是一种社交活动。 总结来说,网络五子棋结合了五子棋游戏的传统魅力和现代网络技术,使得不同地区的玩家能够在局域网内进行娱乐和聊天,既丰富了人们的娱乐生活,又加强了人际交流。而实现这一切的基础在于客户端程序的设计、服务器端的稳定运行、局域网的高效通信,以及音效文件增强的游戏体验。
recommend-type

自由行旅游新篇章:HarmonyOS技术融合与系统架构深度解析

# 1. HarmonyOS技术概述 ## 1.1 HarmonyOS的起源与发展 HarmonyOS(鸿蒙操作系统)由华为公司开发,旨在构建全场景分布式OS,以应对不同设备间的互联问题。自从2019年首次发布以来,HarmonyOS迅速成长,并迅速应用于智能手机、平板、智能穿戴、车载设备等多种平台。该系