扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

效率提升!嵌入式老鸟私藏的终端神器

02/01 11:25
947
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

大家好,我是杂烩君。

嵌入式开发,终端工具就像螺丝刀:不需要花里胡哨,但要顺手、稳定、关键功能齐全。

这次我们来推荐一个Github上开源的、跨平台、热门的终端工具——COMTool

https://github.com/Neutree/COMTool

1. COMTool 功能

串口调试:ASCII/HEX、定时发送、发送历史、常用指令一键发送、收发统计、时间戳、保存日志、发送文件、转义字符等,都有。

协议插件:内置“协议插件”,支持自己写 Python 编解码脚本,还能做快捷键发送(例如方向键控制设备)。

图表插件:内置“图表插件”,按协议帧实时画折线,做传感器/姿态曲线很方便。

网络/远程:同一个工具里还能切到 TCP/UDP、SSH(配合终端插件)。

2. 串口

COMTool 的“调试插件”(一般叫 Send Receive / dbg)就是最传统的串口收发界面,但它把很多小功能做得很顺手。

支持:

    ASCII / HEX 双模式定时发送(压测/心跳/自动化)常用指令、发送历史时间戳、保存日志、自动换行终端颜色(ANSI Color)发送文件收发统计与清屏/清缓存(跑长测必用)编码与“乱码”处理

3. 图表

如果你经常调 IMU、温度、ADC电机速度,串口刷数字看久了会很痛苦。COMTool 的图表插件思路很直接:

你给它发一种“曲线协议帧”它按帧解析出 name/x/y,就能实时画折线图表控件还能在设置里

双击添加(想画几条就加几条)

4. TCP/UDP

除了串口,COMTool 还支持 TCP/UDP(客户端/服务端)

    串口 + 网口双通道设备UDP 广播发现、日志上报TCP 长连接协议

5. SSH

6. 协议

很多时候我们不是单纯收发字符串,而是有一套自己的协议:帧头、长度、校验、字段解析、再把结果友好地打印出来。

COMTool 的 协议插件就是干这个的,而且门槛不高:

你可以在插件里写一段 Python 代码,定义 encode()decode(),就能实现“发送前打包、接收后解包”。它还支持

自定义快捷键发送(Key mode):比如方向键控制云台/小车,不用鼠标点点点。

例如,STM32 端做一套二进制协议(带帧头/长度/校验),COMTool 的 decode() 负责把上报帧解析成可读内容;COMTool 的 encode() 负责把“点灯/灭灯”命令打包发给 STM32。

协议例子

帧格式:

AA 55:帧头

LEN:后面

CMD+PAYLOAD 的字节数

CMD:命令字(1 字节)

PAYLOAD:数据(可选)

SUM:校验(把 AA 55 LEN CMD PAYLOAD... 全部字节求和,取低 8 位)

主要行为是:

周期性上报:每 200ms 发一帧 REPORT,payload 里带 LED 状态 + 计数器接收命令并回包

:收到 LED_SET(0/1) 就控制 PC13 的 LED,并回一帧 ACK

staticvoidcomtool_protocol_task(void *param)
{
    (void)param;

    uint32_t counter = 0;
    uint8_t led_state = 0;

    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

    // parser state
    enum { S_HDR0, S_HDR1, S_LEN, S_BODY, S_SUM } st = S_HDR0;
    uint8_t len = 0;
    uint8_t body[1 + COMTOOL_P1_MAX_PAYLOAD]; // CMD + payload
    uint8_t body_idx = 0;
    uint8_t chk = 0;

    TickType_t last_report = xTaskGetTickCount();

    while (1)
    {
        // ---- parse RX bytes ----
        uint8_t b = 0;
        while (comtool_rb_pop(&b))
        {
            switch (st)
            {
            case S_HDR0:
                st = (b == COMTOOL_P1_HDR0) ? S_HDR1 : S_HDR0;
                break;
            case S_HDR1:
                st = (b == COMTOOL_P1_HDR1) ? S_LEN : S_HDR0;
                break;
            case S_LEN:
                len = b;
                if (len < 1 || len > (1 + COMTOOL_P1_MAX_PAYLOAD))
                {
                    st = S_HDR0;
                    break;
                }
                body_idx = 0;
                // init checksum = sum(AA,55,LEN)
                chk = (uint8_t)((COMTOOL_P1_HDR0 + COMTOOL_P1_HDR1 + len) & 0xFF);
                st = S_BODY;
                break;
            case S_BODY:
                body[body_idx++] = b;
                chk = (uint8_t)((chk + b) & 0xFF);
                if (body_idx >= len)
                    st = S_SUM;
                break;
            case S_SUM:
                if (chk == b)
                {
                    // valid frame
                    uint8_t cmd = body[0];
                    constuint8_t *pl = &body[1];
                    uint8_t pl_len = (uint8_t)(len - 1);

                    if (cmd == COMTOOL_CMD_LED_SET && pl_len >= 1)
                    {
                        led_state = (pl[0] != 0) ? 1 : 0;
                        HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, led_state ? GPIO_PIN_SET : GPIO_PIN_RESET);

                        uint8_t ack_pl[3] = { cmd, 0x00, led_state }; // result=0 ok
                        comtool_send_frame(COMTOOL_CMD_ACK, ack_pl, sizeof(ack_pl));
                    }
                }
                st = S_HDR0;
                break;
            default:
                st = S_HDR0;
                break;
            }
        }

        // ---- periodic report ----
        TickType_t now = xTaskGetTickCount();
        if ((now - last_report) >= pdMS_TO_TICKS(200))
        {
            last_report = now;
            counter++;
            uint8_t rep_pl[1 + 4];
            rep_pl[0] = led_state;
            rep_pl[1] = (uint8_t)(counter & 0xFF);
            rep_pl[2] = (uint8_t)((counter >> 8) & 0xFF);
            rep_pl[3] = (uint8_t)((counter >> 16) & 0xFF);
            rep_pl[4] = (uint8_t)((counter >> 24) & 0xFF);
            comtool_send_frame(COMTOOL_CMD_REPORT, rep_pl, sizeof(rep_pl));
        }

        vTaskDelay(pdMS_TO_TICKS(5));
    }
}

总结

COMTool 给我的感觉是:它不是“功能堆满”的那种大而全,而是把嵌入式最常用的调试链路——收发、协议、终端、曲线——做成了一个相对统一、能长期用的工具。如果你也在找一款“用着顺手、不卡、还能扩展”的串口工具,这是个不错的选择。

如果觉得文章有帮助,麻烦帮忙转发,谢谢!

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

本公众号专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,公众号内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!