file-type

PlayCase软件:强化数据模型与需求分析

RAR文件

下载需积分: 50 | 5.41MB | 更新于2025-03-11 | 137 浏览量 | 4 下载量 举报 收藏
download 立即下载
paly case需求分析软件是一种专门为了建立数据模型和协助需求分析而设计的工具。它通常应用于软件开发项目中,用于帮助项目团队更好地理解用户需求,从而设计出更符合用户期望的软件产品。接下来,我们将详细介绍这款软件所涉及的关键知识点。 首先,需要分析软件的标题“paly case需求分析软件”。从标题来看,这款软件的主要功能是需求分析,而需求分析是软件工程和系统工程中的重要环节。它涉及从客户处获取、整理和分析需求,并转化为明确的规范,以便后续的系统设计和开发。软件的名称中的“paly”可能是笔误,按照软件功能和上下文理解,应该是“play case”,这可能暗示软件的使用方式或功能特性,我们可以在后续的内容中做进一步的探讨。 从描述“play case建立数据模型和帮助需求分析的软件”可以推断,该软件不仅帮助进行需求分析,还提供了建立数据模型的能力。数据模型是描述数据结构和数据关系的抽象,是信息系统构建的基础。在软件开发中,数据模型通常包括概念模型、逻辑模型和物理模型三个层面。概念模型是对系统需求中涉及的数据进行高层次的抽象,而逻辑模型则进一步定义了数据的存储结构和操作。物理模型着重于在具体数据库系统上的实现细节。 在标签“paly case”中,我们再次注意到了可能的笔误。假设这里的标签与标题中相同,即为“play case”,标签通常用于标识软件的分类和用途。在这里它可能代表软件的名称或品牌,同时暗示了软件使用的便捷性和趣味性,这可以吸引用户在实际使用中进行探索和学习。 在“压缩包子文件的文件名称列表:PlayCase”中,我们可以看到文件名称“PlayCase”实际上可能是软件的执行文件名或软件包名。压缩包子文件可能是一个压缩格式的文件包,它包含了软件的所有相关文件和资源。在IT领域,压缩文件是一种常见的数据存储和传输方式,用于减少文件大小,便于分发和安装。 综上所述,paly case需求分析软件涉及以下几个重要的IT知识点: 1. 需求分析:需求分析是理解用户需求和期望的过程,是软件开发生命周期中至关重要的一环。它包括了需求获取、需求管理和需求规范化等多个步骤。 2. 数据模型:数据模型的构建是分析和设计数据库结构的基础,它帮助设计者和开发者理解数据的组织方式,并指导数据存储和数据访问的设计。 3. 概念模型、逻辑模型和物理模型:这三个层次的数据模型构成了数据设计的框架,从高层次的抽象到具体实现的详细设计,共同构建了一个完整的信息系统。 4. 软件工程:软件工程是应用工程原则于软件开发,它涉及到软件生命周期的每一个阶段,包括需求分析、系统设计、实现、测试和维护等。 5. 文件压缩与传输:在IT行业,文件压缩是常见的数据存储和分享手段,它能够减少文件大小,加快数据传输速度,并在一定程度上保护数据内容。 通过以上的知识点,我们能够全面了解paly case需求分析软件的基本功能和应用领域。在实际应用中,该软件可能还包括了用户交互界面、数据模型可视化工具、数据关系映射、需求跟踪机制等高级特性,以提供更加专业和高效的需求分析和数据建模服务。

相关推荐

filetype

void GMAIN_ChangeState(uint8_t state) { GMAIN_GameState = 7; switch (GMAIN_GameState) { case GAME_M_IDLE: video_control_play(VIDEO_LOGO, VIDEO_PLAY_LOOP, 0); break; case GAME_M_WIN: video_control_play(VIDEO_WIN, VIDEO_PLAY_LOOP, esp_mesh_is_root() ? 10 : 12); break; case GAME_M_WIN_ASSIST: video_control_play(VIDEO_WIN_ASSIST, VIDEO_PLAY_LOOP, esp_mesh_is_root() ? 10 : 15); break; case GAME_M_WWJ_STATE_COIN_IN: video_control_play(VIDEO_WWJ_STATE_COIN_IN, VIDEO_PLAY_SINGLE, 0); break; case GAME_M_WWJ_STATE_COIN_OK: video_control_play(VIDEO_WWJ_STATE_COIN_OK, VIDEO_PLAY_LOOP, 0); break; case GAME_M_WWJ_STATE_GAMMING: video_control_play(VIDEO_WWJ_STATE_GAMMING, VIDEO_PLAY_LOOP, 0); break; case GAME_M_WWJ_STATE_STOP: video_control_play(VIDEO_WWJ_STATE_STOP, VIDEO_PLAY_SINGLE, 0); break; case GAME_M_TIME: static TickType_t last_update = 0; const TickType_t update_interval = pdMS_TO_TICKS(200); // 200ms更新间隔 // 状态进入初始化(只执行一次) if(Time_flag == 0) { // 安全初始化 esp_err_t ret = countdown_timer_init(10.0f); // 显示初始值 RGBPanel_FillScreen(0x0000); RGBPanel_ShowValue(0, 0, 10, RGBPanel_IMAGE_WWJ_STATE_RED_NUM0, RGBPanel_NO_IMAGE); RGBPanel_Update(); countdown_timer_start(); Time_flag = 1; last_update = xTaskGetTickCount(); } // 状态持续处理 else { int integer, decimal; printf("1=%d", Time_flag); // 获取剩余时间(带错误检查) if(!countdown_timer_get_remaining(&integer, &decimal)) { Time_flag = 0; countdown_timer_deinit(); printf("2=%d", Time_flag); break; } TickType_t now = xTaskGetTickCount(); if(now - last_update >= update_interval) { printf("3=%d", Time_flag); RGBPanel_FillScreen(0x0000); RGBPanel_ShowValue(0, 0, integer, RGBPanel_IMAGE_WWJ_STATE_WHITE_NUM0, RGBPanel_NO_IMAGE); RGBPanel_Update(); last_update = now; } } break; case GAME_M_SELF_TEST: video_stop(); GMAIN_TestColorIndex = 0; TIM_TIMING_SET_1MS(GMAIN_TimeObj1, 0); break; } }差不多像这样,在状态值为7的时候进入一个显示倒计时任务,该倒计时可被随时暂停

filetype

#include "esp_system.h" #include "Game_Main.h" #include "driver/gpio.h" #include "esptim.h" #include "esp_random.h" #include "esp_mesh.h" #include "../Fun/videoplay.h" #include "../Fun/draw.h" #include "../Fun/RGBPanel.h" #include "../Fun/LanGame.h" #include "../Fun/GameDevice.h" #include "../Fun/JC24BDevice.h" #include "../Fun/video_control.h" #include "../Fun/LanWifiMesh.h" #include "../Fun/Button.h" #include "../Fun/countdown_timer.h" #include "../config.h" uint8_t GMAIN_GameState; static uint8_t GMAIN_TestColorIndex; static TIM_timing_t GMAIN_TimeObj1; static uint8_t GMAIN_BootClickCount = 0; static TIM_timing_t GMAIN_BootTimeObj; static uint8_t GMAIN_testTime = 3; CountdownTimer game_timer; // 全局倒计时器 static TickType_t last_update = 0; // 全局显示更新时间戳 // 显示区域定义 #define DISPLAY_WIDTH 256 // 屏幕宽度 #define DIGIT_WIDTH 45 // 单数字宽度 #define POINT_WIDTH 22 // 小数点宽度 // 总宽度计算:3整数位 + 小数点 + 2小数位 #define TOTAL_WIDTH (3*DIGIT_WIDTH + POINT_WIDTH + 2*DIGIT_WIDTH) #define START_X ((DISPLAY_WIDTH - TOTAL_WIDTH) / 2) // 居中显示 // 格式化数字为固定位数字符串(自动补零) void format_fixed_digits(int value, int digits, char* output) { for (int i = digits - 1; i >= 0; i--) { output[i] = (value % 10) + '0'; // 取最后一位 value /= 10; } output[digits] = '\0'; // 字符串终止符 } // void GMAIN_ChangeState(uint8_t state) // { // // 状态切换前处理当前状态 // switch (GMAIN_GameState) { // case GAME_M_TIME: // // 如果当前是倒计时状态,暂停计时器 // if (timer_get_state(&game_timer) == TIMER_RUNNING) { // timer_pause(&game_timer); // } // break; // } // GMAIN_GameState = state; // 更新状态 // switch (GMAIN_GameState) // { // case 0: // video_control_play(VIDEO_LOGO, VIDEO_PLAY_LOOP, 0); // break; // case 1: // video_control_play(VIDEO_WIN, VIDEO_PLAY_LOOP, esp_mesh_is_root() ? 10 : 12); // break; // case 2: // video_control_play(VIDEO_WIN_ASSIST, VIDEO_PLAY_LOOP, esp_mesh_is_root() ? 10 : 15); // break; // case 3: // video_control_play(VIDEO_WWJ_STATE_COIN_IN, VIDEO_PLAY_SINGLE, 0); // break; // case 4: // video_control_play(VIDEO_WWJ_STATE_COIN_OK, VIDEO_PLAY_LOOP, 0); // break; // case 5: // video_control_play(VIDEO_WWJ_STATE_GAMMING, VIDEO_PLAY_LOOP, 0); // break; // case GAME_M_WWJ_STATE_STOP: // video_control_play(VIDEO_WWJ_STATE_STOP, VIDEO_PLAY_SINGLE, 0); // break; // case GAME_M_TIME: // // 初始化倒计时器(如果未初始化) // if (timer_get_state(&game_timer) == TIMER_STOPPED) { // timer_init(&game_timer, 10.0f); // 10秒倒计时 // } // // 启动倒计时 // timer_start(&game_timer); // // 初始化显示相关变量 // static TickType_t last_update = 0; // last_update = xTaskGetTickCount(); // 重置更新时间 // break; // case GAME_M_SELF_TEST: // video_stop(); // GMAIN_TestColorIndex = 0; // TIM_TIMING_SET_1MS(GMAIN_TimeObj1, 0); // break; // } // } // void GMAIN_Run(void) // { // switch (GMAIN_GameState) // { // case GAME_M_IDLE: // break; // case GAME_M_WIN: // break; // case GAME_M_WIN_ASSIST: // break; // case GAME_M_WWJ_STATE_COIN_IN: // case GAME_M_WWJ_STATE_COIN_OK: // break; // case GAME_M_WWJ_STATE_GAMMING: // break; // case GAME_M_WWJ_STATE_STOP: // break; // case GAME_M_TIME: // 倒计时状态处理 // // 获取剩余时间 // int integer_seconds, centiseconds; // timer_get_remaining_split(&game_timer, &integer_seconds, ¢iseconds); // TickType_t now = xTaskGetTickCount(); // if (now - last_update >= pdMS_TO_TICKS(10)) { // RGBPanel_FillScreen(0x0000); // RGBPanel_ShowValue(10, 0, integer_seconds, // RGBPanel_IMAGE_WWJ_STATE_RED_NUM0, // RGBPanel_NO_IMAGE); // RGBPanel_drawImageById(40, 0, RGBPanel_IMAGE_WWJ_STATE_RED_Point); // RGBPanel_ShowValue(50, 0, centiseconds, // RGBPanel_IMAGE_WWJ_STATE_RED_NUM0, // RGBPanel_NO_IMAGE); // RGBPanel_Update(); // last_update = now; // } // // 检查是否超时 // if (timer_is_expired(&game_timer)) { // // 倒计时结束处理 // GMAIN_ChangeState(GAME_M_WIN); // 切换到胜利状态 // } // break; // case GAME_M_SELF_TEST: // if (TIM_TIMING_RUN(GMAIN_TimeObj1)) // { // if (GMAIN_TestColorIndex >= 8) // { // JC24BDevice_SendLogoPlay(); // LanWifiMesh_SendLogoPlay(); // GMAIN_ChangeState(GAME_M_IDLE); // return; // } // uint8_t r = 0; // uint8_t g = 0; // uint8_t b = 0; // if ((GMAIN_TestColorIndex & 0x01) > 0) // { // r = 0xFF; // } // if ((GMAIN_TestColorIndex & 0x02) > 0) // { // g = 0xFF; // } // if ((GMAIN_TestColorIndex & 0x04) > 0) // { // b = 0xFF; // } // RGBPanel_FillScreenRGB888(r, g, b); // RGBPanel_Update(); // GMAIN_TestColorIndex++; // TIM_TIMING_SET_100MS(GMAIN_TimeObj1, GMAIN_testTime); // } // break; // } // if (IO_KeyPressed(KEY_BUTTON_TEST)) // { // GMAIN_ChangeState(GAME_M_WIN); // JC24BDevice_BroadcastWin(); // LanWifiMesh_BroadcastWin(); // } // if (TIM_TIMING_RUN(GMAIN_BootTimeObj)) // { // TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 10000); // GMAIN_BootClickCount = 0; // } // if (IO_KeyPressed(KEY_BUTTON_BOOT) && g_config.meshType == CONFIG_MESH_TYPE_ROOT) // { // GMAIN_BootClickCount++; // if (GMAIN_BootClickCount >= 5) // { // config_set_mesh_type(CONFIG_MESH_TYPE_CHILD); // esp_restart(); // } // TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 2); // } // } extern int g_wifi_rssi; static void GMAIN_ShowRootFlag(void); void GMAIN_FrameCall(uint32_t frameIndex) { switch (g_config.matrix_chain) { case 2: { switch (GMAIN_GameState) { case GAME_M_WWJ_STATE_COIN_IN: RGBPanel_ShowValue(54, 18, g_GameDeviceData.coinInCount, RGBPanel_IMAGE_WWJ_STATE_WHITE_NUM0, RGBPanel_NO_IMAGE); RGBPanel_ShowValue(92, 18, g_GameDeviceData.coinPlayCount, RGBPanel_IMAGE_WWJ_STATE_YELLOW_NUM0, RGBPanel_NO_IMAGE); break; } } break; case 3: { switch (GMAIN_GameState) { case GAME_M_WWJ_STATE_COIN_IN: RGBPanel_ShowValue(102, 18, g_GameDeviceData.coinInCount, RGBPanel_IMAGE_WWJ_STATE_WHITE_NUM0, RGBPanel_NO_IMAGE); RGBPanel_ShowValue(144, 18, g_GameDeviceData.coinPlayCount, RGBPanel_IMAGE_WWJ_STATE_YELLOW_NUM0, RGBPanel_NO_IMAGE); break; } } break; case 4: { switch (GMAIN_GameState) { case GAME_M_WWJ_STATE_COIN_IN: case GAME_M_WWJ_STATE_COIN_OK: RGBPanel_ShowValue(168, 18, g_GameDeviceData.coinInCount, RGBPanel_IMAGE_WWJ_STATE_WHITE_NUM0, RGBPanel_NO_IMAGE); RGBPanel_ShowValue(208, 18, g_GameDeviceData.coinPlayCount, RGBPanel_IMAGE_WWJ_STATE_YELLOW_NUM0, RGBPanel_NO_IMAGE); break; } } break; default: break; } if (esp_mesh_is_root()) { GMAIN_ShowRootFlag(); } else if (g_wifi_rssi <= -60 || g_wifi_rssi == 0) { RGBPanel_ShowWifiRssi(g_wifi_rssi); } } // 6*6 static const uint8_t GMAIN_mesh_root_flag[] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, }; #define COLOR_YELLOW 0xFFE0 #define GRADIENT_STEPS (128) // 渐变的步数 static uint16_t gradientProgress = 0; typedef struct { uint8_t colorR; uint8_t colorG; uint8_t colorB; } color_t; static color_t startColor = { 31, 31, 31}; static color_t endColor = { 31, 0, 0}; static uint8_t colorIndex = 0; const uint8_t colorIndexBuff[7] = { 0x7, 0x05, 0x01, 0x03, 0x02, 0x06, 0x04}; uint16_t getGradientColor(void) { // 计算每个通道的渐变步长 uint16_t r = startColor.colorR + (endColor.colorR - startColor.colorR) * gradientProgress / (GRADIENT_STEPS - 1); uint16_t g = startColor.colorG + (endColor.colorG - startColor.colorG) * gradientProgress / (GRADIENT_STEPS - 1); uint16_t b = startColor.colorB + (endColor.colorB - startColor.colorB) * gradientProgress / (GRADIENT_STEPS - 1); // 增加渐变进度 if (++gradientProgress == (GRADIENT_STEPS - 1)) { gradientProgress = 0; startColor = endColor; colorIndex = (colorIndex + 1) % 7; endColor.colorR = ((colorIndexBuff[colorIndex] & 0x04) > 0 ? 31 : 0); endColor.colorG = ((colorIndexBuff[colorIndex] & 0x02) > 0 ? 31 : 0); endColor.colorB = ((colorIndexBuff[colorIndex] & 0x01) > 0 ? 31 : 0); } uint16_t color = (r << 11) | (g << 5) | b; // 返回RGB565格式的颜色值 return color; } static void GMAIN_ShowRootFlag(void) { uint16_t color = getGradientColor(); int16_t startX = 58; startX += (g_config.matrix_chain - 1) * 64; for (uint8_t y = 0; y < 6; y++) { for (uint8_t x = 0; x < 6; x++) { RGBPanel_drawPixel(startX + x, y, (GMAIN_mesh_root_flag[x + y * 6] ? color : 0)); } } } void GMAIN_VideoEndCall(void) { switch (GMAIN_GameState) { case 0: break; case 1: case 2: case 3: case 4: case 5: case GAME_M_SELF_TEST: break; } } void GMAIN_Init(void) { timer_init(&game_timer, 0); // 初始化为0秒 GMAIN_count_down(GAME_M_SELF_TEST); GMAIN_BootClickCount = 0; TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 10000); } void GMAIN_count_down(uint8_t state) { // 状态切换前处理当前状态 switch (GMAIN_GameState) { case 2: // 如果当前是倒计时状态,暂停计时器 if (timer_get_state(&game_timer) == TIMER_RUNNING) { timer_stop(&game_timer); } break; } GMAIN_GameState = state; // 更新状态 switch (GMAIN_GameState) { case 0: video_control_play(VIDEO_LOGO, VIDEO_PLAY_LOOP, 0); break; case 1: video_control_play(VIDEO_COUNTDOWN_READY, VIDEO_PLAY_LOOP, 0); break; case 2: video_stop(); // 初始化倒计时器(如果未初始化) if (timer_get_state(&game_timer) == TIMER_STOPPED) { timer_init(&game_timer, g_GameDeviceData.settingtime_value); } // 启动倒计时 timer_start(&game_timer); // 初始化显示相关变量 static TickType_t last_update = 0; last_update = xTaskGetTickCount(); // 重置更新时间 break; case 3: timer_pause(&game_timer); break; case 4: video_control_play(VIDEO_WIN , VIDEO_PLAY_LOOP, 0); break; case 5: video_control_play(VIDEO_LOSE , VIDEO_PLAY_LOOP, 0); break; case GAME_M_SELF_TEST: video_stop(); GMAIN_TestColorIndex = 0; TIM_TIMING_SET_1MS(GMAIN_TimeObj1, 0); break; } } void GMAIN_count_down_Run(void) { switch (GMAIN_GameState) { case 0: break; case 1: break; case 2: // 正计时状态处理 // 获取已耗时 int integer_seconds, centiseconds; timer_get_elapsed_split(&game_timer, &integer_seconds, ¢iseconds); TickType_t now = xTaskGetTickCount(); if (now - last_update >= pdMS_TO_TICKS(10)) { RGBPanel_FillScreen(0x0000); char int_str[4]; char frac_str[3]; format_fixed_digits(integer_seconds, 3, int_str); format_fixed_digits(centiseconds, 2, frac_str); int current_x = START_X; int current_y = 5; for (int i = 0; i < 3; i++) { uint8_t digit = int_str[i] - '0'; RGBPanel_drawImageById(current_x, current_y, RGBPanel_IMAGE_WWJ_STATE_RED_NUM0 + digit); current_x += DIGIT_WIDTH; } RGBPanel_drawImageById(current_x, current_y+13, RGBPanel_IMAGE_WWJ_STATE_RED_Point); current_x += POINT_WIDTH; for (int i = 0; i < 2; i++) { uint8_t digit = frac_str[i] - '0'; RGBPanel_drawImageById(current_x, current_y, RGBPanel_IMAGE_WWJ_STATE_RED_NUM0 + digit); current_x += DIGIT_WIDTH; } } last_update = now; // 超时判断 if (timer_is_expired(&game_timer)) { vTaskDelay(pdMS_TO_TICKS(20)); // 等待20ms确保显示完成 GMAIN_count_down(3); break; } RGBPanel_Update(); break; case 3: break; case 4: break; case 5: break; case GAME_M_SELF_TEST: if (TIM_TIMING_RUN(GMAIN_TimeObj1)) { if (GMAIN_TestColorIndex >= 8) { JC24BDevice_SendLogoPlay(); LanWifiMesh_SendLogoPlay(); GMAIN_count_down(GAME_M_IDLE); return; } uint8_t r = 0; uint8_t g = 0; uint8_t b = 0; if ((GMAIN_TestColorIndex & 0x01) > 0) { r = 0xFF; } if ((GMAIN_TestColorIndex & 0x02) > 0) { g = 0xFF; } if ((GMAIN_TestColorIndex & 0x04) > 0) { b = 0xFF; } RGBPanel_FillScreenRGB888(r, g, b); RGBPanel_Update(); GMAIN_TestColorIndex++; TIM_TIMING_SET_100MS(GMAIN_TimeObj1, GMAIN_testTime); } break; } // if (IO_KeyPressed(KEY_BUTTON_TEST)) // { // GMAIN_count_down(GAME_M_WIN); // JC24BDevice_BroadcastWin(); // LanWifiMesh_BroadcastWin(); // } if (TIM_TIMING_RUN(GMAIN_BootTimeObj)) { TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 10000); GMAIN_BootClickCount = 0; } if (IO_KeyPressed(KEY_BUTTON_BOOT) && g_config.meshType == CONFIG_MESH_TYPE_ROOT) { GMAIN_BootClickCount++; if (GMAIN_BootClickCount >= 5) { config_set_mesh_type(CONFIG_MESH_TYPE_CHILD); esp_restart(); } TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 2); } } 还是停留在9.98,我觉得是显示问题,帮我看看

filetype

/* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : freertos.c * Description : Code for freertos applications ****************************************************************************** * @attention * * Copyright (c) 2024 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 "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usart.h" #include "gpio.h" #include "tim.h" #include <string.h> #include <stdio.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define MOTOR_PWM_MAX 19999 // PWM最大值 (Period - 1) #define MOTOR_PWM_MIN 0 // PWM最小值 /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ struct uart3_rx_t { int num,ok,en; uint8_t data[28]; int class; float score; int x1,y1,x2,y2; uint8_t datarx; }uart3_rx; struct uart2_rx_t { int num,ok,en; uint8_t data[3]; int shexiangtou_en; int manzaijianche_en; int dangban_en; int youhailaji_en; int chuyulaji_en; int kehuishou_en; int qitalaji_en; uint8_t datarx; }uart2_rx; struct pingmu_tx_t { int manzai,ok,en; int class; float score; int x1,y1,x2,y2; }pingmu_tx; osThreadId motorTaskHandle; osThreadId motor2TaskHandle; osThreadId manzaiTaskHandle; osThreadId txTaskHandle; osThreadId uart6MutexHandle; // 新增:电机控制和超声波测距任务句柄 osThreadId motorControlTaskHandle; // 电机控制任务句柄 osThreadId ultrasonicTaskHandle; // 超声波测距任务句柄 // 新增:超声波测距变量 float ultrasonic1_distance = 0.0f; // 超声波1测量距离 (cm) float ultrasonic2_distance = 0.0f; // 超声波2测量距离 (cm) // 新增:舵机状态跟踪变量 typedef enum { SERVO_IDLE = 0, // 舵机空闲状态(在原位) SERVO_WORKING = 1, // 舵机正在执行分类动作 SERVO_RETURNING = 2 // 舵机正在回到原位 } ServoState_t; volatile ServoState_t servoState = SERVO_IDLE; // 舵机状态 volatile uint32_t servoWorkStartTime = 0; // 舵机工作开始时间 // 新增:电机启动停止延时控制变量 volatile uint32_t motor1_startConditionStartTime = 0; // 电机1启动条件开始时间 volatile uint32_t motor2_startConditionStartTime = 0; // 电机2启动条件开始时间 volatile uint8_t motor1_startConditionActive = 0; // 电机1启动条件是否激活 volatile uint8_t motor2_startConditionActive = 0; // 电机2启动条件是否激活 volatile uint32_t motor1_stopConditionStartTime = 0; // 电机1停止条件开始时间 volatile uint32_t motor2_stopConditionStartTime = 0; // 电机2停止条件开始时间 volatile uint8_t motor1_stopConditionActive = 0; // 电机1停止条件是否激活 volatile uint8_t motor2_stopConditionActive = 0; // 电机2停止条件是否激活 // 电机当前状态 volatile uint8_t motor1_running = 0; // 电机1是否正在运行 volatile uint8_t motor2_running = 0; // 电机2是否正在运行 volatile uint8_t servo_class_to_act = 0; volatile uint8_t is_playing_manzai = 0; // 满载播报进行中标志 volatile uint32_t manzai_play_start = 0; // 满载播报开始时间 volatile uint32_t garbage_delay_start = 0; // 垃圾识别延迟开始时间 volatile uint8_t garbage_to_play = 0; // 待播放的垃圾类别 /* USER CODE END Variables */ osThreadId defaultTaskHandle; osSemaphoreId motorHandle; osSemaphoreId motor2Handle; osSemaphoreId rxlubancatHandle; osSemaphoreId rxpingmuHandle; osSemaphoreId bujingdianjiHandle; osSemaphoreId manzaiSignalHandle; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ int fun (int a,int b, int c); _Noreturn void systemMonitorTask(void const * argument); _Noreturn void motor2Task(void const * argument); //_Noreturn void bujingdianjiTask(void const * argument); _Noreturn void manzaiTask(void const * argument); _Noreturn void txTask(void const * argument); // 新增:电机控制和超声波测距任务函数声明 _Noreturn void motorControlTask(void const * argument); // 核心电机控制任务 _Noreturn void ultrasonicTask(void const * argument); // 超声波测距任务 /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void const * argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* GetIdleTaskMemory prototype (linked to static allocation support) */ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } /* USER CODE END GET_IDLE_TASK_MEMORY */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ osMutexDef(uartMutex); osMutexId uartMutexHandle = osMutexCreate(osMutex(uartMutex)); osMutexDef(uart6Mutex); uart6MutexHandle = osMutexCreate(osMutex(uart6Mutex)); /* USER CODE END RTOS_MUTEX */ /* Create the semaphores(s) */ /* definition and creation of motor */ osSemaphoreDef(motor); motorHandle = osSemaphoreCreate(osSemaphore(motor), 1); /* definition and creation of motor2 */ osSemaphoreDef(motor2); motor2Handle = osSemaphoreCreate(osSemaphore(motor2), 1); /* definition and creation of rxlubancat */ osSemaphoreDef(rxlubancat); rxlubancatHandle = osSemaphoreCreate(osSemaphore(rxlubancat), 1); /* definition and creation of rxpingmu */ osSemaphoreDef(rxpingmu); rxpingmuHandle = osSemaphoreCreate(osSemaphore(rxpingmu), 1); osSemaphoreDef(manzaiSignal); manzaiSignalHandle = osSemaphoreCreate(osSemaphore(manzaiSignal), 1); /* definition and creation of bujingdianji */ osSemaphoreDef(bujingdianji); bujingdianjiHandle = osSemaphoreCreate(osSemaphore(bujingdianji), 1); /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart3_rx.datarx, 1); HAL_UART_Receive_IT(&huart6, (uint8_t *)&uart2_rx.datarx, 1); HAL_NVIC_SetPriority(USART1_IRQn, 6, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); HAL_NVIC_SetPriority(USART6_IRQn, 6, 0); HAL_NVIC_EnableIRQ(USART6_IRQn); TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ // osThreadDef(motorTask, motorTask, osPriorityNormal, 0, 128); // 添加舵机初始化 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); // 舵机1初始位置 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); // 舵机2初始位置 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); // 启动PWM输出 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); // servoState = SERVO_IDLE; // 设置初始状态 // motorTaskHandle = osThreadCreate(osThread(motorTask), NULL); // 保留现有的舵机控制任务 osThreadDef(motor2Task, motor2Task, osPriorityAboveNormal, 0, 128); motor2TaskHandle = osThreadCreate(osThread(motor2Task), NULL); // 保留现有的满载检测任务 osThreadDef(manzaiTask, manzaiTask, osPriorityNormal, 0, 128); manzaiTaskHandle = osThreadCreate(osThread(manzaiTask), NULL); osThreadDef(systemMonitorTask, systemMonitorTask, osPriorityBelowNormal, 0, 128); osThreadCreate(osThread(systemMonitorTask), NULL); // 保留现有的串口屏通讯任务 osThreadDef(txTask, txTask, osPriorityNormal, 2, 128); txTaskHandle = osThreadCreate(osThread(txTask), NULL); // 新增:电机控制任务 osThreadDef(motorControlTask, motorControlTask, osPriorityNormal, 0, 256); motorControlTaskHandle = osThreadCreate(osThread(motorControlTask), NULL); // 新增:超声波测距任务 osThreadDef(ultrasonicTask, ultrasonicTask, osPriorityLow, 0, 256); ultrasonicTaskHandle = osThreadCreate(osThread(ultrasonicTask), NULL); /* USER CODE END RTOS_THREADS */ } _Noreturn void systemMonitorTask(void const * argument) { uint32_t last_heartbeat = HAL_GetTick(); const uint32_t WATCHDOG_TIMEOUT = 30000; // 30秒超时 for(;;) { // 检查任务堆栈使用情况 UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL); if(uxHighWaterMark < 20) { NVIC_SystemReset(); // 堆栈溢出复位 } // 30秒无心跳复位 if(HAL_GetTick() - last_heartbeat > WATCHDOG_TIMEOUT) { NVIC_SystemReset(); } // 更新心跳时间 last_heartbeat = HAL_GetTick(); osDelay(1000); } } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ uint32_t last_activity_time = HAL_GetTick(); uart2_rx.manzaijianche_en = 1; for(;;) { //xSemaphoreTake(rxpingmuHandle,portMAX_DELAY); if(xSemaphoreTake(rxpingmuHandle, 100) == pdTRUE) { switch (uart2_rx.data[1]) { case 1: uart2_rx.shexiangtou_en=0; break; case 0: uart2_rx.shexiangtou_en=1; break; case 3: uart2_rx.manzaijianche_en=0; break; case 2: uart2_rx.manzaijianche_en=1; break; case 4: uart2_rx.dangban_en=0; break; case 5: uart2_rx.dangban_en=1; break; case 6: uart2_rx.youhailaji_en=0; break; case 7: uart2_rx.youhailaji_en=1; break; case 8: uart2_rx.chuyulaji_en=0; break; case 9: uart2_rx.chuyulaji_en=1; break; case 10: uart2_rx.kehuishou_en=0; break; case 11: uart2_rx.kehuishou_en=1; break; case 12: uart2_rx.qitalaji_en=0; break; case 13: uart2_rx.qitalaji_en=1; break; default: break; } last_activity_time = HAL_GetTick(); } if(HAL_GetTick() - last_activity_time > 10000) { // 5秒无活动时软复位 NVIC_SystemReset(); } /* USER CODE END StartDefaultTask */ osDelay(100); } } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ void PlayAudio(uint8_t audio_num) { char cmd[] = {0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30, 0xFF,0xFF,0xFF}; cmd[7] = '0' + audio_num; osMutexWait(uart6MutexHandle, osWaitForever); HAL_UART_Transmit(&huart6, (uint8_t *)cmd, sizeof(cmd), HAL_MAX_DELAY); osMutexRelease(uart6MutexHandle); } void PlayGarbageAudio(uint8_t garbage_class) { uint8_t audio_num = 0; switch (garbage_class) { case 0: case 1: case 3: audio_num = 2; break; // 可回收 case 2: case 5: audio_num = 1; break; // 厨余 case 7: case 8: audio_num = 0; break; // 有害 default: audio_num = 3; break; // 其他 } PlayAudio(audio_num); } // 保留现有的舵机控制任务 - 增加状态跟踪 _Noreturn void motor2Task(void const * argument) { // 上电首次执行初始化动作 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); osDelay(500); // 确保舵机到位 servoState = SERVO_IDLE; for(;;) { xSemaphoreTake(motor2Handle, portMAX_DELAY); //uint8_t current_class = uart3_rx.class; if(is_playing_manzai) { osDelay(100); continue; // 跳过当前动作 } // 🎯 设置舵机工作状态 servoState = SERVO_WORKING; //servoWorkStartTime = HAL_GetTick(); uint8_t current_class = servo_class_to_act; switch (current_class) { //有害垃圾 case 0: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //可回收垃圾 case 1: case 8: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; //厨余垃圾 case 2: case 5: case 6: case 7: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(1000); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //其它垃圾 case 3: case 4: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(500); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; default: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); break; } osDelay(1000); // 执行分类动作的延时 // 🎯 设置舵机回到原位状态 servoState = SERVO_RETURNING; __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); osDelay(1000); // 回到原位的延时 // 🎯 设置舵机空闲状态 servoState = SERVO_IDLE; } osSemaphoreGive(motor2Handle); osDelay(10); } // 保留现有的满载检测任务 _Noreturn void manzaiTask(void const * argument) { for(;;) { osDelay(100); if(HAL_GPIO_ReadPin(load1_GPIO_Port,load1_Pin)==0 || HAL_GPIO_ReadPin(load2_GPIO_Port,load2_Pin)==0 || HAL_GPIO_ReadPin(load3_GPIO_Port,load3_Pin)==0 || HAL_GPIO_ReadPin(load4_GPIO_Port,load4_Pin)==0) { pingmu_tx.manzai=1; xSemaphoreGive(rxlubancatHandle); } } } // 保留现有的串口屏通讯任务 _Noreturn void txTask(void const * argument) { int num=0; const char manzaidata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0xC0,0xAC,0xBB, 0xF8,0xC2,0xFA,0xD4,0xD8,0x22,0xff,0xff,0xff}; // const char kongdata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0x20,0x22,0xff,0xff,0xff}; char play[]={0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30}; unsigned char aa[2]={0}; const char start[]={0x64,0x61,0x74,0x61,0x30,0x2E ,0x69 ,0x6E ,0x73 ,0x65 ,0x72 ,0x74 ,0x28 ,0x22 }; const char end[]={0x22,0x29,0xff,0xff,0xff}; const char end2[]={0xff,0xff,0xff}; //���� const char data1[]={0x5E,0xCD,0xC1,0xB6,0xB9,'\0'}; //���ܲ� const char data2[]={0x5E ,0xB0 ,0xD7 ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //���ܲ� const char data3[]={0x5E ,0xBA ,0xFA ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //ֽ�� const char data4[]={0x5E ,0xD6 ,0xBD ,0xB1 ,0xAD ,'\0'}; //ʯͷ const char data5[]={0x5E ,0xCA ,0xAF ,0xCD ,0xB7 ,'\0'}; //��Ƭ const char data6[]={0x5E ,0xB4,0xC9 ,0xC6 ,0xAC ,'\0'}; //5�ŵ��????? const char data7[]={0x5E ,0x35 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //1�ŵ��????? const char data8[]={0x5E ,0x31 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //�к����� const char data10[]={0x5E ,0xD3 ,0xD0 ,0xBA ,0xA6 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�������� const char data11[]={0x5E ,0xB3 ,0xF8 ,0xD3 ,0xE0 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�ɻ������� const char data12[]={0x5E ,0xBF ,0xC9 ,0xBB ,0xD8 ,0xCA ,0xD5 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�������� const char data13[]={0x5E ,0xC6 ,0xE4 ,0xCB ,0xFB ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; const char* data[]={data8,data4,data7,data5,data6,data2,data3,data1,data1,data1,data1}; uart2_rx.manzaijianche_en=0; uart2_rx.shexiangtou_en=1; for(;;) { xSemaphoreTake(rxlubancatHandle,portMAX_DELAY); if(uart3_rx.ok==1 && uart2_rx.shexiangtou_en ==1 ){ uart3_rx.ok=0; HAL_GPIO_TogglePin(led0_GPIO_Port,led0_Pin); uart3_rx.class=uart3_rx.data[1]-0x30; if(uart3_rx.class<0 || uart3_rx.class>9) uart3_rx.class=11; aa[1]=num%10+0x30; aa[0]=num/10+0x30; HAL_UART_Transmit(&huart6, (uint8_t *) start,sizeof(start),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); switch (uart3_rx.class) { case 0: case 2: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data10, strlen(data10),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x30; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�к����� case 5: case 6: case 7: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data11, strlen(data11),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x31; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� case 1: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data12, strlen(data12),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x32; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�ɻ������� case 3: case 4: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data13, strlen(data13),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x33; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� default: break; } servo_class_to_act = uart3_rx.class; xSemaphoreGive(motor2Handle); num++; if(num>99)num=0; osDelay(2000); } if(pingmu_tx.manzai==1 && uart2_rx.manzaijianche_en==1){ HAL_UART_Transmit(&huart6, (uint8_t *) manzaidata, 20,0xFFFF),pingmu_tx.manzai=0; play[7]=0x34; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); osDelay(2000); } } } // ========== 🎯 新增:电机控制任务 ========== // 功能:控制两个电机的PWM速度,与舵机控制分开 // 电机1:PA6 (TIM3_CH1) // 电机2:PA7 (TIM3_CH2) _Noreturn void motorControlTask(void const * argument) { uint32_t tickCounter = 0; // 延迟启动 osDelay(1000); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // PA6 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); // PA7 for(;;) { // 电机现在由超声波任务自动控制,这里只做周期性检查 if(tickCounter % 50 == 0) { // 可以在这里添加电机状态检查逻辑 } tickCounter++; osDelay(200); } } // ========== 🎯 新增:超声波测距函数 ========== // 简化版本,避免任务阻塞,返回距离值(cm*10) int32_t measureDistanceInt(GPIO_TypeDef* trig_port, uint16_t trig_pin, GPIO_TypeDef* echo_port, uint16_t echo_pin) { volatile uint32_t count = 0; volatile uint32_t time_count = 0; // 1. 确保Trig引脚为低电平 HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_RESET); // 短暂延时 for(volatile int i = 0; i < 1000; i++) __NOP(); // 2. 发送10μs触发脉冲 HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_SET); // 10μs延时 @168MHz for(volatile int i = 0; i < 1680; i++) __NOP(); HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_RESET); // 3. 等待Echo上升沿,超时保护 count = 0; while(HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_RESET) { count++; if(count > 300000) { return -1; // 等待上升沿超时 } } // 4. 测量Echo高电平持续时间 time_count = 0; while(HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_SET) { time_count++; if(time_count > 500000) { return -2; // 高电平持续过长 } } // 5. 计算距离 int32_t distance_x10 = (time_count * 50) / 1000; distance_x10 = distance_x10 * 0.95; // 15%校准系数 // 6. 范围检查:1-100cm if(distance_x10 < 5 || distance_x10 > 1000) { return -4; // 超出合理范围 } return distance_x10; } // ========== 🎯 新增:超声波测距任务 ========== // 真实测距版本,控制电机运行,与舵机同步,不使用USART1发送 _Noreturn void ultrasonicTask(void const * argument) { uint32_t counter = 0; int32_t distance1, distance2; for(;;) { // 测量超声波模块1 (PB2->PD8) distance1 = measureDistanceInt(GPIOB, GPIO_PIN_2, GPIOD, GPIO_PIN_8); // 间隔300ms避免干扰 osDelay(300); // 测量超声波模块2 (PB3->PD9) distance2 = measureDistanceInt(GPIOB, GPIO_PIN_3, GPIOD, GPIO_PIN_9); // ========== 🎯 电机控制逻辑 - 与舵机同步 + 启动停止延时500ms ========== uint32_t currentTime = HAL_GetTick(); // ========== 电机1控制逻辑 ========== if(servoState == SERVO_IDLE){ if(distance1 > 100) { // distance1是cm*10,所以100表示10cm __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 6000); // PA7, 30%速度 } else { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 停止 } // ========== 电机2控制逻辑 ========== if(distance2 > 100) { // distance2是cm*10,所以100表示10cm __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 6000); // PA6, 30%速度 (修改:从TIM4_CH2改为TIM3_CH1) } else { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // 停止 (修改:从TIM4_CH2改为TIM3_CH1) } }else{ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); } char msg[60]; sprintf(msg, "D: %ld.%ld, %ld.%ld cm | M1:%s M2:%s\r\n", distance1 > 0 ? distance1/10 : -1, distance1 > 0 ? distance1%10 : 0, distance2 > 0 ? distance2/10 : -1, distance2 > 0 ? distance2%10 : 0, (distance1 > 100) ? "ON" : "OFF", (distance2 > 100) ? "ON" : "OFF"); HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 1000); counter++; osDelay(1200); // 每1.5秒测量一次 } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ // UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_UART_TxCpltCallback could be implemented in the user file */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; if(huart->Instance == USART6) { // 更健壮的帧检测 static uint8_t frame_buffer[32]; static uint8_t frame_index = 0; // 存储接收到的字节 frame_buffer[frame_index] = uart2_rx.datarx; frame_index = (frame_index + 1) % sizeof(frame_buffer); // 检测结束符 0xFF 0xFF 0xFF if(frame_index >= 3 && frame_buffer[frame_index-3] == 0xFF && frame_buffer[frame_index-2] == 0xFF && frame_buffer[frame_index-1] == 0xFF) { // 复制有效数据 memcpy(uart2_rx.data, frame_buffer, frame_index-3); uart2_rx.num = frame_index-3; uart2_rx.ok = 1; frame_index = 0; xSemaphoreGiveFromISR(rxpingmuHandle, &xHigherPriorityTaskWoken); } HAL_UART_Receive_IT(&huart6, (uint8_t*)&uart2_rx.datarx, 1); } if(huart ->Instance == USART1){ HAL_GPIO_TogglePin(led1_GPIO_Port,led1_Pin); if(uart3_rx.datarx=='@') uart3_rx.num=0; uart3_rx.data[uart3_rx.num]=uart3_rx.datarx; uart3_rx.num++; if(uart3_rx.num>=28){ uart3_rx.num=0; if(uart3_rx.data[27]==']'){ uart3_rx.ok=1; xSemaphoreGiveFromISR(rxlubancatHandle, &xHigherPriorityTaskWoken); } uart3_rx.num = 0; // 重置缓冲区 } HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart3_rx.datarx, 1); } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /* USER CODE END Application */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : freertos.c * Description : Code for freertos applications ****************************************************************************** * @attention * * Copyright (c) 2024 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 "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usart.h" #include "gpio.h" #include "tim.h" #include <string.h> #include <stdio.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define MOTOR_PWM_MAX 19999 // PWM最大值 (Period - 1) #define MOTOR_PWM_MIN 0 // PWM最小值 /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ struct uart3_rx_t { int num,ok,en; uint8_t data[28]; int class; float score; int x1,y1,x2,y2; uint8_t datarx; }uart3_rx; struct uart2_rx_t { int num,ok,en; uint8_t data[3]; int shexiangtou_en; int manzaijianche_en; int dangban_en; int youhailaji_en; int chuyulaji_en; int kehuishou_en; int qitalaji_en; uint8_t datarx; }uart2_rx; struct pingmu_tx_t { int manzai,ok,en; int class; float score; int x1,y1,x2,y2; }pingmu_tx; osThreadId motorTaskHandle; osThreadId motor2TaskHandle; osThreadId manzaiTaskHandle; osThreadId txTaskHandle; osThreadId uart6MutexHandle; // 新增:电机控制和超声波测距任务句柄 osThreadId motorControlTaskHandle; // 电机控制任务句柄 osThreadId ultrasonicTaskHandle; // 超声波测距任务句柄 // 新增:超声波测距变量 float ultrasonic1_distance = 0.0f; // 超声波1测量距离 (cm) float ultrasonic2_distance = 0.0f; // 超声波2测量距离 (cm) // 新增:舵机状态跟踪变量 typedef enum { SERVO_IDLE = 0, // 舵机空闲状态(在原位) SERVO_WORKING = 1, // 舵机正在执行分类动作 SERVO_RETURNING = 2 // 舵机正在回到原位 } ServoState_t; volatile ServoState_t servoState = SERVO_IDLE; // 舵机状态 volatile uint32_t servoWorkStartTime = 0; // 舵机工作开始时间 // 新增:电机启动停止延时控制变量 volatile uint32_t motor1_startConditionStartTime = 0; // 电机1启动条件开始时间 volatile uint32_t motor2_startConditionStartTime = 0; // 电机2启动条件开始时间 volatile uint8_t motor1_startConditionActive = 0; // 电机1启动条件是否激活 volatile uint8_t motor2_startConditionActive = 0; // 电机2启动条件是否激活 volatile uint32_t motor1_stopConditionStartTime = 0; // 电机1停止条件开始时间 volatile uint32_t motor2_stopConditionStartTime = 0; // 电机2停止条件开始时间 volatile uint8_t motor1_stopConditionActive = 0; // 电机1停止条件是否激活 volatile uint8_t motor2_stopConditionActive = 0; // 电机2停止条件是否激活 // 电机当前状态 volatile uint8_t motor1_running = 0; // 电机1是否正在运行 volatile uint8_t motor2_running = 0; // 电机2是否正在运行 volatile uint8_t servo_class_to_act = 0; volatile uint8_t is_playing_manzai = 0; // 满载播报进行中标志 volatile uint32_t manzai_play_start = 0; // 满载播报开始时间 volatile uint32_t garbage_delay_start = 0; // 垃圾识别延迟开始时间 volatile uint8_t garbage_to_play = 0; // 待播放的垃圾类别 /* USER CODE END Variables */ osThreadId defaultTaskHandle; osSemaphoreId motorHandle; osSemaphoreId motor2Handle; osSemaphoreId rxlubancatHandle; osSemaphoreId rxpingmuHandle; osSemaphoreId bujingdianjiHandle; osSemaphoreId manzaiSignalHandle; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ int fun (int a,int b, int c); _Noreturn void systemMonitorTask(void const * argument); _Noreturn void motor2Task(void const * argument); //_Noreturn void bujingdianjiTask(void const * argument); _Noreturn void manzaiTask(void const * argument); _Noreturn void txTask(void const * argument); // 新增:电机控制和超声波测距任务函数声明 _Noreturn void motorControlTask(void const * argument); // 核心电机控制任务 _Noreturn void ultrasonicTask(void const * argument); // 超声波测距任务 /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void const * argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* GetIdleTaskMemory prototype (linked to static allocation support) */ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } /* USER CODE END GET_IDLE_TASK_MEMORY */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ osMutexDef(uartMutex); osMutexId uartMutexHandle = osMutexCreate(osMutex(uartMutex)); osMutexDef(uart6Mutex); uart6MutexHandle = osMutexCreate(osMutex(uart6Mutex)); /* USER CODE END RTOS_MUTEX */ /* Create the semaphores(s) */ /* definition and creation of motor */ osSemaphoreDef(motor); motorHandle = osSemaphoreCreate(osSemaphore(motor), 1); /* definition and creation of motor2 */ osSemaphoreDef(motor2); motor2Handle = osSemaphoreCreate(osSemaphore(motor2), 1); /* definition and creation of rxlubancat */ osSemaphoreDef(rxlubancat); rxlubancatHandle = osSemaphoreCreate(osSemaphore(rxlubancat), 1); /* definition and creation of rxpingmu */ osSemaphoreDef(rxpingmu); rxpingmuHandle = osSemaphoreCreate(osSemaphore(rxpingmu), 1); osSemaphoreDef(manzaiSignal); manzaiSignalHandle = osSemaphoreCreate(osSemaphore(manzaiSignal), 1); /* definition and creation of bujingdianji */ osSemaphoreDef(bujingdianji); bujingdianjiHandle = osSemaphoreCreate(osSemaphore(bujingdianji), 1); /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart3_rx.datarx, 1); HAL_UART_Receive_IT(&huart6, (uint8_t *)&uart2_rx.datarx, 1); HAL_NVIC_SetPriority(USART1_IRQn, 6, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); HAL_NVIC_SetPriority(USART6_IRQn, 6, 0); HAL_NVIC_EnableIRQ(USART6_IRQn); TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ // osThreadDef(motorTask, motorTask, osPriorityNormal, 0, 128); // 添加舵机初始化 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); // 舵机1初始位置 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); // 舵机2初始位置 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); // 启动PWM输出 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); // servoState = SERVO_IDLE; // 设置初始状态 // motorTaskHandle = osThreadCreate(osThread(motorTask), NULL); // 保留现有的舵机控制任务 osThreadDef(motor2Task, motor2Task, osPriorityAboveNormal, 0, 128); motor2TaskHandle = osThreadCreate(osThread(motor2Task), NULL); // 保留现有的满载检测任务 osThreadDef(manzaiTask, manzaiTask, osPriorityNormal, 0, 128); manzaiTaskHandle = osThreadCreate(osThread(manzaiTask), NULL); osThreadDef(systemMonitorTask, systemMonitorTask, osPriorityBelowNormal, 0, 128); osThreadCreate(osThread(systemMonitorTask), NULL); // 保留现有的串口屏通讯任务 osThreadDef(txTask, txTask, osPriorityNormal, 2, 128); txTaskHandle = osThreadCreate(osThread(txTask), NULL); // 新增:电机控制任务 osThreadDef(motorControlTask, motorControlTask, osPriorityNormal, 0, 256); motorControlTaskHandle = osThreadCreate(osThread(motorControlTask), NULL); // 新增:超声波测距任务 osThreadDef(ultrasonicTask, ultrasonicTask, osPriorityLow, 0, 256); ultrasonicTaskHandle = osThreadCreate(osThread(ultrasonicTask), NULL); /* USER CODE END RTOS_THREADS */ } _Noreturn void systemMonitorTask(void const * argument) { uint32_t last_heartbeat = HAL_GetTick(); const uint32_t WATCHDOG_TIMEOUT = 30000; // 30秒超时 for(;;) { // 检查任务堆栈使用情况 UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL); if(uxHighWaterMark < 20) { NVIC_SystemReset(); // 堆栈溢出复位 } // 30秒无心跳复位 if(HAL_GetTick() - last_heartbeat > WATCHDOG_TIMEOUT) { NVIC_SystemReset(); } // 更新心跳时间 last_heartbeat = HAL_GetTick(); osDelay(1000); } } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ uint32_t last_activity_time = HAL_GetTick(); uart2_rx.manzaijianche_en = 1; for(;;) { //xSemaphoreTake(rxpingmuHandle,portMAX_DELAY); if(xSemaphoreTake(rxpingmuHandle, 100) == pdTRUE) { switch (uart2_rx.data[1]) { case 1: uart2_rx.shexiangtou_en=0; break; case 0: uart2_rx.shexiangtou_en=1; break; case 3: uart2_rx.manzaijianche_en=0; break; case 2: uart2_rx.manzaijianche_en=1; break; case 4: uart2_rx.dangban_en=0; break; case 5: uart2_rx.dangban_en=1; break; case 6: uart2_rx.youhailaji_en=0; break; case 7: uart2_rx.youhailaji_en=1; break; case 8: uart2_rx.chuyulaji_en=0; break; case 9: uart2_rx.chuyulaji_en=1; break; case 10: uart2_rx.kehuishou_en=0; break; case 11: uart2_rx.kehuishou_en=1; break; case 12: uart2_rx.qitalaji_en=0; break; case 13: uart2_rx.qitalaji_en=1; break; default: break; } last_activity_time = HAL_GetTick(); } if(HAL_GetTick() - last_activity_time > 10000) { // 5秒无活动时软复位 NVIC_SystemReset(); } /* USER CODE END StartDefaultTask */ osDelay(100); } } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ void PlayAudio(uint8_t audio_num) { char cmd[] = {0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30, 0xFF,0xFF,0xFF}; cmd[7] = '0' + audio_num; osMutexWait(uart6MutexHandle, osWaitForever); HAL_UART_Transmit(&huart6, (uint8_t *)cmd, sizeof(cmd), HAL_MAX_DELAY); osMutexRelease(uart6MutexHandle); } void PlayGarbageAudio(uint8_t garbage_class) { uint8_t audio_num = 0; switch (garbage_class) { case 0: case 1: case 3: audio_num = 2; break; // 可回收 case 2: case 5: audio_num = 1; break; // 厨余 case 7: case 8: audio_num = 0; break; // 有害 default: audio_num = 3; break; // 其他 } PlayAudio(audio_num); } // 保留现有的舵机控制任务 - 增加状态跟踪 _Noreturn void motor2Task(void const * argument) { // 上电首次执行初始化动作 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); osDelay(500); // 确保舵机到位 servoState = SERVO_IDLE; for(;;) { xSemaphoreTake(motor2Handle, portMAX_DELAY); //uint8_t current_class = uart3_rx.class; if(is_playing_manzai) { osDelay(100); continue; // 跳过当前动作 } // 🎯 设置舵机工作状态 servoState = SERVO_WORKING; //servoWorkStartTime = HAL_GetTick(); uint8_t current_class = servo_class_to_act; switch (current_class) { //有害垃圾 case 0: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //可回收垃圾 case 1: case 8: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; //厨余垃圾 case 2: case 5: case 6: case 7: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(1000); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //其它垃圾 case 3: case 4: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(500); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; default: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); break; } osDelay(1000); // 执行分类动作的延时 // 🎯 设置舵机回到原位状态 servoState = SERVO_RETURNING; __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); osDelay(1000); // 回到原位的延时 // 🎯 设置舵机空闲状态 servoState = SERVO_IDLE; } osSemaphoreGive(motor2Handle); osDelay(10); } // 保留现有的满载检测任务 _Noreturn void manzaiTask(void const * argument) { for(;;) { osDelay(100); if(HAL_GPIO_ReadPin(load1_GPIO_Port,load1_Pin)==0 || HAL_GPIO_ReadPin(load2_GPIO_Port,load2_Pin)==0 || HAL_GPIO_ReadPin(load3_GPIO_Port,load3_Pin)==0 || HAL_GPIO_ReadPin(load4_GPIO_Port,load4_Pin)==0) { pingmu_tx.manzai=1; xSemaphoreGive(rxlubancatHandle); } } } // 保留现有的串口屏通讯任务 _Noreturn void txTask(void const * argument) { int num=0; const char manzaidata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0xC0,0xAC,0xBB, 0xF8,0xC2,0xFA,0xD4,0xD8,0x22,0xff,0xff,0xff}; // const char kongdata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0x20,0x22,0xff,0xff,0xff}; char play[]={0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30}; unsigned char aa[2]={0}; const char start[]={0x64,0x61,0x74,0x61,0x30,0x2E ,0x69 ,0x6E ,0x73 ,0x65 ,0x72 ,0x74 ,0x28 ,0x22 }; const char end[]={0x22,0x29,0xff,0xff,0xff}; const char end2[]={0xff,0xff,0xff}; //���� const char data1[]={0x5E,0xCD,0xC1,0xB6,0xB9,'\0'}; //���ܲ� const char data2[]={0x5E ,0xB0 ,0xD7 ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //���ܲ� const char data3[]={0x5E ,0xBA ,0xFA ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //ֽ�� const char data4[]={0x5E ,0xD6 ,0xBD ,0xB1 ,0xAD ,'\0'}; //ʯͷ const char data5[]={0x5E ,0xCA ,0xAF ,0xCD ,0xB7 ,'\0'}; //��Ƭ const char data6[]={0x5E ,0xB4,0xC9 ,0xC6 ,0xAC ,'\0'}; //5�ŵ��????? const char data7[]={0x5E ,0x35 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //1�ŵ��????? const char data8[]={0x5E ,0x31 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //�к����� const char data10[]={0x5E ,0xD3 ,0xD0 ,0xBA ,0xA6 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�������� const char data11[]={0x5E ,0xB3 ,0xF8 ,0xD3 ,0xE0 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�ɻ������� const char data12[]={0x5E ,0xBF ,0xC9 ,0xBB ,0xD8 ,0xCA ,0xD5 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�������� const char data13[]={0x5E ,0xC6 ,0xE4 ,0xCB ,0xFB ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; const char* data[]={data8,data4,data7,data5,data6,data2,data3,data1,data1,data1,data1}; uart2_rx.manzaijianche_en=0; uart2_rx.shexiangtou_en=1; for(;;) { xSemaphoreTake(rxlubancatHandle,portMAX_DELAY); if(uart3_rx.ok==1 && uart2_rx.shexiangtou_en ==1 ){ uart3_rx.ok=0; HAL_GPIO_TogglePin(led0_GPIO_Port,led0_Pin); uart3_rx.class=uart3_rx.data[1]-0x30; if(uart3_rx.class<0 || uart3_rx.class>9) uart3_rx.class=11; aa[1]=num%10+0x30; aa[0]=num/10+0x30; HAL_UART_Transmit(&huart6, (uint8_t *) start,sizeof(start),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); switch (uart3_rx.class) { case 0: case 2: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data10, strlen(data10),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x30; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�к����� case 5: case 6: case 7: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data11, strlen(data11),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x31; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� case 1: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data12, strlen(data12),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x32; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�ɻ������� case 3: case 4: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data13, strlen(data13),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x33; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� default: break; } servo_class_to_act = uart3_rx.class; xSemaphoreGive(motor2Handle); num++; if(num>99)num=0; osDelay(2000); } if(pingmu_tx.manzai==1 && uart2_rx.manzaijianche_en==1){ HAL_UART_Transmit(&huart6, (uint8_t *) manzaidata, 20,0xFFFF),pingmu_tx.manzai=0; play[7]=0x34; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); osDelay(2000); } } } // ========== 🎯 新增:电机控制任务 ========== // 功能:控制两个电机的PWM速度,与舵机控制分开 // 电机1:PA6 (TIM3_CH1) // 电机2:PA7 (TIM3_CH2) _Noreturn void motorControlTask(void const * argument) { uint32_t tickCounter = 0; // 延迟启动 osDelay(1000); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // PA6 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); // PA7 for(;;) { // 电机现在由超声波任务自动控制,这里只做周期性检查 if(tickCounter % 50 == 0) { // 可以在这里添加电机状态检查逻辑 } tickCounter++; osDelay(200); } } // ========== 🎯 新增:超声波测距函数 ========== // 简化版本,避免任务阻塞,返回距离值(cm*10) int32_t measureDistanceInt(GPIO_TypeDef* trig_port, uint16_t trig_pin, GPIO_TypeDef* echo_port, uint16_t echo_pin) { volatile uint32_t count = 0; volatile uint32_t time_count = 0; // 1. 确保Trig引脚为低电平 HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_RESET); // 短暂延时 for(volatile int i = 0; i < 1000; i++) __NOP(); // 2. 发送10μs触发脉冲 HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_SET); // 10μs延时 @168MHz for(volatile int i = 0; i < 1680; i++) __NOP(); HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_RESET); // 3. 等待Echo上升沿,超时保护 count = 0; while(HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_RESET) { count++; if(count > 300000) { return -1; // 等待上升沿超时 } } // 4. 测量Echo高电平持续时间 time_count = 0; while(HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_SET) { time_count++; if(time_count > 500000) { return -2; // 高电平持续过长 } } // 5. 计算距离 int32_t distance_x10 = (time_count * 50) / 1000; distance_x10 = distance_x10 * 0.95; // 15%校准系数 // 6. 范围检查:1-100cm if(distance_x10 < 5 || distance_x10 > 1000) { return -4; // 超出合理范围 } return distance_x10; } // ========== 🎯 新增:超声波测距任务 ========== // 真实测距版本,控制电机运行,与舵机同步,不使用USART1发送 _Noreturn void ultrasonicTask(void const * argument) { uint32_t counter = 0; int32_t distance1, distance2; for(;;) { // 测量超声波模块1 (PB2->PD8) distance1 = measureDistanceInt(GPIOB, GPIO_PIN_2, GPIOD, GPIO_PIN_8); // 间隔300ms避免干扰 osDelay(300); // 测量超声波模块2 (PB3->PD9) distance2 = measureDistanceInt(GPIOB, GPIO_PIN_3, GPIOD, GPIO_PIN_9); // ========== 🎯 电机控制逻辑 - 与舵机同步 + 启动停止延时500ms ========== uint32_t currentTime = HAL_GetTick(); // ========== 电机1控制逻辑 ========== if(servoState == SERVO_IDLE){ if(distance1 > 100) { // distance1是cm*10,所以100表示10cm __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 6000); // PA7, 30%速度 } else { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 停止 } // ========== 电机2控制逻辑 ========== if(distance2 > 100) { // distance2是cm*10,所以100表示10cm __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 6000); // PA6, 30%速度 (修改:从TIM4_CH2改为TIM3_CH1) } else { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // 停止 (修改:从TIM4_CH2改为TIM3_CH1) } }else{ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); } char msg[60]; sprintf(msg, "D: %ld.%ld, %ld.%ld cm | M1:%s M2:%s\r\n", distance1 > 0 ? distance1/10 : -1, distance1 > 0 ? distance1%10 : 0, distance2 > 0 ? distance2/10 : -1, distance2 > 0 ? distance2%10 : 0, (distance1 > 100) ? "ON" : "OFF", (distance2 > 100) ? "ON" : "OFF"); HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 1000); counter++; osDelay(1200); // 每1.5秒测量一次 } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ // UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_UART_TxCpltCallback could be implemented in the user file */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; if(huart->Instance == USART6) { // 更健壮的帧检测 static uint8_t frame_buffer[32]; static uint8_t frame_index = 0; // 存储接收到的字节 frame_buffer[frame_index] = uart2_rx.datarx; frame_index = (frame_index + 1) % sizeof(frame_buffer); // 检测结束符 0xFF 0xFF 0xFF if(frame_index >= 3 && frame_buffer[frame_index-3] == 0xFF && frame_buffer[frame_index-2] == 0xFF && frame_buffer[frame_index-1] == 0xFF) { // 复制有效数据 memcpy(uart2_rx.data, frame_buffer, frame_index-3); uart2_rx.num = frame_index-3; uart2_rx.ok = 1; frame_index = 0; xSemaphoreGiveFromISR(rxpingmuHandle, &xHigherPriorityTaskWoken); } HAL_UART_Receive_IT(&huart6, (uint8_t*)&uart2_rx.datarx, 1); } if(huart ->Instance == USART1){ HAL_GPIO_TogglePin(led1_GPIO_Port,led1_Pin); if(uart3_rx.datarx=='@') uart3_rx.num=0; uart3_rx.data[uart3_rx.num]=uart3_rx.datarx; uart3_rx.num++; if(uart3_rx.num>=28){ uart3_rx.num=0; if(uart3_rx.data[27]==']'){ uart3_rx.ok=1; xSemaphoreGiveFromISR(rxlubancatHandle, &xHigherPriorityTaskWoken); } uart3_rx.num = 0; // 重置缓冲区 } HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart3_rx.datarx, 1); } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /* USER CODE END Application */ 这个程序中为什么超声波控制启停无效?该怎么解决

filetype

#include “esp_system.h” #include “Game_Main.h” #include “driver/gpio.h” #include “esptim.h” #include “esp_random.h” #include “esp_mesh.h” #include “…/Fun/videoplay.h” #include “…/Fun/draw.h” #include “…/Fun/RGBPanel.h” #include “…/Fun/LanGame.h” #include “…/Fun/GameDevice.h” #include “…/Fun/JC24BDevice.h” #include “…/Fun/video_control.h” #include “…/Fun/LanWifiMesh.h” #include “…/Fun/Button.h” #include “…/Fun/countdown_timer.h” #include “…/config.h” uint8_t GMAIN_GameState; static uint8_t GMAIN_TestColorIndex; static TIM_timing_t GMAIN_TimeObj1; static uint8_t GMAIN_BootClickCount = 0; static TIM_timing_t GMAIN_BootTimeObj; static uint8_t GMAIN_testTime = 3; CountdownTimer game_timer; // 全局倒计时器 static TickType_t last_update = 0; // 全局显示更新时间戳 // 显示区域定义 #define DISPLAY_WIDTH 256 // 屏幕宽度 #define DIGIT_WIDTH 45 // 单数字宽度 #define POINT_WIDTH 22 // 小数点宽度 // 总宽度计算:3整数位 + 小数点 + 2小数位 #define TOTAL_WIDTH (3DIGIT_WIDTH + POINT_WIDTH + 2DIGIT_WIDTH) #define START_X ((DISPLAY_WIDTH - TOTAL_WIDTH) / 2) // 居中显示 // 格式化数字为固定位数字符串(自动补零) void format_fixed_digits(int value, int digits, char* output) { for (int i = digits - 1; i >= 0; i–) { output[i] = (value % 10) + ‘0’; // 取最后一位 value /= 10; } output[digits] = ‘\0’; // 字符串终止符 } extern int g_wifi_rssi; static void GMAIN_ShowRootFlag(void); void GMAIN_FrameCall(uint32_t frameIndex) { if (esp_mesh_is_root()) { GMAIN_ShowRootFlag(); } else if (g_wifi_rssi <= -60 || g_wifi_rssi == 0) { RGBPanel_ShowWifiRssi(g_wifi_rssi); } } // 6*6 static const uint8_t GMAIN_mesh_root_flag[] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, }; #define COLOR_YELLOW 0xFFE0 #define GRADIENT_STEPS (128) // 渐变的步数 static uint16_t gradientProgress = 0; typedef struct { uint8_t colorR; uint8_t colorG; uint8_t colorB; } color_t; static color_t startColor = { 31, 31, 31}; static color_t endColor = { 31, 0, 0}; static uint8_t colorIndex = 0; const uint8_t colorIndexBuff[7] = { 0x7, 0x05, 0x01, 0x03, 0x02, 0x06, 0x04}; uint16_t getGradientColor(void) { // 计算每个通道的渐变步长 uint16_t r = startColor.colorR + (endColor.colorR - startColor.colorR) * gradientProgress / (GRADIENT_STEPS - 1); uint16_t g = startColor.colorG + (endColor.colorG - startColor.colorG) * gradientProgress / (GRADIENT_STEPS - 1); uint16_t b = startColor.colorB + (endColor.colorB - startColor.colorB) * gradientProgress / (GRADIENT_STEPS - 1); // 增加渐变进度 if (++gradientProgress == (GRADIENT_STEPS - 1)) { gradientProgress = 0; startColor = endColor; colorIndex = (colorIndex + 1) % 7; endColor.colorR = ((colorIndexBuff[colorIndex] & 0x04) > 0 ? 31 : 0); endColor.colorG = ((colorIndexBuff[colorIndex] & 0x02) > 0 ? 31 : 0); endColor.colorB = ((colorIndexBuff[colorIndex] & 0x01) > 0 ? 31 : 0); } uint16_t color = (r << 11) | (g << 5) | b; // 返回RGB565格式的颜色值 return color; } static void GMAIN_ShowRootFlag(void) { uint16_t color = getGradientColor(); int16_t startX = 58; startX += (g_config.matrix_chain - 1) * 64; for (uint8_t y = 0; y < 6; y++) { for (uint8_t x = 0; x < 6; x++) { RGBPanel_drawPixel(startX + x, y, (GMAIN_mesh_root_flag[x + y * 6] ? color : 0)); } } } void GMAIN_VideoEndCall(void) { switch (GMAIN_GameState) { case GAME_M_IDLE: break; case GAME_M_READY: case GAME_M_TIME: case GAME_M_PAUSE: case GAME_M_WIN: case GAME_M_LOSE: case GAME_M_SELF_TEST: break; } } void GMAIN_Init(void) { timer_init(&game_timer, 0); // 初始化为0秒 GMAIN_count_down(GAME_M_SELF_TEST); GMAIN_BootClickCount = 0; TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 10000); } void GMAIN_count_down(uint8_t state) { // 状态切换前处理当前状态 switch (GMAIN_GameState) { case GAME_M_TIME: // 如果当前是倒计时状态,停止计时器 if (timer_get_state(&game_timer) == TIMER_RUNNING) { timer_stop(&game_timer); } break; } GMAIN_GameState = state; // 更新状态 switch (GMAIN_GameState) { case GAME_M_IDLE: video_control_play(VIDEO_LOGO, VIDEO_PLAY_LOOP, 0); break; case GAME_M_READY: video_control_play(VIDEO_COUNTDOWN_READY, VIDEO_PLAY_LOOP, 0); break; case GAME_M_TIME: video_stop(); // 初始化倒计时器(如果未初始化) if (timer_get_state(&game_timer) == TIMER_STOPPED) { timer_init(&game_timer, g_GameDeviceData.settingtime_value); } // 启动倒计时 timer_start(&game_timer); // 初始化显示相关变量 static TickType_t last_update = 0; last_update = xTaskGetTickCount(); // 重置更新时间 break; case GAME_M_PAUSE: timer_pause(&game_timer); break; case GAME_M_WIN: video_control_play(VIDEO_WIN , VIDEO_PLAY_LOOP, 0); break; case GAME_M_LOSE: video_control_play(VIDEO_LOSE , VIDEO_PLAY_LOOP, 0); break; case GAME_M_SELF_TEST: video_stop(); GMAIN_TestColorIndex = 0; TIM_TIMING_SET_1MS(GMAIN_TimeObj1, 0); break; } } void GMAIN_count_down_Run(void) { switch (GMAIN_GameState) { case GAME_M_IDLE: break; case GAME_M_READY: break; case GAME_M_TIME: // 正计时状态处理 // 获取已耗时 int integer_seconds, centiseconds; timer_get_elapsed_split(&game_timer, &integer_seconds, ¢iseconds); TickType_t now = xTaskGetTickCount(); if (now - last_update >= pdMS_TO_TICKS(10)) { RGBPanel_FillScreen(0x0000); char int_str[4]; char frac_str[3]; format_fixed_digits(integer_seconds, 3, int_str); format_fixed_digits(centiseconds, 2, frac_str); int current_x = START_X; int current_y = 5; for (int i = 0; i < 3; i++) { uint8_t digit = int_str[i] - ‘0’; RGBPanel_drawImageById(current_x, current_y, RGBPanel_IMAGE_WWJ_STATE_RED_NUM0 + digit); current_x += DIGIT_WIDTH; } RGBPanel_drawImageById(current_x, current_y+13, RGBPanel_IMAGE_WWJ_STATE_RED_Point); current_x += POINT_WIDTH; for (int i = 0; i < 2; i++) { uint8_t digit = frac_str[i] - ‘0’; RGBPanel_drawImageById(current_x, current_y, RGBPanel_IMAGE_WWJ_STATE_RED_NUM0 + digit); current_x += DIGIT_WIDTH; } } last_update = now; RGBPanel_Update(); break; case GAME_M_PAUSE: break; case GAME_M_WIN: break; case GAME_M_LOSE: break; case GAME_M_SELF_TEST: if (TIM_TIMING_RUN(GMAIN_TimeObj1)) { if (GMAIN_TestColorIndex >= 8) { JC24BDevice_SendLogoPlay(); LanWifiMesh_SendLogoPlay(); GMAIN_count_down(GAME_M_IDLE); return; } uint8_t r = 0; uint8_t g = 0; uint8_t b = 0; if ((GMAIN_TestColorIndex & 0x01) > 0) { r = 0xFF; } if ((GMAIN_TestColorIndex & 0x02) > 0) { g = 0xFF; } if ((GMAIN_TestColorIndex & 0x04) > 0) { b = 0xFF; } RGBPanel_FillScreenRGB888(r, g, b); RGBPanel_Update(); GMAIN_TestColorIndex++; TIM_TIMING_SET_100MS(GMAIN_TimeObj1, GMAIN_testTime); } break; } // if (IO_KeyPressed(KEY_BUTTON_TEST)) // { // GMAIN_count_down(GAME_M_WIN); // JC24BDevice_BroadcastWin(); // LanWifiMesh_BroadcastWin(); // } if (TIM_TIMING_RUN(GMAIN_BootTimeObj)) { TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 10000); GMAIN_BootClickCount = 0; } if (IO_KeyPressed(KEY_BUTTON_BOOT) && g_config.meshType == CONFIG_MESH_TYPE_ROOT) { GMAIN_BootClickCount++; if (GMAIN_BootClickCount >= 5) { config_set_mesh_type(CONFIG_MESH_TYPE_CHILD); esp_restart(); } TIM_TIMING_SET_1S(GMAIN_BootTimeObj, 2); } } #include “countdown_timer.h” #include “esp_log.h” #include “esp_timer.h” // 全局校准后的tick周期(单位:毫秒) float calibrated_tick_period_ms = 1.0f; // 默认值 /** @brief 校准系统tick周期 @note 应在系统初始化时调用 */ void timer_calibrate(void) { TickType_t start_ticks = xTaskGetTickCount(); uint64_t start_us = esp_timer_get_time(); vTaskDelay(pdMS_TO_TICKS(1000)); // 精确延迟1秒 uint64_t real_duration_us = esp_timer_get_time() - start_us; TickType_t elapsed_ticks = xTaskGetTickCount() - start_ticks; calibrated_tick_period_ms = (real_duration_us / 1000.0f) / elapsed_ticks; ESP_LOGI(“TIMER_CAL”, “Calibrated tick period: %.6f ms”, (double)calibrated_tick_period_ms); } // 初始化计时器 void timer_init(CountdownTimer *timer, float seconds) { timer->total_ms = (uint64_t)(seconds * 1000); // 秒转毫秒 timer->elapsed_ms = 0; timer->state = TIMER_STOPPED; ESP_LOGI(“TIMER”, “Initialized: %.1f seconds (%llu ms)”, seconds, timer->total_ms); } // 启动或恢复计时 void timer_start(CountdownTimer *timer) { if (timer->state == TIMER_STOPPED) { timer->elapsed_ms = 0; // 重置已耗时 timer->start_tick = xTaskGetTickCount(); timer->state = TIMER_RUNNING; ESP_LOGI(“TIMER”, “Started: %llu ms target”, timer->total_ms); } else if (timer->state == TIMER_PAUSED) { // 恢复时补偿暂停时间 TickType_t now = xTaskGetTickCount(); uint64_t paused_duration = (uint64_t)((now - timer->pause_tick) * calibrated_tick_period_ms); timer->start_tick += pdMS_TO_TICKS(paused_duration); timer->state = TIMER_RUNNING; ESP_LOGI(“TIMER”, “Resumed: %llu ms elapsed”, timer->elapsed_ms); } } // 暂停计时 void timer_pause(CountdownTimer *timer) { if (timer->state == TIMER_RUNNING) { timer->state = TIMER_PAUSED; timer->pause_tick = xTaskGetTickCount(); // 更新已耗时 TickType_t now = xTaskGetTickCount(); timer->elapsed_ms = (uint64_t)((now - timer->start_tick) * calibrated_tick_period_ms); ESP_LOGI(“TIMER”, “Paused: %llu ms elapsed”, timer->elapsed_ms); } } // 停止并重置计时 void timer_stop(CountdownTimer *timer) { timer->state = TIMER_STOPPED; timer->elapsed_ms = 0; ESP_LOGI(“TIMER”, “Stopped and reset”); } // 获取已耗时(毫秒) uint64_t timer_get_elapsed_ms(CountdownTimer *timer) { if (timer->state == TIMER_RUNNING) { TickType_t now = xTaskGetTickCount(); return (uint64_t)((now - timer->start_tick) * calibrated_tick_period_ms); } return timer->elapsed_ms; } // 获取已耗时分段显示(秒和百分秒) void timer_get_elapsed_split(CountdownTimer *timer, int *seconds, int *centiseconds) { uint64_t elapsed_ms = timer_get_elapsed_ms(timer); // 限制不超过设定值 if (elapsed_ms > timer->total_ms) { elapsed_ms = timer->total_ms; } // 计算总秒数 *seconds = (int)(elapsed_ms / 1000); // 计算百分秒(四舍五入) uint64_t remainder_ms = elapsed_ms % 1000; *centiseconds = (int)((remainder_ms + 5) / 10); // +5实现四舍五入 // 处理进位 if (*centiseconds >= 100) { *seconds += 1; *centiseconds = 0; } // 调试输出 ESP_LOGD(“TIMER_SPLIT”, “Elapsed: %llu ms → %d.%02d s”, elapsed_ms, *seconds, *centiseconds); } // 检查是否超时 bool timer_is_expired(CountdownTimer *timer) { if (timer->state != TIMER_RUNNING) return false; uint64_t elapsed_ms = timer_get_elapsed_ms(timer); return (elapsed_ms > timer->total_ms); } // 获取当前状态 TimerState timer_get_state(CountdownTimer *timer) { return timer->state; } 我需要一个功能,暂停可以暂停在我设定的值,暂停时屏幕显示的是这个值,设定值与原先的计时开始设定值获取方式是一样的

vjame
  • 粉丝: 1
上传资源 快速赚钱