DEF_TIMESLICE MIN_TIMESLICE

进程调度时间片解析
本文介绍了进程调度中涉及的时间片概念,包括进程的默认时间片为100毫秒及最小时间片为5毫秒的具体定义。通过宏定义的方式展示了不同时间片的计算方法。
进程所获得的默认时间片为100ms
DEF_TIMESLICE = 100ms


#define DEF_TIMESLICE      (100 * HZ / 1000)
#define HZ                 1000


进程所能获得的最小时间片为5ms
MIN_TIMESLICE = 5 ms


#define MIN_TIMESLICE       max(5 * HZ / 1000, 1)
#define HZ                     1000






1.设计目的 通过模拟多级反馈队列调度算法(Multi-Level Feedback Queue, MFQ),加深对操作系统进程调度机制的理解,掌握进程状态转换、时间片分配、优先级调整等核心概念,提升程序设计与系统模拟能力。 2.内容要求 进程建模:使用四元组(pid/到达时间/CPU总需求/I/O间隔)描述进程,数据可通过以下方式获取。 随机生成(数量≥20) 从 JSON/CSV 文件读入 调度队列设计:实现 3 级就绪队列,参数如下: 队列级别 时间片长度 调度规则 Q0 2 ms 时间片轮转 Q1 4 ms 时间片轮转 Q2 无限 先来先服务(FCFS) 进程状态转换: 若进程在时间片用尽前阻塞或结束,保留当前优先级; 若时间片用尽未结束,降入下一级队列。 阻塞模拟:进程每运行I/O间隔毫秒后进入阻塞状态,阻塞时长 5 ms。 输出与保存: 甘特图(以pid-time线性文本格式呈现); 每个进程的周转时间、带权周转时间、等待时间; 系统平均 CPU 利用率、吞吐量。 3.关键概念与算法说明 进程控制块(PCB)参数 字段名 含义 pid 进程标识符 arrive 到达时间(ms) cpu_need 剩余 CPU 执行时间(ms) io_gap I/O 阻塞间隔(ms) cpu_since_io 距上次 I/O 已执行时间(ms) state 进程状态(NEW/READY/RUN/BLOCK/DONE) queue_level 所在队列级别(0/1/2) start/finish 首次运行时间 / 完成时间(ms) wait_time 总等待时间(ms) 调度核心逻辑 时间推进:以 1ms 为单位模拟系统时钟,每 Tick 执行以下操作:  检查新到达进程,加入 Q0;  检查阻塞进程,到期后移回原队列;  若 CPU 空闲,按优先级从高到低(Q0→Q1→Q2)调度进程;  运行当前进程 1ms,更新 CPU 需求、时间片剩余量及 I/O 状态;  处理进程结束、I/O 阻塞或时间片用尽场景,调整进程状态与队列。 优先级调整规则:  进程在时间片内完成或阻塞,保留当前队列级别;  时间片用尽未完成,队列级别 + 1(最多到 Q2)。 性能指标计算  周转时间 = 完成时间 - 到达时间;  带权周转时间 = 周转时间 / CPU 总需求;  等待时间 = 总时间 - CPU 执行时间;  CPU 利用率 = (CPU 忙时 / 总时间)× 100%;  吞吐量 = 完成进程数 / 总时间(进程 /ms)。 4.输入 / 输出样例 输入样例(JSON) [ {"pid": 1, "arrive": 0, "cpu_total": 15, "io_gap": 5}, {"pid": 2, "arrive": 2, "cpu_total": 20, "io_gap": 8}, {"pid": 3, "arrive": 3, "cpu_total": 10, "io_gap": 4} ] 输出样例(甘特图文本) ===== 甘特图(时间轴步长 1ms)===== 0-1: PID1 1-2: PID1 2-3: PID2 3-4: PID3 4-5: PID3 (BLOCK) 5-6: PID1 ... 性能指标样例 PID 1 到达0ms 完成25ms 周转25 带权1.67 等待10 PID 2 到达2ms 完成30ms 周转28 带权1.40 等待12 ... 平均周转时间: 26.50 ms CPU利用率: 85.32% 吞吐量: 0.08 进程/ms 5.设计成果要求 程序功能:实现完整的多级反馈队列调度逻辑,支持进程生成、状态转换、I/O 阻塞模拟及结果统计。 输出文件:按格式保存甘特图、进程性能指标及系统统计数据。 代码规范:注释清晰,结构合理,支持参数配置(如队列数量、时间片长度)。 根据上述要求编写一个完整的代码,使其满足上述要求,输出的结果不为空求满足要求,并对每句代码加以注释
06-29
#include <iostream> #include <fstream> #include <vector> #include <queue> #include <algorithm> #include <iomanip> #include <string> using namespace std; // 进程状态枚举 enum ProcessState { READY, RUNNING, BLOCKED, FINISHED }; // 片段类型枚举 enum SegmentType { CPU_SEGMENT, IO_SEGMENT }; // 进程片段结构体 struct Segment { SegmentType type; int length; int remaining; // 剩余执行时间 Segment(SegmentType t, int len) : type(t), length(len), remaining(len) {} }; // 进程结构体 struct Process { int id; int priority; int arrivalTime; vector<Segment> segments; int currentSegment; // 当前执行的片段索引 // 统计信息 int finishTime; int timeSliceUsed; int readyWaitTime; int IOWaitTime; int CPUTime; int IOTime; int turnaroundTime; double weightedTurnaroundTime; ProcessState state; int remainingTimeSlice; // 当前时间片剩余时间 Process(int id, int pri, int arr, const vector<Segment>& segs) : id(id), priority(pri), arrivalTime(arr), segments(segs), currentSegment(0), finishTime(0), timeSliceUsed(0), readyWaitTime(0), IOWaitTime(0), CPUTime(0), IOTime(0), turnaroundTime(0), weightedTurnaroundTime(0.0), state(READY), remainingTimeSlice(0) { } }; // 系统统计结构体 struct SystemStats { int totalProcesses; int timeSlice; int totalCPUTime; int totalIOTime; double avgReadyWaitTime; double avgIOWaitTime; double avgCPUTime; double avgIOTime; double avgTurnaroundTime; double avgWeightedTurnaroundTime; }; class Scheduler { private: vector<Process> processes; int timeSlice; int currentTime; queue<int> readyQueue; // 存储进程ID queue<int> ioQueue; // 存储进程ID vector<int> finishedProcesses; // 存储已完成进程ID Process* currentProcess; // 当前运行的进程 bool cpuBusy; bool ioBusy; Process* ioProcess; // 当前使用IO设备的进程 SystemStats stats; public: Scheduler(const vector<Process>& procs, int ts) : processes(procs), timeSlice(ts), currentTime(0), currentProcess(nullptr), cpuBusy(false), ioBusy(false), ioProcess(nullptr) { // 初始化统计信息 stats.totalProcesses = procs.size(); stats.timeSlice = ts; stats.totalCPUTime = 0; stats.totalIOTime = 0; // 按到达时间排序进程 sort(processes.begin(), processes.end(), [](const Process& a, const Process& b) { return a.arrivalTime < b.arrivalTime; }); // 初始化就绪队列 for (int i = 0; i < processes.size(); i++) { if (processes[i].arrivalTime <= currentTime) { readyQueue.push(i); } } } // 简单轮转调度 - 主调度循环 // 这是整个调度系统的核心,采用时间驱动的方式模拟进程调度 void roundRobinScheduling() { // 主循环:持续运行直到所有进程都完成 while (!allProcessesFinished()) { // 检查是否有新进程到达(到达时间等于当前时间) checkNewArrivals(); // IO设备处理:处理正在使用IO的进程,以及从IO队列中取出新进程 processIO(); // CPU调度:处理当前运行的进程,以及从就绪队列中调度新进程 scheduleCPU(); // 时间推进:每个时钟周期时间加1 currentTime++; // 更新等待时间统计:增加就绪队列和IO队列中进程的等待时间 updateWaitTimes(); } // 所有进程完成后,计算最终统计信息(平均等待时间、周转时间等) calculateStatistics(); } private: bool allProcessesFinished() { return finishedProcesses.size() == processes.size(); } // 检查新到达的进程 - 每个时钟周期调用一次 // 将到达时间等于当前时间的进程加入就绪队列 void checkNewArrivals() { for (int i = 0; i < processes.size(); i++) { // 检查进程是否在当前时刻到达且处于就绪状态 if (processes[i].arrivalTime == currentTime && processes[i].state == READY) { readyQueue.push(i); // 加入就绪队列,等待CPU调度 } } } // IO设备处理函数 - 模拟IO设备的执行 void processIO() { // 第一部分:处理当前正在使用IO设备的进程 if (ioBusy && ioProcess) { Segment& currentSegment = ioProcess->segments[ioProcess->currentSegment]; // 执行一个时间单位的IO操作 currentSegment.remaining--; // IO片段剩余时间减1 ioProcess->IOTime++; // 进程总IO时间加1 stats.totalIOTime++; // 系统总IO时间加1 // 检查IO片段是否完成 if (currentSegment.remaining == 0) { ioProcess->currentSegment++; // 移动到下一个片段 // 情况1:所有片段都完成,进程结束 if (ioProcess->currentSegment >= ioProcess->segments.size()) { ioProcess->state = FINISHED; ioProcess->finishTime = currentTime; finishedProcesses.push_back(ioProcess->id); } // 情况2:还有下一个片段,IO完成后需要CPU处理,进入就绪队列 else { // IO完成后,下一个片段通常是CPU片段,进入就绪队列等待CPU调度 ioProcess->state = READY; readyQueue.push(findProcessIndex(ioProcess->id)); } // IO设备释放 ioBusy = false; ioProcess = nullptr; } } // 第二部分:如果IO设备空闲,从IO队列中取出下一个等待IO的进程 // IO设备也采用FIFO队列,先到先服务 if (!ioBusy && !ioQueue.empty()) { int nextIOIndex = ioQueue.front(); // 取队列头部进程 ioQueue.pop(); Process& nextProcess = processes[nextIOIndex]; nextProcess.state = BLOCKED; // 设置为阻塞状态(正在使用IO) ioProcess = &nextProcess; ioBusy = true; // IO设备被占用 } } // CPU调度核心函数 - 实现轮转调度算法 void scheduleCPU() { // 第一部分:处理当前正在运行的进程 if (cpuBusy && currentProcess) { Segment& currentSegment = currentProcess->segments[currentProcess->currentSegment]; // 执行一个时间单位的CPU操作 currentSegment.remaining--; // 当前片段剩余时间减1 currentProcess->CPUTime++; // 进程总CPU时间加1 currentProcess->remainingTimeSlice--; // 当前时间片剩余时间减1 stats.totalCPUTime++; // 系统总CPU时间加1 // 情况1:当前CPU片段执行完成 if (currentSegment.remaining == 0) { currentProcess->currentSegment++; // 移动到下一个片段 // 情况1.1:所有片段都完成,进程结束 if (currentProcess->currentSegment >= currentProcess->segments.size()) { currentProcess->state = FINISHED; currentProcess->finishTime = currentTime; // 记录完成时间 finishedProcesses.push_back(currentProcess->id); cpuBusy = false; currentProcess = nullptr; } // 情况1.2:还有下一个片段,根据片段类型决定去向 else { Segment& nextSegment = currentProcess->segments[currentProcess->currentSegment]; if (nextSegment.type == IO_SEGMENT) { // 下一个是IO片段,进入IO阻塞队列 currentProcess->state = BLOCKED; ioQueue.push(findProcessIndex(currentProcess->id)); } else { // 下一个是CPU片段,进入就绪队列等待再次调度 currentProcess->state = READY; readyQueue.push(findProcessIndex(currentProcess->id)); } cpuBusy = false; currentProcess = nullptr; } } // 情况2:时间片用完但片段未完成(轮转调度的关键) else if (currentProcess->remainingTimeSlice == 0) { // 强制让出CPU,重新进入就绪队列末尾,等待下次调度 currentProcess->state = READY; readyQueue.push(findProcessIndex(currentProcess->id)); cpuBusy = false; currentProcess = nullptr; } } // 第二部分:如果CPU空闲,从就绪队列中取出下一个进程执行 // 这是轮转调度的核心:FIFO队列,公平分配CPU时间 if (!cpuBusy && !readyQueue.empty()) { int nextIndex = readyQueue.front(); // 取队列头部进程(FIFO) readyQueue.pop(); Process& nextProcess = processes[nextIndex]; nextProcess.state = RUNNING; // 设置为运行状态 nextProcess.remainingTimeSlice = timeSlice; // 分配完整时间片 nextProcess.timeSliceUsed++; // 记录使用的时间片数量 currentProcess = &nextProcess; cpuBusy = true; } } // 更新等待时间统计 - 每个时钟周期调用一次 // 统计进程在就绪队列和IO队列中的等待时间,用于性能分析 void updateWaitTimes() { // 更新就绪队列中所有进程的CPU等待时间 // 这些进程正在等待CPU资源,每过一个时间单位等待时间加1 queue<int> tempQueue = readyQueue; while (!tempQueue.empty()) { int procIndex = tempQueue.front(); tempQueue.pop(); processes[procIndex].readyWaitTime++; // CPU等待时间递增 } // 更新IO队列中所有进程的IO等待时间 // 这些进程正在等待IO设备资源,每过一个时间单位等待时间加1 queue<int> tempIOQueue = ioQueue; while (!tempIOQueue.empty()) { int procIndex = tempIOQueue.front(); tempIOQueue.pop(); processes[procIndex].IOWaitTime++; // IO等待时间递增 } } // 根据进程ID查找进程在数组中的索引 // 由于队列中存储的是索引而不是进程对象,需要此函数进行转换 int findProcessIndex(int id) { for (int i = 0; i < processes.size(); i++) { if (processes[i].id == id) { return i; } } return -1; // 未找到返回-1(理论上不应该发生) } // 计算统计信息 - 在所有进程完成后调用 // 计算每个进程和系统的平均性能指标 void calculateStatistics() { double totalReadyWait = 0; double totalIOWait = 0; double totalCPUTime = 0; double totalIOTime = 0; double totalTurnaround = 0; double totalWeightedTurnaround = 0; // 遍历所有进程,计算各项指标 for (Process& proc : processes) { // 周转时间 = 完成时间 - 到达时间(进程从到达到最后完成的总时间) proc.turnaroundTime = proc.finishTime - proc.arrivalTime; // 带权周转时间 = 周转时间 / 服务时间(CPU时间 + IO时间) // 反映进程等待时间相对于执行时间的比例,值越小说明调度效率越高 proc.weightedTurnaroundTime = static_cast<double>(proc.turnaroundTime) / (proc.CPUTime + proc.IOTime); // 累加各项指标用于计算平均值 totalReadyWait += proc.readyWaitTime; totalIOWait += proc.IOWaitTime; totalCPUTime += proc.CPUTime; totalIOTime += proc.IOTime; totalTurnaround += proc.turnaroundTime; totalWeightedTurnaround += proc.weightedTurnaroundTime; } // 计算系统平均指标 stats.avgReadyWaitTime = totalReadyWait / processes.size(); stats.avgIOWaitTime = totalIOWait / processes.size(); stats.avgCPUTime = totalCPUTime / processes.size(); stats.avgIOTime = totalIOTime / processes.size(); stats.avgTurnaroundTime = totalTurnaround / processes.size(); stats.avgWeightedTurnaroundTime = totalWeightedTurnaround / processes.size(); } public: void writeResultsToFile(const string& filename) { ofstream outFile(filename); if (!outFile) { cerr << "无法打开输出文件: " << filename << endl; return; } // 按结束时间排序进程 vector<Process> sortedProcesses = processes; sort(sortedProcesses.begin(), sortedProcesses.end(), [](const Process& a, const Process& b) { return a.finishTime < b.finishTime; }); // 写入第一行(对齐格式) outFile << "Processes: " << setw(3) << right << stats.totalProcesses << " TimeSlice: " << setw(3) << right << stats.timeSlice << endl; // 写入每个进程的信息(对齐格式) for (const Process& proc : sortedProcesses) { // 计算CPU和IO片段数量 int cpuPieces = 0; int ioPieces = 0; for (const Segment& seg : proc.segments) { if (seg.type == CPU_SEGMENT) { cpuPieces++; } else { ioPieces++; } } outFile << "ID " << setw(2) << right << proc.id << ": "; outFile << "Priority: " << setw(4) << right << proc.priority << ", "; outFile << "Arrival: " << setw(4) << right << proc.arrivalTime << ", "; outFile << "Finish: " << setw(5) << right << proc.finishTime << ", "; outFile << "CPU pieces: " << setw(2) << right << cpuPieces << ", "; outFile << "IO pieces: " << setw(2) << right << ioPieces << ", "; outFile << "CPU wait: " << setw(4) << right << proc.readyWaitTime << ", "; outFile << "CPU: " << setw(3) << right << proc.CPUTime << ", "; outFile << "IO wait: " << setw(5) << right << proc.IOWaitTime << ", "; outFile << "IO: " << setw(4) << right << proc.IOTime << ", "; outFile << "Turnover: " << setw(5) << right << proc.turnaroundTime << ", "; outFile << "Weighted turnover: " << fixed << setprecision(3) << setw(7) << right << proc.weightedTurnaroundTime << endl; } // 写入统计信息(对齐格式) outFile << "Average CPU wait: " << fixed << setprecision(3) << setw(8) << right << stats.avgReadyWaitTime << ", "; outFile << "Average CPU: " << fixed << setprecision(3) << setw(8) << right << stats.avgCPUTime << ", "; outFile << "Average IO wait: " << fixed << setprecision(3) << setw(8) << right << stats.avgIOWaitTime << ", "; outFile << "Average IO: " << fixed << setprecision(3) << setw(8) << right << stats.avgIOTime << ", "; outFile << "Average turnover: " << fixed << setprecision(3) << setw(8) << right << stats.avgTurnaroundTime << ", "; outFile << "Average weighted turnover: " << fixed << setprecision(3) << setw(8) << right << stats.avgWeightedTurnaroundTime << endl; outFile.close(); } void printStatistics() { cout << "\n=== 调度统计结果 ===" << endl; cout << "进程数量: " << stats.totalProcesses << endl; cout << "时间片大小: " << stats.timeSlice << endl; cout << "平均就绪等待时间: " << fixed << setprecision(2) << stats.avgReadyWaitTime << endl; cout << "平均IO等待时间: " << stats.avgIOWaitTime << endl; cout << "平均占用CPU时间: " << stats.avgCPUTime << endl; cout << "平均占用IO设备时间: " << stats.avgIOTime << endl; cout << "平均周转时间: " << stats.avgTurnaroundTime << endl; cout << "平均带权周转时间: " << stats.avgWeightedTurnaroundTime << endl; } }; // 读取进程文件 - 从文件中读取进程信息并构建进程列表 // 文件格式:第一行为进程数量n,接下来n行,每行包含:进程ID、优先级、到达时间、片段数量、片段长度列表 vector<Process> readProcessFile(const string& filename) { ifstream inFile(filename); vector<Process> processes; if (!inFile) { cerr << "无法打开输入文件: " << filename << endl; return processes; } int n; // 进程数量 inFile >> n; // 读取每个进程的信息 for (int i = 0; i < n; i++) { int id, priority, arrivalTime, m; // m为片段数量 inFile >> id >> priority >> arrivalTime >> m; vector<Segment> segments; // 读取进程的片段序列:偶数索引为CPU片段,奇数索引为IO片段 // 这种交替模式模拟了典型的进程执行模式:CPU计算 -> IO操作 -> CPU计算 -> ... for (int j = 0; j < m; j++) { int segmentLength; inFile >> segmentLength; SegmentType type = (j % 2 == 0) ? CPU_SEGMENT : IO_SEGMENT; segments.push_back(Segment(type, segmentLength)); } // 创建进程对象并加入列表 processes.push_back(Process(id, priority, arrivalTime, segments)); } inFile.close(); return processes; } int main() { // 读取进程数据 vector<Process> processes = readProcessFile("TASK"); if (processes.empty()) { cerr << "没有读取到进程数据,程序退出" << endl; return 1; } int choice; bool running = true; while (running) { cout << "\n========== 进程调度系统 ==========" << endl; cout << "1. 输入时间片并运行调度" << endl; cout << "2. 退出程序" << endl; cout << "请选择操作(输入 1 或 2): "; cin >> choice; if (choice == 1) { // 用户输入时间片大小 int timeSlice; cout << "\n请输入时间片大小(范围:5-20): "; cin >> timeSlice; // 验证时间片大小是否在有效范围内 while (timeSlice < 5 || timeSlice > 20) { cout << "输入无效!时间片大小必须在 5-20 之间,请重新输入: "; cin >> timeSlice; } cout << "\n=== 使用时间片大小: " << timeSlice << " 进行调度 ===" << endl; // 重新读取进程数据以重置状态 vector<Process> freshProcesses = readProcessFile("TASK"); if (freshProcesses.empty()) { cerr << "无法重新读取进程数据" << endl; continue; } // 创建调度器并执行调度 // 使用新的进程数据和时间片大小初始化调度器 Scheduler scheduler(freshProcesses, timeSlice); // 执行轮转调度算法,直到所有进程完成 scheduler.roundRobinScheduling(); // 输出结果到文件 scheduler.writeResultsToFile("ROUND"); // 打印统计信息 scheduler.printStatistics(); cout << "\n调度完成!结果已保存到 ROUND文件。" << endl; } else if (choice == 2) { cout << "\n感谢使用,程序退出!" << endl; running = false; } else { cout << "\n输入无效!请输入 1 或 2。" << endl; } } return 0; }请根据此代码,帮我生成多组测试数据,使其具有代表性
最新发布
11-30
#include “timeslice.h” #include “uart_test.h” #include <string.h> /* 时间片周期配置数组 (ms) */ static const uint32_t timeslice_periods[TIMESLICE_COUNT] = { 1, // 10, // 50, // 100, // 500, // 1000 // }; /* 全局变量定义 */ uint32_t g_system_tick = 0; // 系统总tick计数 bool g_timeslice_flags[TIMESLICE_COUNT] = {false}; // 时间片标志数组 uint32_t g_timeslice_counters[TIMESLICE_COUNT] = {0}; // 时间片计数器数组 /** @brief 时间片系统初始化 */ void TimeSlice_Init(void) { uint8_t i; // 初始化系统tick g_system_tick = 0; // 初始化时间片标志和计数器 for (i = 0; i < TIMESLICE_COUNT; i++) { g_timeslice_flags[i] = false; g_timeslice_counters[i] = 0; } } /** @brief 时间片tick更新 @note 在TIM1中断中调用,每1ms调用一次 */ void TimeSlice_TickUpdate(void) { uint8_t i; // 系统tick自增 g_system_tick++; // 遍历所有时间片,检查是否到达周期时间 for (i = 0; i < TIMESLICE_COUNT; i++) { g_timeslice_counters[i]++; // 检查是否到达设定的周期 if (g_timeslice_counters[i] >= timeslice_periods[i]) { g_timeslice_flags[i] = true; // 设置时间片标志 g_timeslice_counters[i] = 0; // 重置计数器 } } } /** @brief 检查时间片标志是否置位 @param id 时间片ID @return true 标志已置位,false 标志未置位 */ bool TimeSlice_IsSet(TimeSlice_ID_t id) { if (id >= TIMESLICE_COUNT) return false; return g_timeslice_flags[id]; } /** @brief 清除时间片标志 @param id 时间片ID */ void TimeSlice_ClearFlag(TimeSlice_ID_t id) { if (id >= TIMESLICE_COUNT) return; g_timeslice_flags[id] = false; } /** @brief 获取系统运行时间 @return 系统运行时间(ms) */ uint32_t TimeSlice_GetSystemTick(void) { return g_system_tick; } /** @brief 主循环任务调度 @note 在主循环中调用此函数进行任务调度 */ void TimeSlice_TaskScheduler(void) { for(int i = 0;i<TIMESLICE_COUNT;i++) { if(TimeSlice_IsSet(i)) { TimeSlice_ClearFlag(i); switch(i) { case TIMESLICE_1MS: // 1ms高频任务 break; case TIMESLICE_10MS: // 10ms任务 - 串口处理 UART_Process(); break; case TIMESLICE_50MS: // 50ms任务 break; case TIMESLICE_100MS: // 100ms任务 break; case TIMESLICE_500MS: // 500ms任务 break; case TIMESLICE_1000MS: // 1000ms任务 - 串口测试数据发送 // UART_SendTestData(); break; } } }使用这个时间片当收到0x00,60秒后发送0x01
07-10
要实现 **“当收到 `0x00` 命令后,60秒再发送 `0x01`”** 的功能,可以结合你已有的时间片调度机制和串口接收处理函数来完成。 --- ### ✅ 实现思路 1. **在串口接收处理中识别 `0x00` 命令。** 2. **一旦检测到该命令,记录当前系统 tick,并设置一个标志位。** 3. **在主循环或 1ms 时间片任务中轮询判断是否达到 60 秒(即 60000 ms)。** 4. **如果满足条件,则发送 `0x01` 并清除标志。** --- ### ✅ 示例代码修改 #### 1. 在头文件或 `.c` 文件顶部添加全局变量 ```c // 新增变量用于控制60秒延时发送 bool g_send_0x01_flag = false; uint32_t g_send_0x01_tick = 0; ``` #### 2. 修改串口接收函数(假设为 `UART_Process()`) ```c void UART_Process(void) { uint8_t rx_data; while (UART_GetReceivedData(&rx_data)) // 假设该函数能获取接收到的数据 { if (rx_data == 0x00) { // 设置发送标志并记录当前tick g_send_0x01_flag = true; g_send_0x01_tick = TimeSlice_GetSystemTick(); } } } ``` #### 3. 在 `TimeSlice_TaskScheduler()` 或 1ms 时间片任务中检查是否超时 ```c void TimeSlice_TaskScheduler(void) { for(int i = 0; i < TIMESLICE_COUNT; i++) { if(TimeSlice_IsSet(i)) { TimeSlice_ClearFlag(i); switch(i) { case TIMESLICE_1MS: // 检查是否需要发送0x01 if (g_send_0x01_flag) { uint32_t current_tick = TimeSlice_GetSystemTick(); if ((current_tick - g_send_0x01_tick) >= 60000) { UART_SendControlCommand(0x01); // 发送0x01 g_send_0x01_flag = false; // 清除标志 } } break; case TIMESLICE_10MS: UART_Process(); break; // 其他case保持不变... } } } } ``` #### 4. 添加 `UART_SendControlCommand()` 函数(如未定义) ```c void UART_SendControlCommand(uint8_t cmd) { uint8_t payload = 0x01; uint8_t payload_len = 1; uint8_t frame[10]; // 足够大的缓冲区 uint16_t index = 0; frame[index++] = 0x5A; // 帧头 frame[index++] = cmd; // CMD frame[index++] = payload_len; // Payload长度 frame[index++] = payload; // Payload // 校验和 uint8_t checksum = cmd + payload_len + payload; frame[index++] = checksum & 0xFF; frame[index++] = 0xA5; // 帧尾 UART_SendData(frame, index); } ``` --- ### ✅ 总结 通过在串口接收处理中检测 `0x00` 命令,并记录系统 tick,在后续的时间片中进行判断是否到达 60 秒,即可实现延迟发送 `0x01` 的功能。 这种方式结构清晰、不依赖额外定时器资源,适用于大多数嵌入式项目。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值