楼主: 韩文2018
19 0

51单片机第四讲之倒计时程序设计 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-9-26
最后登录
2018-9-26

楼主
韩文2018 发表于 2025-12-5 20:23:22 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

单片机综合项目:倒计时控制系统的设计与实现

一、系统功能与设计说明

1. 主要功能模块概述

本项目构建了一个基于单片机的倒计时控制装置,具备完整的计时、显示、交互与报警能力。系统通过多个硬件模块协同工作,实现用户友好的操作体验。
功能模块 实现方式 说明
计时功能 定时器中断 确保时间精度,提供稳定计时基础
显示功能 数码管动态扫描 用于展示模式标识及当前倒计时数值
界面切换 按键控制 支持在显示模式与设置模式间切换
状态指示 LED指示灯 倒计时结束时亮起以作提示
报警功能 蜂鸣器 倒计时归零后发出声音警报

2. 系统性能指标要求

  • 按键响应时间:不超过0.2秒,保证操作灵敏性
  • 数码管刷新时间:不高于0.2秒,避免视觉闪烁现象

3. 显示界面布局设计

(1)倒计时运行界面

该界面用于实时显示剩余时间,具体分配如下:
数码管位置 1 2 3 4 5 6
显示内容 1 熄灭 熄灭 熄灭 倒计时十位 倒计时个位

示例:当前显示为“1 _ _ _ 3 5”表示处于倒计时模式,时间为35秒。

数码管显示示例
  +---+   +---+   +---+   +---+   +---+   +---+
  | 1 |   |   |   |   |   |   |   | 3 |   | 0 |
  +---+   +---+   +---+   +---+   +---+   +---+

(2)参数设置界面

进入设置模式后,允许用户调整倒计时初始值,显示格式如下:
数码管位置 1 2 3 4 5 6
显示内容 2 熄灭 熄灭 熄灭 设置值十位(闪烁) 设置值个位(闪烁)
闪烁说明 不闪烁 不闪烁 不闪烁 不闪烁 1秒周期闪烁 1秒周期闪烁

示例:显示“2 _ _ _ 3 0”且最后两位每秒闪烁,表示正在设定30秒倒计时。

设置界面显示示例(闪烁效果)
  +---+   +---+   +---+   +---+   +-------+   +-------+
  | 2 |   |   |   |   |   |   |   | 3(闪) |   | 0(闪) |
  +---+   +---+   +---+   +---+   +-------+   +-------+

4. 按键功能定义与使用规范

系统采用四个独立按键完成全部人机交互任务,各按键功能如下表所示:
按键 功能名称 功能说明 有效界面
S1 开始按键 启动或暂停倒计时进程 仅限显示界面
S2 复位按键 将系统恢复至初始状态 仅限显示界面
S3 切换按键 在显示与设置界面之间切换 所有界面均有效
S4 设置按键 循环选择预设时间:15→30→60秒 仅限设置界面

注意事项:

  • 必须加入软件消抖机制,防止因机械抖动导致误判
  • 按键操作过程中不得影响数码管正常刷新
  • 不同界面下按键的有效性需严格控制

5. 系统运行状态反馈机制

根据当前所处状态,系统通过多种外设进行反馈:
系统状态 LED指示灯 蜂鸣器 数码管显示
倒计时进行中 全部熄灭 关闭 正常显示当前剩余时间
倒计时结束 全部点亮 开启报警音 显示“00”
设置模式 全部熄灭 关闭 设置数值以1秒周期闪烁

6. 可选倒计时参数配置

系统提供三种常用预设时间选项,对应不同的应用场景:
设置值 二进制表示 适用场景
15秒 00001111 适用于短时提醒任务
30秒 00011110 适合一般性倒计时需求
60秒 00111100 用于较长时间控制场合

7. 上电初始化状态设定

设备上电后,系统自动进入以下默认配置状态:
项目 初始值 说明
当前界面 显示界面 非设置模式,直接进入运行状态
倒计时参数 30秒 作为默认预设时间
模式标识符 1 表示当前为显示模式
LED状态 全灭 尚未到达倒计时终点
蜂鸣器状态 关闭 无报警触发

二、程序模块化结构设计

1. 底层驱动模块实现

为提升代码可读性和维护效率,将核心外设操作封装为独立功能模块。
(1)按键检测模块

头文件定义(Key.h):

#ifndef _KEY_H_
#define _KEY_H_
#include <REGX52.H>

// 函数声明
unsigned char Key_Read(void);

#endif

源文件实现(Key.c):

#include "Key.h"

/**
* 独立按键扫描函数
* @return 返回按键编号:0-无按键,1-按键1,2-按键2,3-按键3,4-按键4
*/
unsigned char Key_Read(void) {
    unsigned char temp = 0;
    if (P3_4 == 0) temp = 1;  // 检测S1
    if (P3_5 == 0) temp = 2;  // 检测S2
    if (P3_6 == 0) temp = 3;  // 检测S3
    if (P3_7 == 0) temp = 4;  // 检测S4
    return temp;
}
(2)数码管显示模块

头文件声明(Seg.h):

#ifndef _SEG_H_
#define _SEG_H_
#include <REGX52.H>

// 函数声明
void Seg_Disp(unsigned char Wela, unsigned char Dula);

#endif

源文件实现(Seg.c):

#include "Seg.h"

// 共阴极数码管段码表:0~9 和熄灭状态
unsigned char Seg_Dula[11] = {
    0x3F,  // 0
    0x06,  // 1
    0x5B,  // 2
    0x4F,  // 3
    0x66,  // 4
    0x6D,  // 5
    0x7D,  // 6
    0x07,  // 7
    0x7F,  // 8
    0x6F,  // 9
    0x00   // 熄灭
};

// 位选信号编码表:对应六个数码管
unsigned char Seg_Wela[6] = {
    0xFE,  // 第1位
    0xFD,  // 第2位
    0xFB,  // 第3位
    0xF7,  // 第4位
    0xEF,  // 第5位
    0xDF   // 第6位
};

/**
* 数码管显示控制函数
* @param Wela 位选参数(0-5,指定第几个数码管)
* @param Dula 段选参数(0-9,要显示的数字)
*/
void Seg_Disp(unsigned char Wela, unsigned char Dula) {
    // 消影处理,防止重影
    P0 = 0x00;
    P2_6 = 1;
    P2_6 = 0;

    // 位选:选定目标数码管
    P0 = Seg_Wela[Wela];
    P2_7 = 1;
    P2_7 = 0;

    // 段选:输出数字数据
// 头文件包含
#include <REGX52.H>
#include "Seg.h"
#include "Key.h"

// 全局变量定义
unsigned char Key_Slow_Down = 0;   // 按键扫描间隔控制(每10ms触发一次)
unsigned char Seg_Slow_Down = 0;   // 数码管更新频率控制(每500ms执行一次)

/**
 * 主函数
 */
void main(void) {
    Timer0_Init();          // 启动定时器0初始化
    while (1) {
        Key_Proc();         // 轮询按键处理
        Seg_Proc();         // 执行数码管显示逻辑
        LED_Buzzer_Proc();  // 控制LED与蜂鸣器状态
    }
}

/**
 * 定时器0初始化函数
 * 配置为16位定时模式,实现1ms中断周期(基于12MHz晶振)
 */
void Timer0_Init(void) {
    TMOD &= 0xF0;            // 清零定时器0的工作模式位
    TMOD |= 0x01;            // 设置为16位定时器模式(模式1)
    TL0 = 0x20;              // 加载低8位初始值
    TH0 = 0xD1;              // 加载高8位初始值
    TF0 = 0;                 // 清除溢出标志位
    TR0 = 1;                 // 启动定时器0
    ET0 = 1;                 // 开启定时器0中断
    EA = 1;                  // 全局中断使能
}

/**
 * 定时器0中断服务程序
 * 每1ms进入一次,用于驱动软件定时机制
 */
void Timer0_Server() interrupt 1 {
    TL0 = 0x20;                          // 重装定时器低字节
    TH0 = 0xD1;                          // 重装定时器高字节
    if (++Key_Slow_Down == 10) Key_Slow_Down = 0;    // 达到10次即10ms,归零复位
    if (++Seg_Slow_Down == 500) Seg_Slow_Down = 0;  // 达到500次即500ms,清零重启
}

/**
 * 按键处理函数
 * 每10ms调用一次,检测当前按键输入并作出响应
 */
void Key_Proc(void) {
    if (Key_Slow_Down) return;       // 尚未到达10ms周期则跳过
    Key_Slow_Down = 1;
    // TODO: 插入具体的按键检测和事件响应代码
}

/**
 * 数码管显示处理函数
 * 每500ms执行一次,刷新显示内容以降低CPU负载
 */
void Seg_Proc(void) {
    if (Seg_Slow_Down) return;       // 若未满500ms则不执行
    Seg_Slow_Down = 1;

    // 显示模式标识:第一位数码管显示模式编号(1或2)
    Seg_Buf[0] = Seg_Mode + 1;  // 模式0显示为1,模式1显示为2
}

/**
 * LED与蜂鸣器控制函数
 * 根据系统运行状态调节外设输出
 */
void LED_Buzzer_Proc(void) {
    // TODO: 添加对LED指示灯及蜂鸣器的逻辑控制代码
}

//============================== 核心功能模块:数码管显示设计 ==============================

/*
 * 显示相关数据结构说明:
 *
 * 变量名           类型        初始值     功能描述
 * 
Seg_Mode
unsigned char
- 模式标志:0表示显示模式,1表示设置模式 *
Time_Count
unsigned char
30 当前倒计时数值(运行中显示) *
Seg_Time[3]
unsigned char
{15,30,60} 可选倒计时时间数组 *
Seg_Time_Index
unsigned char
1 当前选中的预设时间索引 *
Seg_Flag
bit
0/1 闪烁控制标志:0亮,1灭 *
Seg_Buf[6]
unsigned char
{10,10,10,10,10,10} 显示缓冲区(六位数码管) */
//================================ 软件减速机制详解 ==================================== /* * 设计目标:通过软件方式降低高频任务执行频率,提升系统效率 * * 减速项 周期 作用说明 性能指标要求 *
Key_Slow_Down
10ms 减少按键扫描次数,避免误触重复响应 响应延迟 ≤ 0.2秒 *
Seg_Slow_Down
500ms 降低数码管刷新频率,节省处理器资源 刷新间隔 ≤ 0.2秒 * * 实现原理: * - 使用定时器每1ms触发中断 * - 在中断中递增对应的减速计数器 * - 主循环中检查计数器是否归零,决定是否执行对应功能 * - 达到设定周期后自动清零,形成周期性调度 */
// 示例代码段(原始操作顺序) P0 = Seg_Dula[Dula]; P2_6 = 1; P2_6 = 0;
// 倒计时数值显示(第5、6个数码管)
if (Seg_Mode == 0) {
    // 显示模式:直接显示当前倒计时值
    Seg_Buf[4] = Time_Count / 10 % 10;  // 十位数
    Seg_Buf[5] = Time_Count / 1 % 10;   // 个位数
} else {
    // 设置模式:根据闪烁标志决定是否显示设置值
    if (Seg_Flag == 0) {
        // 亮状态:正常显示设定的时间值
        Seg_Buf[4] = Seg_Time[Seg_Time_Index] / 10 % 10;
        Seg_Buf[5] = Seg_Time[Seg_Time_Index] / 1 % 10;
    } else {
        // 灭状态:关闭显示,用于实现闪烁效果
        Seg_Buf[4] = 10;  // 熄灭
        Seg_Buf[5] = 10;  // 熄灭
    }
}

2. 定时器中断功能完善

(1)中断服务函数扩展

以下为定时器0中断服务函数的完整实现,包含多个关键变量的周期性更新与控制逻辑。

变量名 类型 初始值 功能说明
数码管扫描位置索引
Seg_Pos
Time_1000ms
用于动态扫描控制,每1ms切换一个数码管
1000ms计数器(用于倒计时)
unsigned char
unsigned int
累计至1000次触发一次秒级递减
500ms计数器(用于闪烁)
Time_500ms
unsigned int
实现参数设置时的500ms周期闪烁
/**
 * 定时器0中断服务函数
 */
void Timer0_Server() interrupt 1 {
    // 重装定时器初值,维持1ms中断周期
    TL0 = 0x20;
    TH0 = 0xD1;

    // 更新各类软件计数器
    if (++Key_Slow_Down == 10) Key_Slow_Down = 0;   // 按键处理周期:10ms
    if (++Seg_Slow_Down == 500) Seg_Slow_Down = 0;  // 数码管刷新基准:500ms

    // 动态扫描数码管:每次中断驱动一位,循环扫描
    if (++Seg_Pos == 6) Seg_Pos = 0;
    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos]);

    // 处理倒计时逻辑:每1000ms减少1秒
    if (++Time_1000ms == 1000) {
        Time_1000ms = 0;
        if (System_Flag == 1) {  // 仅在运行状态下倒计时
            Time_Count--;
            if (Time_Count == 255) {  // 防止无符号下溢
                Time_Count = 0;
            }
        }
    }

    // 控制设置界面中参数的闪烁效果(500ms切换一次)
    if (++Time_500ms == 500) {
        Time_500ms = 0;
        Seg_Flag = !Seg_Flag;  // 反转闪烁标志位
    }
}

数据类型选择说明

为确保各变量能正确承载所需最大值,合理选择数据类型至关重要:

变量 需要最大值 0-255范围 0-65535范围 选择
1000
unsigned char
unsigned int
Time_1000ms
使用可容纳更大值的类型以支持1000
500
unsigned int
Time_500ms
unsigned int
同样需选用支持至少500的类型

3. 按键功能实现

(1)按键处理函数完善

按键模块通过边沿检测机制实现精确响应。相关变量定义如下:

变量名 类型 初始值 功能说明
当前按键值
Key_Val
unsigned char
存储当前读取到的按键状态
下降沿检测(按键按下)
Key_Down
unsigned char
识别按键从释放到按下的跳变
上升沿检测(按键释放)
Key_Up
unsigned char
检测按键从按下到释放的过程
上次按键值(用于边沿检测)
Key_Old
unsigned char
保存前一时刻的状态以便比较
系统运行标志:0-停止,1-运行
System_Flag
bit
控制系统处于暂停或运行状态
/**
 * 按键处理函数
 */
void Key_Proc(void) {
    // 实现10ms节拍控制,避免频繁执行
    if (Key_Slow_Down != 0) return;
    Key_Slow_Down = 1;

    // 读取当前按键状态并进行边沿检测
    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Val ^ Key_Old);  // 下降沿:按键被按下
    Key_Up   = ~Key_Val & (Key_Val ^ Key_Old);  // 上升沿:按键被释放
    Key_Old = Key_Val;  // 更新历史状态

    // 根据按键动作执行对应操作
    switch (Key_Down) {
        case 1:  // S1按键:开始/暂停倒计时(仅在显示模式下有效)
            if (Seg_Mode == 0) {
                System_Flag = !System_Flag;  // 切换运行状态
            }
            break;

        case 2:  // S2按键:复位倒计时时间(恢复为预设值)
            if (Seg_Mode == 0) {
                Time_Count = Seg_Time[Seg_Time_Index];  // 重载设置值
            }
            break;

        case 3:  // S3按键:切换显示与设置模式
            Seg_Mode = !Seg_Mode;  // 切换界面模式
            break;

        case 4:  // S4按键:在设置模式下切换不同参数项
            if (Seg_Mode == 1) {
                Seg_Time_Index++;
                if (Seg_Time_Index == 3) {
                    Seg_Time_Index = 0;  // 循环切换三个参数
                }
            }
            break;
    }
}
// 头文件包含
#include <REGX52.H>
#include "Seg.h"
#include "Key.h"

// 全局变量定义
unsigned char Seg_Buf[6] = {10, 10, 10, 10, 10, 10};  // 数码管显示缓存
unsigned char Seg_Pos = 0;        // 数码管扫描位置
unsigned char Seg_Mode = 0;       // 当前模式:0-显示模式,1-设置模式
unsigned char Key_Val, Key_Old, Key_Up, Key_Down;  // 按键相关变量
unsigned char Seg_Slow_Down = 0;  // 数码管刷新限速标志
unsigned char Key_Slow_Down = 0;  // 按键处理限速标志
unsigned int Time_1000ms = 0;     // 1秒计时标志
unsigned int Time_500ms = 0;      // 500毫秒闪烁计时
unsigned char Time_Count = 30;    // 倒计时当前值
unsigned char Seg_Time[3] = {15, 30, 60};         // 可选定时时间数组
unsigned char Seg_Time_Index = 1;                 // 时间选项索引
bit Seg_Flag = 0;       // 闪烁标志位(0:不闪,1:闪)
bit System_Flag = 0;    // 系统运行状态标志

/**
 * 定时器0初始化函数(1ms定时 @12MHz)
 */
void Timer0_Init(void) {
    TMOD &= 0xF0;      // 清除定时器0模式位
    TL0 = 0x20;          // 设置初始低字节
    TH0 = 0xD1;          // 设置初始高字节
    TF0 = 0;             // 清除溢出标志
    TR0 = 1;             // 启动定时器0
    ET0 = 1;             // 开启定时器0中断
    EA  = 1;             // 开启全局中断
}

/**
 * 数码管显示处理函数
 * 负责更新显示内容并实现闪烁效果
 */
void Seg_Proc() {
    if (Seg_Slow_Down) return;
    Seg_Slow_Down = 1;

    // 显示当前模式编号(1或2)
    Seg_Buf[0] = Seg_Mode + 1;

    if (Seg_Mode == 0) {
        // 显示模式:显示当前倒计时数值
        Seg_Buf[4] = Time_Count / 10 % 10;
        Seg_Buf[5] = Time_Count / 1 % 10;
    } else {
        // 设置模式:根据闪烁标志决定是否显示时间
        if (Seg_Flag == 0) {
            Seg_Buf[4] = Seg_Time[Seg_Time_Index] / 10 % 10;
            Seg_Buf[5] = Seg_Time[Seg_Time_Index] / 1 % 10;
        } else {
            Seg_Buf[4] = 10;  // 不显示(空白)
            Seg_Buf[5] = 10;  // 不显示(空白)
        }
    }
}

/**
 * 按键处理函数
 * 实现模式切换、启动/暂停、复位和时间设置功能
 */
void Key_Proc() {
    if (Key_Slow_Down) return;
    Key_Slow_Down = 1;

    // 按键状态读取与边沿检测
    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Val ^ Key_Old);
    Key_Up   = ~Key_Val & (Key_Val ^ Key_Old);
    Key_Old = Key_Val;

    switch (Key_Down) {
        case 1:
            // S1按键:在显示模式下开始/暂停倒计时
            if (Seg_Mode == 0) {
                System_Flag = !System_Flag;
            }
            break;

        case 2:
            // S2按键:在显示模式下复位倒计时
            if (Seg_Mode == 0) {
                Time_Count = Seg_Time[Seg_Time_Index];
            }
            break;

        case 3:
            // S3按键:任意模式下切换显示/设置界面
            Seg_Mode = !Seg_Mode;
            break;

        case 4:
            // S4按键:设置模式下循环切换定时时间(15→30→60→15...)
            if (Seg_Mode == 1) {
                if (++Seg_Time_Index == 3) {
                    Seg_Time_Index = 0;
                }
                
Seg_Time_Index
} break; } } /** * LED与蜂鸣器控制函数 * 根据倒计时状态控制外设动作 */ void LED_Buzzer_Proc(void) { if (Time_Count == 0) { // 倒计时结束:点亮所有LED,触发蜂鸣器 P1 = 0x00; // 所有LED亮(低电平有效) P2_3 = 0; // 蜂鸣器开启(低电平有效)
System_Flag = !System_Flag
} else { // 倒计时进行中:关闭LED和蜂鸣器 P1 = 0xFF; // 所有LED灭(高电平熄灭) P2_3 = 1; // 蜂鸣器关闭(高电平无效) } }

(2)按键响应逻辑说明表

按键 当前模式 执行动作 结果状态
S1 显示模式 开始/暂停倒计时
System_Flag = !System_Flag
S2 显示模式 复位倒计时
Time_Count = Seg_Time[Seg_Time_Index]
S3 任意模式 切换显示/设置界面
Seg_Mode = !Seg_Mode
S4 设置模式 循环切换参数(15-30-60)
// 主循环中将调用上述各模块函数完成系统控制
// 包括定时器中断服务、数码管动态扫描、按键扫描及外设控制等流程

// 定时器0中断服务函数

void Timer0_Server() interrupt 1 {

    // 重新加载定时初值

    TL0 = 0x20;

    TH0 = 0xD1;

    // 按键与数码管的减速计数

    if (++Key_Slow_Down == 10) Key_Slow_Down = 0;

    if (++Seg_Slow_Down == 500) Seg_Slow_Down = 0;

    // 数码管动态扫描:每轮依次显示一位

    if (++Seg_Pos == 6) Seg_Pos = 0;

    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos]);

    // 倒计时逻辑处理

    if (System_Flag == 1) {

        if (++Time_1000ms == 1000) {

            Time_1000ms = 0;

            Time_Count--;

            if (Time_Count == 255) {

                Time_Count = 0;

            }

        }

    }

    // 实现参数闪烁效果,周期为1秒

    if (++Time_500ms == 500) {

        Time_500ms = 0;

        Seg_Flag = !Seg_Flag;

    }

}

// LED与蜂鸣器控制进程

void LED_Buzzer_Proc(){

    if(Time_Count == 0){

        P1 = 0x00; // 所有LED点亮

        P2_3 = 0; // 蜂鸣器开启

    } else {

        P1 = 0xFF; // LED熄灭

        P2_3 = 1; // 蜂鸣器关闭

    }

}

// 主函数入口

void main(){

    Timer0_Init(); // 初始化定时器

    while(1){

        Key_Proc(); // 按键处理

        Seg_Proc(); // 显示处理

        LED_Buzzer_Proc(); // 外设控制

    }

}

五、系统测试与调试

1. 功能测试项目

测试项目 测试方法 预期结果 通过标准
初始状态 上电复位 显示界面,倒计时30秒 数码管显示"1 - - - 3 0"
开始/暂停 按下S1键 倒计时开始或暂停 计时值随时间递减或保持不变
复位功能 按下S2键 恢复至当前设置的倒计时时间 计时值重置为设定值
界面切换 按下S3键 在显示模式与设置模式之间切换 模式标识符在1和2之间变化
参数设置 在设置界面下按S4键 倒计时参数循环切换 设置值按15→30→60→15顺序循环
闪烁效果 进入设置界面后 可调参数以1秒周期闪烁 亮500ms,灭500ms
倒计时结束 计时归零时 触发报警信号 LED全亮(P1=0x00),蜂鸣器启动(P2_3=0)

2. 时序要求验证

功能 要求时间 实现方式 实测结果
按键响应 ≤0.2秒 每10ms扫描一次按键状态 0.01秒内响应
数码管刷新 ≤0.2秒 每个数码管间隔约1ms更新 一轮刷新耗时6ms(即0.006秒)
参数闪烁 1秒周期 通过500ms翻转一次闪烁标志位 准确实现亮500ms、灭500ms

六、项目总结

1. 技术要点回顾

技术要点 实现方法 关键代码
定时器中断 配置Timer0产生1ms定时中断
Timer0_Init()
数码管动态扫描 在中断中逐位轮流驱动六个数码管
Timer0_Server()
按键检测 采用边沿触发结合软件去抖机制
Key_Proc()
显示界面管理 使用模式变量控制当前显示内容
Seg_Proc()
外围设备控制 根据系统状态控制LED和蜂鸣器输出
LED_Buzzer_Proc()

2. 设计模式应用

设计模式 应用场景 实现方式
状态模式 用于切换显示与设置两种操作模式
Seg_Mode
观察者模式 响应按键事件的变化 通过中断实时检测按键动作
策略模式 支持多种倒计时参数选择
Seg_Time
使用数组存储不同预设值
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:程序设计 倒计时 单片机 include System

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-27 22:02