You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式测试脚本:如何在按键触发前持续执行周期性动作

问题

我正在为嵌入式控制器编写测试脚本,部分测试需用户执行操作后方可继续。例如,我会在屏幕打印如下指令:

printf("Turn switch A to ON position then press any key");

随后希望脚本等待用户按下按键后,再执行后续测试步骤:

ExpectedSwitchState = ON;
CheckSwitch(01);

我可以通过以下方式轻松实现等待(但需按下回车键):

printf("\nPress Enter to continue");
getChar();

当前面临的问题是:必须确保工具在无其他命令传输时,每4秒发送一次tester present消息;且希望按键后立即恢复执行,无需等待剩余的4秒周期。

我更熟悉嵌入式C语言,对电脑输入相关的常用命令不太了解。目前仅找到暂停程序的方法,尚未知晓如何实现“持续执行动作直到按键按下”的逻辑。我曾考虑编写一个while循环,每1ms递增计数器,当计数器达到4000时发送tester present消息,同时检测到按键则退出循环,但该方案略显繁琐,且我不清楚检测按键的具体命令。

解决方案

1. 实现非阻塞按键检测

标准C没有内置非阻塞键盘检测函数,需基于平台实现:

  • Windows平台:直接用<conio.h>里的_kbhit()(检测按键是否按下,非阻塞)和_getch()(读取按键且不回显)。
  • Linux/macOS平台:通过修改终端属性实现非阻塞检测,示例代码如下:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>

// 非阻塞检测按键是否按下
int kbhit(void) {
    struct termios oldt, newt;
    int ch;
    int oldf;

    // 保存终端原有属性
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    // 关闭规范模式和回显
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    // 设置终端为非阻塞模式
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();

    // 恢复终端原有属性
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    if(ch != EOF) {
        ungetc(ch, stdin); // 将字符放回输入流,供后续读取
        return 1;
    }

    return 0;
}

2. 结合定时器实现核心逻辑

基于非阻塞按键检测,编写循环逻辑,同时满足每4秒发送tester present、按键立即退出的需求:

#include <stdio.h>
#include <unistd.h> // Linux下用于usleep,Windows用Sleep()

#define TESTER_INTERVAL_MS 4000 // 4秒间隔,单位毫秒

void WaitForUserAndSendTester(void) {
    unsigned int elapsed_ms = 0;
    printf("Turn switch A to ON position then press any key\n");

    while(1) {
        // 检测到按键则退出循环
        if(kbhit()) {
            getchar(); // 读取按键,清除输入缓存
            break;
        }

        // 1ms延时(根据平台调整:Windows用Sleep(1),Linux用usleep(1000))
        usleep(1000);
        elapsed_ms++;

        // 达到4秒间隔,发送tester present
        if(elapsed_ms >= TESTER_INTERVAL_MS) {
            printf("Sending tester present message...\n");
            // 替换为实际发送tester present的函数调用
            // SendTesterPresent();
            elapsed_ms = 0;
        }
    }

    // 执行后续测试步骤
    ExpectedSwitchState = ON;
    CheckSwitch(01);
}

3. 优化建议

  • 不要依赖固定延时(如usleep(1000)),建议用系统高精度定时器(比如Linux的clock_gettime、Windows的QueryPerformanceCounter)计算时间差,避免系统负载高时导致间隔不准。
  • 跨平台场景用条件编译区分不同平台的代码,比如:
#ifdef _WIN32
#include <conio.h>
#include <windows.h>
#define DELAY_MS(ms) Sleep(ms)
#else
#include <unistd.h>
#define DELAY_MS(ms) usleep(ms*1000)
#endif

内容的提问来源于stack exchange,提问作者Shaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:12:45