按键长按逻辑技术文档

按键长按逻辑技术文档

:clipboard: 文档信息

  • 项目名称: DS18B20温度传感器控制系统
  • 目标平台: STC15F2K60S2 单片机
  • 主频: 12.000MHz
  • 文档版本: v1.0
  • 最后更新: 2026-02-03

1. 概述

1.1 功能描述

长按功能允许用户通过持续按住按键来实现参数的连续调节,无需重复按压。本系统实现了 S14(增加)和 S15(减少)两个按键的长按检测和连续触发功能。

1.2 技术特点

  • :white_check_mark: 双层计时机制: 中断计时 + 主循环减速
  • :white_check_mark: 可配置触发参数: 延迟时间、触发频率可调
  • :white_check_mark: 防抖动设计: 松开立即清零,避免误触发
  • :white_check_mark: 资源占用低: 仅使用 2 个全局变量

1.3 系统参数

参数 数值 说明
定时器周期 1ms Timer0 中断频率
按键扫描周期 10ms Key_Proc 调用频率
数码管刷新周期 50ms Seg_Proc 调用频率
长按触发延迟 250ms 按住多久后开始连续触发

2. 实现原理

2.1 架构设计

┌─────────────────────────────────────────────────────────┐
│                    硬件层 (物理按键)                      │
│                         S14 / S15                        │
└─────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────┐
│                 中断层 (Timer0: 1ms)                     │
│  ┌───────────────────────────────────────────────────┐  │
│  │  • 按键状态监测: Key_Old                          │  │
│  │  • 计时器累加: Key_Long++  (每1ms)               │  │
│  │  • 松开清零: Key_Long = 0                        │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────┐
│                应用层 (Key_Proc: 10ms)                   │
│  ┌───────────────────────────────────────────────────┐  │
│  │  • 阈值检测: if(Key_Long >= 250)                 │  │
│  │  • 减速控制: Key_Long_Slow                       │  │
│  │  • 动作执行: P_DIS[0]++ / P_DIS[1]++            │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

2.2 双计时器机制

第一层:中断计时器 (Key_Long)

作用: 精确测量按键按下的持续时间

// 定时器中断 (1ms执行一次)
if((Key_Old == 14) || (Key_Old == 15))
{
    if(++Key_Long == 65535) Key_Long = 0;  // 累加,防溢出
}
else
{
    Key_Long = 0;  // 松开立即归零
}

特性:

  • 精度:1ms
  • 最大测量时间:65.535秒
  • 按键松开后立即清零

第二层:减速计数器 (Key_Long_Slow)

作用: 控制连续触发的频率

// 主循环 (10ms执行一次)
if(Key_Long >= 250)  // 已按下超过250ms
{
    if(++Key_Long_Slow >= 5)  // 减速计数器
    {
        Key_Long_Slow = 0;     // 达到阈值,清零重计
        P_DIS[0] ++;           // 执行动作
    }
}

特性:

  • 基准周期:10ms (Key_Proc调用周期)
  • 触发间隔:阈值 × 10ms
  • 示例:阈值=5 → 每50ms触发一次

2.3 时间轴分析

完整操作流程

时间 (ms)  中断 (1ms周期)        主循环 (10ms周期)           显示
═════════════════════════════════════════════════════════════════
0          按下S14               -                          P 30-20
           Key_Long = 0
1          Key_Long = 1          -                          P 30-20
2          Key_Long = 2          -                          P 30-20
...        ...                   ...                        ...
10         Key_Long = 10         检查: 10 < 250 (未触发)    P 30-20
20         Key_Long = 20         检查: 20 < 250 (未触发)    P 30-20
...        ...                   ...                        ...
250        Key_Long = 250        检查: 250 >= 250 ✅        P 30-20
                                 Key_Long_Slow = 1
260        Key_Long = 260        Key_Long_Slow = 2          P 30-20
270        Key_Long = 270        Key_Long_Slow = 3          P 30-20
280        Key_Long = 280        Key_Long_Slow = 4          P 30-20
290        Key_Long = 290        Key_Long_Slow = 5          P 30-20
300        Key_Long = 300        Key_Long_Slow = 0 ✅       P 31-20
                                 执行: P_DIS[0]++
310        Key_Long = 310        Key_Long_Slow = 1          P 31-20
...        ...                   ...                        ...
350        Key_Long = 350        Key_Long_Slow = 0 ✅       P 32-20
                                 执行: P_DIS[0]++
...        ...                   ...                        ...
500        松开按键              -                          P 35-20
501        Key_Long = 0          检查: 0 < 250 (停止)      P 35-20

总结:

  • 0~250ms: 等待期,判断是否为长按
  • 250ms后: 每50ms执行一次增加操作
  • 松开时: 立即停止

3. 代码详解

3.1 变量声明

/* 全局变量 */
unsigned int Key_Long;        // 长按计时器 (中断累加)
unsigned char Key_Old;        // 当前按键状态
unsigned char P_DIS[2];       // 参数显示数组 [TMAX, TMIN]
unsigned char Set_Index;      // 当前设置索引 (0=TMAX, 1=TMIN)
unsigned char Display_Mode;   // 显示模式 (1=参数设置模式)

3.2 中断服务函数

/* 定时器0中断服务函数 - 1ms周期 */
void Timer0Server() interrupt 1
{
    // ... 其他中断任务 ...

    /* 长按计时逻辑 */
    if((Key_Old == 14) || (Key_Old == 15))  // 检测S14或S15
    {
        if(++Key_Long == 65535)  // 累加计时
            Key_Long = 0;        // 防止溢出
    }
    else  // 按键松开
    {
        Key_Long = 0;  // 立即清零
    }
}

关键点:

  1. 精确计时: 每1ms累加一次,误差 < 0.1%
  2. 防溢出保护: 达到65535后归零
  3. 快速响应: 松开瞬间清零,下次按下重新计时

3.3 按键处理函数

当前实现(存在问题)

void Key_Proc()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 1;

    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Old ^ Key_Val);
    Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
    Key_Old = Key_Val;

    // ... 按键下降沿处理 ...

    /* 长按处理 - 当前实现 */
    switch(Key_Old)
    {
        case 14:  // S14增加
            if(Key_Long >= 250)  // ⚠️ 问题:无减速,触发过快
            {
                if(Display_Mode == 1)
                {
                    switch(Set_Index)
                    {
                        case 0:
                            P_DIS[0] ++;
                            if(P_DIS[0] >= 70) P_DIS[0] = 70;
                        break;
                        case 1:
                            P_DIS[1] ++;
                            if(P_DIS[1] >= 70) P_DIS[1] = 70;
                        break;
                    }
                }
            }
        break;

        case 15:  // S15减少 (类似逻辑)
            // ... 省略 ...
        break;
    }
}

问题分析:

  • :cross_mark: 触发频率 = 100次/秒(每10ms一次)
  • :cross_mark: 参数变化过快,难以精确控制
  • :cross_mark: 用户体验差

4. 优化方案

4.1 方案A:固定减速(推荐 :star:

实现代码

/* 新增全局变量 */
unsigned char Key_Long_Slow;  // 长按减速计数器

/* 优化后的按键处理函数 */
void Key_Proc()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 1;

    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Old ^ Key_Val);
    Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
    Key_Old = Key_Val;

    // ... 按键下降沿处理 ...

    /* 优化后的长按处理 */
    switch(Key_Old)
    {
        case 14:  // S14增加
            if(Key_Long >= 250)
            {
                if(Display_Mode == 1)
                {
                    if(++Key_Long_Slow >= 5)  // 减速控制
                    {
                        Key_Long_Slow = 0;  // 达到阈值后清零
                        switch(Set_Index)
                        {
                            case 0:
                                P_DIS[0] ++;
                                if(P_DIS[0] >= 70) P_DIS[0] = 70;
                            break;
                            case 1:
                                P_DIS[1] ++;
                                if(P_DIS[1] >= 70) P_DIS[1] = 70;
                            break;
                        }
                    }
                }
            }
        break;

        case 15:  // S15减少
            if(Key_Long >= 250)
            {
                if(Display_Mode == 1)
                {
                    if(++Key_Long_Slow >= 5)
                    {
                        Key_Long_Slow = 0;
                        switch(Set_Index)
                        {
                            case 0:
                                P_DIS[0] --;
                                if(P_DIS[0] <= 10) P_DIS[0] = 10;
                            break;
                            case 1:
                                P_DIS[1] --;
                                if(P_DIS[1] <= 10) P_DIS[1] = 10;
                            break;
                        }
                    }
                }
            }
        break;
    }
}

/* 中断服务函数修改 */
void Timer0Server() interrupt 1
{
    // ... 其他代码 ...

    if((Key_Old == 14) || (Key_Old == 15))
    {
        if(++Key_Long == 65535) Key_Long = 0;
    }
    else
    {
        Key_Long = 0;
        Key_Long_Slow = 0;  // 松开时重置减速计数器
    }
}

效果对比

项目 优化前 优化后
触发频率 100次/秒 20次/秒
触发间隔 10ms 50ms
调整10→70 0.6秒 3秒
用户体验 :cross_mark: 太快 :white_check_mark: 合适
精确控制 :cross_mark: 困难 :white_check_mark: 容易

4.2 方案B:加速曲线(进阶 :star::star:

实现代码

void Key_Proc()
{
    // ... 前置代码 ...

    switch(Key_Old)
    {
        case 14:
            if(Key_Long >= 250)
            {
                if(Display_Mode == 1)
                {
                    unsigned char speed;

                    /* 渐进加速曲线 */
                    if(Key_Long < 500)        // 0~0.5s: 初期
                        speed = 10;           // 每100ms触发
                    else if(Key_Long < 1500)  // 0.5~1.5s: 中期
                        speed = 5;            // 每50ms触发
                    else                      // 1.5s+: 后期
                        speed = 2;            // 每20ms触发

                    if(++Key_Long_Slow >= speed)
                    {
                        Key_Long_Slow = 0;
                        switch(Set_Index)
                        {
                            case 0:
                                P_DIS[0] ++;
                                if(P_DIS[0] >= 70) P_DIS[0] = 70;
                            break;
                            case 1:
                                P_DIS[1] ++;
                                if(P_DIS[1] >= 70) P_DIS[1] = 70;
                            break;
                        }
                    }
                }
            }
        break;

        case 15:  // 减少逻辑类似
            // ... 省略 ...
        break;
    }
}

速度曲线

触发频率 (次/秒)
   ↑
50 ┤                          ┌──────────
   │                          │ 快速期
20 ┤              ┌───────────┤
   │              │ 中速期    │
10 ┤──────────────┤           │
   │   初速期     │           │
 0 └──────────────┴───────────┴──────────→ 按下时长 (秒)
        0.5         1.5

效果对比

阶段 时长 速度 适用场景
初速期 0~0.5s 10次/秒 精确定位目标值
中速期 0.5~1.5s 20次/秒 中等范围调整
快速期 1.5s+ 50次/秒 大范围快速调整

4.3 方案C:自适应速度(专业 :star::star::star:

核心思想

根据当前值与边界的距离动态调整速度:

  • 离边界远 → 快速调整
  • 接近边界 → 自动减速
void Key_Proc()
{
    // ... 前置代码 ...

    switch(Key_Old)
    {
        case 14:
            if(Key_Long >= 250)
            {
                if(Display_Mode == 1)
                {
                    unsigned char speed;
                    unsigned char distance;  // 距离边界的距离

                    /* 自适应速度 */
                    switch(Set_Index)
                    {
                        case 0:  // 调整TMAX
                            distance = 70 - P_DIS[0];  // 距离上限
                            if(distance > 20)      speed = 2;   // 远离边界,快速
                            else if(distance > 5)  speed = 5;   // 接近边界,中速
                            else                   speed = 10;  // 临近边界,慢速
                        break;

                        case 1:  // 调整TMIN
                            distance = 70 - P_DIS[1];
                            if(distance > 20)      speed = 2;
                            else if(distance > 5)  speed = 5;
                            else                   speed = 10;
                        break;
                    }

                    if(++Key_Long_Slow >= speed)
                    {
                        Key_Long_Slow = 0;
                        // 执行增加操作
                    }
                }
            }
        break;
    }
}

5. 参数配置指南

5.1 Key_Long_Slow 阈值选择

计算公式

触发间隔 (ms) = 阈值 × Key_Proc周期
触发频率 (次/秒) = 1000 / 触发间隔

参数对照表

阈值 触发间隔 触发频率 10→70耗时 适用场景
1 10ms 100次/秒 0.6秒 :cross_mark: 太快
2 20ms 50次/秒 1.2秒 :warning: 较快
3 30ms 33次/秒 1.8秒 :white_check_mark: 快速调整
5 50ms 20次/秒 3秒 :white_check_mark: 推荐
8 80ms 12.5次/秒 4.8秒 :white_check_mark: 精确控制
10 100ms 10次/秒 6秒 :white_check_mark: 可用
20 200ms 5次/秒 12秒 :warning: 较慢
50 500ms 2次/秒 30秒 :cross_mark: 太慢
100 1000ms 1次/秒 60秒 :cross_mark: 禁止

选择建议

决策树:

参数范围 < 20?
 ├─ 是 → 阈值 8~10 (精确控制)
 └─ 否 ↓
参数范围 20~50?
 ├─ 是 → 阈值 5 (推荐) ⭐
 └─ 否 ↓
参数范围 > 50?
 └─ 是 → 阈值 3~5 (快速调整)

5.2 长按触发延迟 (Key_Long >= ?)

标准值对比

延迟 说明 适用场景
150ms 快速响应 游戏、快速操作
250ms 标准 蓝桥杯推荐 :star:
500ms 保守 防止误触优先
1000ms 超保守 :cross_mark: 不推荐

蓝桥杯建议

#define KEY_LONG_DELAY  250  // 250ms
#define KEY_LONG_SLOW   5    // 50ms间隔

if(Key_Long >= KEY_LONG_DELAY)
{
    if(++Key_Long_Slow >= KEY_LONG_SLOW)
    {
        // 执行动作
    }
}

6. 常见问题与解决方案

6.1 问题:长按触发过快,无法精确控制

症状:

想调整到 35,但一松开就跳到 38 了

原因: Key_Long_Slow 阈值过小

解决:

// 修改前
if(++Key_Long_Slow >= 2)  // 太快

// 修改后
if(++Key_Long_Slow >= 5)  // 合适

6.2 问题:长按后等待很久才开始变化

症状:

按住按键后,等了1秒才看到数字变化

原因: Key_Long 触发延迟过大

解决:

// 修改前
if(Key_Long >= 1000)  // 太慢

// 修改后
if(Key_Long >= 250)   // 标准

6.3 问题:松开按键后还在继续变化

症状:

松开 S14 后,参数还增加了 2~3 次

原因: 忘记在中断中清零 Key_Long_Slow

解决:

void Timer0Server() interrupt 1
{
    if((Key_Old == 14) || (Key_Old == 15))
    {
        if(++Key_Long == 65535) Key_Long = 0;
    }
    else
    {
        Key_Long = 0;
        Key_Long_Slow = 0;  // ✅ 必须清零
    }
}

6.4 问题:调整速度不均匀,有时快有时慢

症状:

有时每秒变化5次,有时每秒变化20次

原因: Key_Long_Slow 没有在执行后清零

解决:

if(++Key_Long_Slow >= 5)
{
    Key_Long_Slow = 0;  // ✅ 必须清零重计
    P_DIS[0] ++;
}

6.5 问题:按键按下瞬间就触发长按

症状:

刚按下 S14,立刻就开始连续增加

原因: 没有检查 Key_Long >= 250 条件

解决:

// 确保有延迟判断
if(Key_Long >= 250)  // ✅ 必须先达到阈值
{
    if(++Key_Long_Slow >= 5)
    {
        // 执行动作
    }
}

7. 性能分析

7.1 资源占用

资源 占用量 说明
RAM 3字节 Key_Long(2) + Key_Long_Slow(1)
ROM ~50字节 长按判断逻辑
CPU < 1% 中断和主循环开销极小

7.2 时序精度

项目 精度 误差
计时精度 1ms < 0.01%
触发延迟 ±10ms < 4%
触发频率 ±1次/秒 < 5%

7.3 响应时间

最快响应 = 长按延迟 + 减速周期
        = 250ms + 50ms
        = 300ms

首次触发后 = 每 50ms 触发一次

8. 最佳实践

8.1 蓝桥杯推荐配置

/* 宏定义配置 */
#define KEY_LONG_TRIGGER    250  // 长按触发延迟 (ms)
#define KEY_LONG_INTERVAL   5    // 触发间隔 (×10ms)

/* 全局变量 */
unsigned int Key_Long;
unsigned char Key_Long_Slow;

/* 中断服务函数 */
void Timer0Server() interrupt 1
{
    // ... 其他代码 ...

    if((Key_Old == 14) || (Key_Old == 15))
    {
        if(++Key_Long == 65535) Key_Long = 0;
    }
    else
    {
        Key_Long = 0;
        Key_Long_Slow = 0;
    }
}

/* 按键处理函数 */
void Key_Proc()
{
    // ... 前置代码 ...

    switch(Key_Old)
    {
        case 14:
            if(Key_Long >= KEY_LONG_TRIGGER)
            {
                if(Display_Mode == 1)
                {
                    if(++Key_Long_Slow >= KEY_LONG_INTERVAL)
                    {
                        Key_Long_Slow = 0;
                        // 执行增加操作
                    }
                }
            }
        break;

        case 15:
            // 减少逻辑类似
        break;
    }
}

8.2 代码规范

:white_check_mark: 推荐写法

// 1. 使用宏定义,便于调整
#define KEY_LONG_SLOW_THRESHOLD  5

// 2. 明确的变量命名
unsigned int Key_Long;         // 不要用 kl
unsigned char Key_Long_Slow;   // 不要用 kls

// 3. 清晰的注释
if(++Key_Long_Slow >= 5)  // 每50ms触发一次
{
    Key_Long_Slow = 0;  // 清零重计
    P_DIS[0] ++;        // 执行操作
}

// 4. 防御性编程
if(P_DIS[0] >= 70) P_DIS[0] = 70;  // 边界保护

:cross_mark: 不推荐写法

// 1. 魔法数字
if(++kls >= 5) { }  // ❌ 变量名不清晰

// 2. 缺少边界检查
P_DIS[0] ++;  // ❌ 可能超出范围

// 3. 忘记清零
if(Key_Long >= 250)
{
    P_DIS[0] ++;  // ❌ 没有减速控制
}

8.3 调试技巧

技巧1: 串口输出监控

if(Key_Long >= 250)
{
    if(++Key_Long_Slow >= 5)
    {
        Key_Long_Slow = 0;
        P_DIS[0] ++;

        // 调试输出
        printf("Key_Long=%u, Value=%u\n", Key_Long, P_DIS[0]);
    }
}

技巧2: LED指示

// 长按触发时点亮 L1
if(Key_Long >= 250)
{
    ucLed[0] = 1;  // 指示灯亮
}
else
{
    ucLed[0] = 0;  // 指示灯灭
}

技巧3: 数码管显示计时器

// 临时显示 Key_Long 值,便于调试
Seg_Buf[0] = Key_Long / 1000 % 10;
Seg_Buf[1] = Key_Long / 100 % 10;
Seg_Buf[2] = Key_Long / 10 % 10;
Seg_Buf[3] = Key_Long % 10;

9. 扩展功能

9.1 多按键长按支持

void Key_Proc()
{
    // 为每个按键分配独立的计时器
    static unsigned char Key_Slow[4] = {0, 0, 0, 0};  // S12~S16

    switch(Key_Old)
    {
        case 12:
            if(Key_Long >= 250)
                if(++Key_Slow[0] >= 5) { Key_Slow[0] = 0; /* 动作 */ }
        break;

        case 13:
            if(Key_Long >= 250)
                if(++Key_Slow[1] >= 5) { Key_Slow[1] = 0; /* 动作 */ }
        break;

        // ... 其他按键
    }
}

9.2 长按/短按区分

void Key_Proc()
{
    // 捕捉按键上升沿
    Key_Up = ~Key_Val & (Key_Old ^ Key_Val);

    if(Key_Up == 14)  // S14松开
    {
        if(Key_Long < 250)
        {
            // 短按动作:单次增加
            P_DIS[0] ++;
        }
        // 长按动作已在持续过程中执行
    }
}

9.3 双键组合长按

// 同时按住 S14 + S15 → 快速复位
if((Key_Old == 14) && (Key_Val == 15))  // 组合按键检测
{
    if(Key_Long >= 1000)  // 长按1秒
    {
        // 执行复位操作
        P_DIS[0] = 30;
        P_DIS[1] = 20;
    }
}

10. 附录

10.1 完整示例代码

文件位置: main.c

/* 头文件声明 */
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Key.h>
#include <Seg.h>

/* 宏定义 */
#define KEY_LONG_TRIGGER    250  // 长按触发延迟
#define KEY_LONG_INTERVAL   5    // 连续触发间隔

/* 全局变量 */
unsigned char Key_Val, Key_Down, Key_Old, Key_Up;
unsigned char Key_Slow_Down;
unsigned int Key_Long;
unsigned char Key_Long_Slow;
unsigned char P_DIS[2] = {30, 20};
unsigned char Set_Index;
unsigned char Display_Mode;

/* 按键处理函数 */
void Key_Proc()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 1;

    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Old ^ Key_Val);
    Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
    Key_Old = Key_Val;

    /* 按键下降沿处理 */
    switch(Key_Down)
    {
        case 12:  // 模式切换
            Display_Mode++;
            if(Display_Mode == 2) Display_Mode = 0;
        break;

        case 13:  // 切换设置项
            if(Display_Mode == 1)
            {
                Set_Index++;
                if(Set_Index == 2) Set_Index = 0;
            }
        break;
    }

    /* 长按处理 */
    switch(Key_Old)
    {
        case 14:  // S14增加
            if(Key_Long >= KEY_LONG_TRIGGER)
            {
                if(Display_Mode == 1)
                {
                    if(++Key_Long_Slow >= KEY_LONG_INTERVAL)
                    {
                        Key_Long_Slow = 0;
                        switch(Set_Index)
                        {
                            case 0:
                                P_DIS[0]++;
                                if(P_DIS[0] >= 70) P_DIS[0] = 70;
                            break;
                            case 1:
                                P_DIS[1]++;
                                if(P_DIS[1] >= 70) P_DIS[1] = 70;
                            break;
                        }
                    }
                }
            }
        break;

        case 15:  // S15减少
            if(Key_Long >= KEY_LONG_TRIGGER)
            {
                if(Display_Mode == 1)
                {
                    if(++Key_Long_Slow >= KEY_LONG_INTERVAL)
                    {
                        Key_Long_Slow = 0;
                        switch(Set_Index)
                        {
                            case 0:
                                P_DIS[0]--;
                                if(P_DIS[0] <= 10) P_DIS[0] = 10;
                            break;
                            case 1:
                                P_DIS[1]--;
                                if(P_DIS[1] <= 10) P_DIS[1] = 10;
                            break;
                        }
                    }
                }
            }
        break;
    }
}

/* 定时器0初始化 */
void Timer0Init(void)
{
    AUXR &= 0x7F;
    TMOD &= 0xF0;
    TL0 = 0x18;
    TH0 = 0xFC;
    TF0 = 0;
    TR0 = 1;
    ET0 = 1;
    EA = 1;
}

/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{
    if(++Key_Slow_Down == 10) Key_Slow_Down = 0;

    /* 长按计时 */
    if((Key_Old == 14) || (Key_Old == 15))
    {
        if(++Key_Long == 65535) Key_Long = 0;
    }
    else
    {
        Key_Long = 0;
        Key_Long_Slow = 0;
    }
}

/* 主函数 */
void main()
{
    System_Init();
    Timer0Init();

    while(1)
    {
        Key_Proc();
        Seg_Proc();
    }
}

10.2 测试用例

用例ID 操作 预期结果 通过标准
TC-01 短按S14 无反应 :white_check_mark: 未触发长按
TC-02 长按S14 (0.3s) 参数开始连续增加 :white_check_mark: 250ms后触发
TC-03 长按S14 (1s) 增加约20次 :white_check_mark: 频率正确
TC-04 参数达到70后继续长按 停止在70 :white_check_mark: 边界保护
TC-05 松开S14 立即停止增加 :white_check_mark: 快速响应
TC-06 从10调整到70 约3秒完成 :white_check_mark: 速度合适

10.3 参考资料

  • STC15F2K60S2 数据手册
  • 蓝桥杯单片机竞赛规则
  • 《单片机按键检测技术》
  • 《嵌入式系统人机交互设计》

版本历史

版本 日期 修改内容
v1.0 2026-02-03 初始版本,完整文档编写

文档结束