# 单片机调试助手-windows **Repository Path**: jswyll_com/mcu_assistant ## Basic Information - **Project Name**: 单片机调试助手-windows - **Description**: 单片机调试助手,集串口/蓝牙/TCP/UDP调试、IAP升级、波形助手、图像助手等功能一体 - **Primary Language**: C# - **License**: LGPL-3.0 - **Default Branch**: master - **Homepage**: https://jswyll.com/iap/ - **GVP Project**: No ## Statistics - **Stars**: 21 - **Forks**: 16 - **Created**: 2021-04-10 - **Last Updated**: 2025-08-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: 上位机, 无线升级, 串口调试, IAP ## README # 单片机调试助手-windows ## 1. 介绍 单片机调试助手,集串口/蓝牙/TCP/UDP调试、IAP升级、波形助手、图像助手等功能一体 ## 2. 安装教程 1. 点击右上方`克隆/下载`,下载ZIP包 2. 解压ZIP包,双击`单片机调试助手.exe`即可直接运行 > **注意** > > `单片机调试助手.exe.config`须与`单片机调试助手.exe`在同一个文件夹下,其它文件为说明文件,可删除。 ## 3. 软件特性 串口配置为1位起始位、8位数据位、1位停止位。 - 有新版本时软件自动更新 - 在接收区文本框连续单击三次可清空接收框内容 - 在发送区输入`\r\n`可以转义成回车换行 - 发送快捷键:Alt+N,N为0~9,对应各个发送按钮 - 可设置异常拔出串口后在10秒内尝试重新打开 - 记忆应用配置(设置、文本框、选择框内容) - 暗色界面主题 ### 单片机IAP升级 详见[在线升级调试程序(一) (jswyll.com/iap/)](https://jswyll.com/iap/ "在线升级调试程序") ### 彩色打印 - 解析ANSI颜色字符 > 本软件支持ANSI转义序列:[ANSI escape code - Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code)标准的重置(0)、黑色(30)、红色(31)、绿色(32)、黄色(33)和蓝色(34)转义序列。由于软件主题为亮色时,白色背景下的黄色前景字体不显眼,故以金色前景色显示。 典型例子:乐鑫科技ESP_LOG、[RT_Thread 日志组件](https://www.rt-thread.org/document/api/group__ulog.html "RT-Thread API参考手册: 日志组件")。 #### 效果图 ![image-20211111184033127](figures/colorful_log.png "彩色日志") #### RT-Thread打印 在"rt_config.h"中打开彩色宏定义 ```c #define RT_DEBUG #define RT_DEBUG_COLOR ``` 在.c源文件中可打印 ```c #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include int CO2; int main(void) { // ... LOG_D("init ok."); // ... LOG_I("read CO2 value: %d", CO2); // ... LOG_W("location info is noneffective."); // ... LOG_E("read O2 failed!"); while (1) { // ... } } ``` 其中,打印类型如下表: | 打印类型 | 说明 | 使用颜色打印时的颜色 | | -------- | ---- | -------------------- | | LOG_E | 错误 | 红色 | | LOG_W | 警告 | 黄色 | | LOG_I | 信息 | 绿色 | | LOG_D | 调试 | 默认颜色 | 各打印类型函数的用法与printf函数一样。 `DBG_TAG`是打印标签,每个源文件可以不一样,通常取为文件名,便于显示打印信息时知道打印来源。 打印等级`DBG_LVL`可取为:`DBG_ERROR`、`DBG_WARNING`、`DBG_INFO`、`DBG_LOG`,打印等级依次增大,即该源文件文件打印的类型越多: | DBG_LVL | 打印的类型 | | ----------- | -------------------------------------- | | DBG_ERROR | 只打印`LOG_E` | | DBG_WARNING | 打印`LOG_E`、`LOG_W` | | DBG_INFO | 打印`LOG_E`、`LOG_W`、`LOG_I` | | DBG_LOG | 打印`LOG_E`、`LOG_W`、`LOG_I`、`LOG_D` | 可以在调试时把打印等级设为`DBG_LOG`来显示更多的信息;在正式版时设为`DBG_INFO`或更高的等级以减少程序大小。 > **注意:**`#include `应在宏定义`DBG_TAG`和`DBG_LVL`之后。 #### 非RT-Thread中打印 不使用RT-Thread时,可以模仿RT-Thread的打印方式: 1. 新建一个"rtdbg.h"文件,保存在所在工程中,内容复制自RT-Thread的"rtdbg.h",并增加如下第37\~40行的代码 ```c /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2016-11-12 Bernard The first version * 2018-05-25 armink Add simple API, such as LOG_D, LOG_E */ /* * The macro definitions for debug * * These macros are defined in static. If you want to use debug macro, you can * use as following code: * * In your C/C++ file, enable/disable DEBUG_ENABLE macro, and then include this * header file. * * #define DBG_TAG "MOD_TAG" * #define DBG_LVL DBG_INFO * #include // must after of DBG_LVL, DBG_TAG or other options * * Then in your C/C++ file, you can use LOG_X macro to print out logs: * LOG_D("this is a debug log!"); * LOG_E("this is a error log!"); */ #ifndef RT_DBG_H__ #define RT_DBG_H__ #ifdef __cplusplus extern "C" { #endif #include #define RT_DEBUG #define RT_DEBUG_COLOR #define rt_kprintf printf /* the debug log will force enable when RT_DEBUG macro is defined */ #if defined(RT_DEBUG) && !defined(DBG_ENABLE) #define DBG_ENABLE #endif /* it will force output color log when RT_DEBUG_COLOR macro is defined */ #if defined(RT_DEBUG_COLOR) && !defined(DBG_COLOR) #define DBG_COLOR #endif #if defined(RT_USING_ULOG) /* using ulog compatible with rtdbg */ #include #else /* DEBUG level */ #define DBG_ERROR 0 #define DBG_WARNING 1 #define DBG_INFO 2 #define DBG_LOG 3 #ifdef DBG_TAG #ifndef DBG_SECTION_NAME #define DBG_SECTION_NAME DBG_TAG #endif #else /* compatible with old version */ #ifndef DBG_SECTION_NAME #define DBG_SECTION_NAME "DBG" #endif #endif /* DBG_TAG */ #ifdef DBG_ENABLE #ifdef DBG_LVL #ifndef DBG_LEVEL #define DBG_LEVEL DBG_LVL #endif #else /* compatible with old version */ #ifndef DBG_LEVEL #define DBG_LEVEL DBG_WARNING #endif #endif /* DBG_LVL */ /* * The color for terminal (foreground) * BLACK 30 * RED 31 * GREEN 32 * YELLOW 33 * BLUE 34 * PURPLE 35 * CYAN 36 * WHITE 37 */ #ifdef DBG_COLOR #define _DBG_COLOR(n) rt_kprintf("\033["#n"m") #define _DBG_LOG_HDR(lvl_name, color_n) \ rt_kprintf("\033["#color_n"m[" lvl_name "/" DBG_SECTION_NAME "] ") #define _DBG_LOG_X_END \ rt_kprintf("\033[0m\n") #else #define _DBG_COLOR(n) #define _DBG_LOG_HDR(lvl_name, color_n) \ rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ") #define _DBG_LOG_X_END \ rt_kprintf("\n") #endif /* DBG_COLOR */ /* * static debug routine * NOTE: This is a NOT RECOMMENDED API. Please using LOG_X API. * It will be DISCARDED later. Because it will take up more resources. */ #define dbg_log(level, fmt, ...) \ if ((level) <= DBG_LEVEL) \ { \ switch(level) \ { \ case DBG_ERROR: _DBG_LOG_HDR("E", 31); break; \ case DBG_WARNING: _DBG_LOG_HDR("W", 33); break; \ case DBG_INFO: _DBG_LOG_HDR("I", 32); break; \ case DBG_LOG: _DBG_LOG_HDR("D", 0); break; \ default: break; \ } \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_COLOR(0); \ } #define dbg_here \ if ((DBG_LEVEL) <= DBG_LOG){ \ rt_kprintf(DBG_SECTION_NAME " Here %s:%d\n", \ __FUNCTION__, __LINE__); \ } #define dbg_log_line(lvl, color_n, fmt, ...) \ do \ { \ _DBG_LOG_HDR(lvl, color_n); \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_LOG_X_END; \ } \ while (0) #define dbg_raw(...) rt_kprintf(__VA_ARGS__); #else #define dbg_log(level, fmt, ...) #define dbg_here #define dbg_enter #define dbg_exit #define dbg_log_line(lvl, color_n, fmt, ...) #define dbg_raw(...) #endif /* DBG_ENABLE */ #if (DBG_LEVEL >= DBG_LOG) #define LOG_D(fmt, ...) dbg_log_line("D", 0, fmt, ##__VA_ARGS__) #else #define LOG_D(...) #endif #if (DBG_LEVEL >= DBG_INFO) #define LOG_I(fmt, ...) dbg_log_line("I", 32, fmt, ##__VA_ARGS__) #else #define LOG_I(...) #endif #if (DBG_LEVEL >= DBG_WARNING) #define LOG_W(fmt, ...) dbg_log_line("W", 33, fmt, ##__VA_ARGS__) #else #define LOG_W(...) #endif #if (DBG_LEVEL >= DBG_ERROR) #define LOG_E(fmt, ...) dbg_log_line("E", 31, fmt, ##__VA_ARGS__) #else #define LOG_E(...) #endif #define LOG_RAW(...) dbg_raw(__VA_ARGS__) #endif /* defined(RT_USING_ULOG) && define(DBG_ENABLE) */ #ifdef __cplusplus } #endif #endif /* RT_DBG_H__ */ ``` 注释第39行`#define RT_DEBUG_COLOR`可关闭颜色打印。 2. 在.c源文件中使用,使用方法和在RT-Thread中一样 > **注意:** 由于Keil C51的不支持C99以上的语法标准,不支持可变宏定义,以上方法无法在Keil C51中使用。 ### 虚拟波形助手 效果: ![虚拟波形助手](figures/scope.gif "虚拟波形助手") - 单击可移动红色游标到该位置 - 鼠标指针移到曲线上可显示该点数值 - 双击暂停接收波形(关闭端口),再次双击继续接收(打开端口) - 在图表区域鼠标滚轮可缩放 测试条件:51单片机STC8G,波特率115200bps #### 使用方法 在`菜单栏 - 扩展 - 波形助手`打开该功能,软件在收到指定协议的数据后将自动解析为波形。 当前协议:单片机发送数据格式:“0:波形1数值,1:波形2数值,2:波形3数值...\r\n”。其中“\r\n”代表回车并换行,每发送一行代表一次各个波形的Y值,冒号和逗号均为英文半角符,数值可为整数或小数,冒号前的0、1、2、3等表示数据对应于哪个波形。示例:`0:-0.912962,1:0.408004\r\n` 测试代码,发送正弦、余弦函数值: ```c #include #include void main() { float t = 0; // 初始化... while(1) { printf("0:%f,1:%f\r\n", sin(t), cos(t)); t += 0.1; delay_ms(10); } } ``` 上述代码中printf函数已被重定向输出到串口,故可以直接用printf打印。 如果printf未重定向输出到串口,可以用先用`sprintf`函数先将字符串输出到数组,然后再调用串口函数发送字符串,效果是等同的: ```c #include #include #includde void main() { float t = 0; char txt[64]; // 初始化... while(1) { sprintf(txt, "0:%f,1:%f\r\n", sin(t), cos(t)); uart_putstr(UART_1, txt, strlen(txt)); t += 0.1; delay_ms(10); } } ``` 例如,智能车调试PID时,可以: ```c #include extern int aim_speed, real_speed; extern float speed_P, speed_I, speed_D; int main(void) { // 初始化... while(1) { printf("0:%d,1:%d,2:%.3f,3%.3f,4:%.3f", aim_speed, real_speed, speed_P, speed_I, speed_D) delay_ms(100); } } ``` 效果如下: ![image-20211106184531877](figures/PID.png "PID调试") ## 4. 更新日志 ### 2023.03.26 - `[新增]` 全面的测试;优化代码覆盖率 破坏性变化: - `[移除]` 图像助手功能 - `[移除]` 使用扇区描述文件功能。编程扇区时,上位机只负责按照选择的编程大小发送指令`0x02`、目标地址、数据;iap设备端收到后,应判断目标地址是否为扇区地址,如果是就先擦除扇区,然后向目标地址编程数据。这么做的好处在于上位机无需理会扇区分布情况,并且选择的编程大小可以小于扇区大小。 ### 2022.01.12 - `[新增]` 两个多条发送行;修复全屏时遮住状态栏 ### 2021.09.22 - `[新增]` IAP支持扇区大小不一的MCU(使用扇区描述文件) ### 2021.09.26 - `[新增]` 修复Keil编译一次触发两次升级问题 ### 2022.03.30 - `[修复]` 某些情况下启动时自动打开端口的为空;支持使用bin文件和flash描述文件进行升级 ## 5. 问题反馈 提交issue:[https://gitee.com/jswyll_com/mcu_assistant/issues](https://gitee.com/jswyll_com/mcu_assistant/issues "问题反馈") 作者邮箱:2439423861@qq.com