├── .gitignore ├── README.md ├── changelog.txt ├── doc ├── github.txt ├── qbytearray.md ├── todo.txt ├── 上位机程序开发文档.docx ├── 主界面-20160508.jpg ├── 主界面设计.png ├── 使用说明书 - v2.0.docx ├── 使用说明书 - v2.1.docx ├── 指令列表.png ├── 测试-20160626.jpg ├── 通信协议-20160409.xlsx ├── 通信协议-20160411.xlsx ├── 通信协议-20160413.xlsx ├── 通信协议-20160416.xlsx ├── 通信协议-20160423.xlsx ├── 通信协议-20160507.xlsx ├── 通信协议-20160709.xlsx └── 通讯协议定义.txt └── src ├── command.cpp ├── command.h ├── commanditemlist.cpp ├── commandline.cpp ├── commandline.h ├── config └── save.json ├── configdialog.cpp ├── configdialog.h ├── configdialog.ui ├── console.cpp ├── console.h ├── form.cpp ├── form.h ├── form.ui ├── images ├── app.ico ├── application-exit.png ├── clear.png ├── close.png ├── connect.png ├── disconnect.png ├── help.png ├── help_48dp.png ├── link.png ├── link_off.png ├── open.png ├── save.png ├── serial.png ├── settings.png └── settings_new.png ├── line.cpp ├── line.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── settingsdialog.cpp ├── settingsdialog.h ├── settingsdialog.ui ├── tuner.pro └── tuner.qrc /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | qrc_*.cpp 24 | ui_*.h 25 | Makefile* 26 | *build-* 27 | 28 | # QtCreator 29 | 30 | *.autosave 31 | 32 | #QtCtreator Qml 33 | *.qmlproject.user 34 | *.qmlproject.user.* 35 | 36 | release/ 37 | downloads/ 38 | # windows file 39 | ~$* 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # step-servo-tuner 2 | 采用QT框架开发PC端串口通信程序,步进电机控制器与PC端通信,调试控制器程序 3 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | 2016-4-13 2 | ========== 3 | 暂时实现配置数据下载功能,包含11个命令数据,总计110个字节。 4 | 5 | terminal.exe为主程序。 6 | 7 | 2016-4-23 8 | ========== 9 | 10 | 修改内容: 11 | 12 | 1、主程序名改为 tuner.exe 13 | 2、主界面 14 | 3、配置参数界面,操作详见使用说明书。 15 | 16 | 17 | 2016-5-11 18 | =========== 19 | 测试版功能 20 | 1、配置参数的文件保存与读取(对应save.json文件); 21 | 2、所有指令加入指令队列功能。 22 | 23 | 24 | 2016-5-12 25 | =========== 26 | 1、修改参数配置需重启软件生效; 27 | 2、写入配置文件或下载参数增加提示框; 28 | 3、增加延时指令; 29 | 4、修改少许BUG。 30 | 31 | 32 | 2016-7-2 33 | =========== 34 | 版本v1.1 35 | 1、修改已有BUG; 36 | 2、修改程序文件格式 37 | 程序文件json格式定义 38 | { 39 | title: -- 指令类型 40 | content: -- 指令内容 41 | type: -- 指令编码 42 | params: [] -- 指令参数 43 | data: -- 指令数据 44 | } 45 | 3、指令行与工具栏自动关联 46 | 47 | 注意:之前程序文件不可用,请用自带示例程序进行演示,或重新生成程序文件。 48 | 49 | 2016-7-10 50 | ============= 51 | 版本v1.2,修改记录: 52 | 1、启用相对指令,且仅下发相对脉冲数,无需转为绝对脉冲数 53 | 2、速度设置直接下发频率值,无需转换为百分比 54 | 3、启用零点设置 55 | 版本v1.2,修改记录: 56 | 1、启用相对指令,且仅下发相对脉冲数,无需转为绝对脉冲数 57 | 2、速度设置直接下发频率值,无需转换为百分比 58 | 3、启用零点设置 59 | 60 | v1.3 61 | 修改256细分时的速度设置,需要对每秒脉冲数除以2后下发,其他细分不作处理。 62 | 63 | 说明如下: 64 | 1、转速*电机圆周长=线速度。 65 | 2、转速*200*电机细分等级=每秒脉冲数。 (说明:200是360°除以电机的步距角1.8°所得的) 66 | 3、每秒脉冲数*100/50000=速度档位。 (注意: 50000是金工设定的最高脉冲频率,100是因为算百分比,速度档位的值就是你原来要下发的值) 67 | 68 | 2016-7-23 69 | =============== 70 | 发布V2.0版本,新增功能: 71 | 1、插入指令,用户选择指令行前插入若干指令; 72 | 2、删除指令改进,用户可选中指令行删除; 73 | 3、改进指令程序可读性,指令形式改为[指令代号 参数列表],比如绝对位置300mm 74 | 指令为 POS 300,以空格隔开指令与参数,多个参数使用空格字符隔开。 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /doc/github.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/github.txt -------------------------------------------------------------------------------- /doc/qbytearray.md: -------------------------------------------------------------------------------- 1 | ## QByteArray 2 | 3 | 一句话 4 | > The QByteArray class provides an array of bytes. 5 | 6 | 如上所述,`QByteArray`类用于操作字节数组。 7 | 8 | `QByteArray`用于操作字符串,可以是以`\0`结尾的原生字节(raw bytes)或者传统意义的8位字节字符串。 9 | 用起来比`const char *`指针方便太多(没体验过,持怀疑态度)。 10 | 11 | `QString`类也是Qt用来管理字符串,不同的是采用16位Unicode字符,可以存放non-ASCII/non-Latin-1 12 | 字符。`QByteArray`有两个优势:a) 用于管理原生二进制数据;b) 内存资源稀缺情况下(如嵌入式Linux 13 | 环境)。 14 | 15 | ### 初始化 16 | 17 | `QByteArray ba("Hello")` 传人`const char *`初始化`QByteArray`数据类型。 18 | 19 | `resize()`方法 20 | ```cpp 21 | QByteArray ba; 22 | ba.resize(5); 23 | ba[0] = 0x3c; 24 | ba[1] = 0xb8; 25 | ba[2] = 0x64; 26 | ba[3] = 0x18; 27 | ba[4] = 0xca; 28 | ``` 29 | 30 | ### QByteArray::fromHex(), QByteArray::toHex() 31 | ``` 32 | QByteArray ba("Hello"); 33 | ba.toHex(); // 34 | ``` 35 | 36 | ### 思路 37 | QtGui界面上字符串`QString`进行组装为指令结构体数据类型,然后转换为`QByteArray`数据类型,便于串口进行传送。 38 | 39 | - 从交互界面获取字符数据 40 | - 数据组装为指令数据 41 | - 转成`QByteArray`数据格式 42 | - 通过串口发送出去 43 | -------------------------------------------------------------------------------- /doc/todo.txt: -------------------------------------------------------------------------------- 1 | 2016-2-20 周六 2 | =============== 3 | 今天的工作任务: 4 | 1. 摆放配置相关控件并结合软件管理控件 5 | 2. 实现配置参数串口通信写入功能 6 | 界面功能说明: 7 | 从驱动器上传 - 读取驱动器寄存器数值 8 | 下载到驱动器 - 向驱动器写入参数值 9 | 启动 - 启动或停止运动控制指令 10 | 11 | 2016-2-22 周一 12 | ================ 13 | 今天编辑了开发文档,提出自己疑问。 14 | 上周六半天时间把步进电机调制程序功能界面基本摆放完毕,以及一份说明文档。 15 | 16 | 17 | 18 | 2016-4-13 周三 19 | ================= 20 | 之前关于 将quint8数组转换为QByteArray类型数据问题 21 | 使用 append()方法无法实现 22 | 后改用 QByteArray operator[] 实现该功能 23 | 24 | 25 | 2016-4-16 周六 26 | ================== 27 | 换行(NL - next line)对应整型值为10 28 | 回车(CR)对应整数值为13 29 | 30 | 配置用弹出界面提供用户,硬件参数,软件参数 31 | 运动控制采用函数库的形式,工具,支持拖拽。 32 | 增加硬件参数配置功能 33 | 34 | 运动控制指令 35 | 距离需转换为脉冲数,毫米/一圈 36 | plus = 37 | 一圈需要多少脉冲 - 200 38 | 百分比*50K = 39 | 40 | 2016-4-17 周日 41 | =================== 42 | 功能需求 43 | 1、读取配置文件 - 电机机械参数、型号等参数(难度**) 44 | 2、主界面功能,指令参数设定、指令拖放、指令序列单步或自动执行(难度*****) 45 | 关于参数配置 46 | 一方面是下位机配置(通过串口下载到驱动器,也可以回读到页面) 47 | 另一方面就是上位机配置(直接放在内存或磁盘上) 48 | 49 | 50 | 2016-4-19 周二 51 | ==================== 52 | TODO 53 | 今晚实现配置文件读取功能 54 | 55 | 配置包括串口配置、控制器配置、机械参数配置 56 | 串口配置写入串口设备缓存 57 | 控制器配置通过串口传给控制器 58 | 机械参数配置到上位机目录下 59 | 60 | 2016-4-20 周三 61 | ==================== 62 | DO 63 | 配置数据写入磁盘文件(JSON格式) 64 | TODO 65 | QTableWidget增加数据行 66 | 67 | 2016-4-26 周二 68 | ===================== 69 | 编程经验: 70 | 不要纠结于界面排版,核心是逻辑和数据结构设计,功能分离 71 | 了解一些软件设计模式,比如model/view,视图-展示框架 72 | 有想法赶紧去着手实现,时间往往就在徘徊和拖延中流失 73 | 功不唐捐,深入了解一个类的接口,都是有益的 74 | 75 | 2016-4-27 周三 76 | ===================== 77 | 昨晚认真研究 model/view 设计思路。 78 | model作为数据处理关键,最终通过view展示,而且可以同时展示与不同view 79 | model整理 80 | QStringListModel - 管理QString单元 81 | QStandardItemModel - 管理比较复杂的树结构,可以是任意类型数据 82 | 单步对应单步执行指令,单击一次发送一条指令。 83 | 自动对应从开始执行到结束为止,中间可以插入跳转指令。 84 | 85 | 2016-4-28 周四 86 | ====================== 87 | 今晚弄明白 QAbstractItemModel 如何追加一行数据: 88 | model 先插入某行, 然后 setData 该行数据即可 89 | 90 | 现在的思路是: 91 | 初始行变量为0 92 | 追加一行,行变量加1,指令序列增加相应指令数 93 | 删除一行,行变量减1,指令序列删除相应指令数 94 | 95 | 单步执行,单击执行按钮从指令序列起始位置发送相应数量指令 96 | 自动执行,单击执行按钮指令序列一次性发送,根据下位机返回的数据定位到具体指令行。 97 | 98 | 2016-5-5 周四 99 | ====================== 100 | 101 | 102 | 103 | 2016-5-7 周六 104 | ====================== 105 | 功能 106 | 1、 根据用户输入位置值(绝对或相对)转成脉冲数, 107 | 公式:绝对位置/周长 * 1圈脉冲数(200*细分等级) 108 | 2、 参数打包需将发送参数写入磁盘持久化 109 | 3、 下载打包,可以多次下载 110 | 111 | 112 | 113 | 200脉冲 - 1圈 114 | 200*细分 = 1圈脉冲数 115 | 距离转换脉冲数 116 | 117 | 2016-5-8 周日 118 | ======================= 119 | 发布一个软件版本,支持运行指令新增、删除、清空,以及单步运行,下载和停止功能。 120 | 一直想完善的指令数据结构、配置指令下载功能,无奈惰性阻力无力抗拒,一直搁浅 121 | 接下来的主要工作是继续完成其他指令,如操作、跳转、IO等指令功能 122 | 此外,指令修改功能(行选中进行编辑,编辑区仍然是指令区) 123 | 124 | 125 | 2016-5-18 周三 126 | ======================== 127 | 控制器上位机发布beta版后需要改进部分: 128 | 1、电流档位和电压边界配置需求修改 129 | 2、增加控制主板选配(最大电流与IO端口数等) 130 | 3、指令程序持久化,保存为文件形式(比如json文件) 131 | 132 | 2016-5-20 周五 133 | ======================== 134 | 需求修改 135 | 1、电流档位和电压边界自动设置 136 | 2、增加控制器选型,最大电流与IO数变更 137 | 3、程序指令持久化 138 | 139 | 1、2以完成,3进行中 140 | 141 | 2016-5-21 周六 142 | ======================== 143 | big bug: 144 | 软件每次启动需读取配置文件,若文件不存在,软件无法启动。 145 | fix bug: 146 | 将配置文件作为资源文件,首次从资源读取。 147 | 148 | 2016-5-26 周四 149 | ======================== 150 | 需求更改: 151 | 1、速度档位输入改为线速度输入(mm/s),并转换成转速(rps)显示, 152 | 转换为档位百分比发给金; 153 | 2、程序文件持久化. 154 | 155 | 2016-5-27 周五 156 | ======================== 157 | 1、完善程序载入和保存功能,并测试功能; 158 | 2、更换图标和应用图标 159 | action icon: https://design.google.com/icons/ 160 | app icon: http://www.iconarchive.com/show/flatwoken-icons-by-alecive/Apps-Audio-Card-icon.html 161 | 162 | 2016-5-31 周二 163 | ========================= 164 | 考虑指令列表的修改需求实现: 165 | 1 166 | 双击选中后,指令编辑界面选中,加入按钮变为修改,提示修改参数 167 | a 鼠标双击后如何判断是什么类型指令 168 | b 选中指令行点击“修改”获取选中行类型及其参数输入入口 169 | 170 | 难度系数 a+++ b++ 171 | 关键问题是:如何确定选中行是什么指令类型 172 | 173 | 任务分解: 174 | 1 175 | QAbstractItemModel相关知识 176 | 2 177 | QMouseEvent 鼠标事件,获取选中行 178 | 3 179 | 增加选中行信息维度 180 | 4 181 | 选中行信息相关操作,修改命令行参数 182 | 183 | 2016-6-2 周四 184 | ========================= 185 | 新需求:系统上电运行需要提醒或警告用户 186 | 鼠标事件 187 | void mousePressEvent(QMouseEvent *e); 188 | void mouseReleaseEvent(QMouseEvent *e); 189 | void mouseDoubleClickEvent(QMouseEvent *e); 190 | 191 | QT事件与信号的区别 192 | 事件实际上是事件列队,不同对象可能触发相同事件,所以有列队管理 193 | 信号可以具体到某个对象,即比事件更加精准 194 | 195 | 2016-6-4 周六 196 | =========================== 197 | 上周四研究发现无需通过监测鼠标事件实现修改指令功能,而是通过响应 198 | QTableView单击或双击信号实现指令行修改。 199 | 具体怎么实现有些门道,需要认真考虑,一旦突破关键障碍,可能就不再是问题。 200 | 201 | 2016-6-6 周一 202 | =========================== 203 | 近期打算从该控制器项目退出,考虑到指令修改功能尚未实现,而且自己在逃避困难 204 | 两天周末时间没有投入时间解决问题,而是把时间用在MIT课程中,尽管从Python语言 205 | 数据处理和可视化课程中学习到不少知识,但归根结底还是在逃避问题。 206 | 那么,指令修改有哪些问题呢? 207 | 选中行所属指令类型如何标识,便于触发相应指令编辑工具栏 208 | 指令相关数据的更新问题, 209 | 210 | 2016-6-16 周四 211 | =========================== 212 | 思考程序的核心层,即两个概念或者数据结构: 213 | 指令 214 | 操作方法: 215 | 构造方法 - 根据指定类型生成通讯协议设计数据结构 216 | 整型数据转换为字符数组 int -> quint8[] 217 | 数组转换为串口通讯数据格式 quint8[] -> QByteArray 218 | 219 | 指令模型 管理指令序列 220 | 操作方法: 221 | 插入指令 222 | 修改指令 223 | 移动指令 224 | 删除指令 225 | 发送串口数据 226 | 保存指令文件 227 | 读取指令文件 228 | 229 | 注意:语言基础薄弱 核心层很难完成 支持性工作需要铺垫 230 | 231 | 2016-6-17 周五 232 | ============================= 233 | 重构指令数据,封装各种类型指令的数据构建。 234 | 235 | 接下来是重要的指令管理模型数据重构,比指令难些,实现指令序列 236 | 顺序加入 237 | 插入(前与后) 238 | 修改 239 | 移动 240 | 删除 241 | 242 | 243 | 2016-6-21 周二 244 | ============================== 245 | 别人往往只能看到结果,所以过程是自己,结果给别人尽量漂亮点 246 | 自定义数据角色(显示 可编辑 提示等等) 247 | model->setData(model->index(row, 0), acmd.type(), Qt::UserRole); 248 | model->setData(model->index(row, 1), acmd.type(), Qt::UserRole); 249 | 250 | QModleIndex::data(int role = Qt::DisplayRole) 251 | 默认返回显示角色数据 252 | QModleIndex::data(int role = Qt::UserRole) 253 | 即可显示自定义角色数据,比如指令类型编号 254 | 255 | 2016-6-22 周三 256 | ============================== 257 | 考虑指令修改逻辑复杂性,暂时放下,先实现指令插入和删除功能。 258 | 因此,每个指令加入到指令序列有两种模式(追加和插入,加上修改其实为三种模式) 259 | 选中指令行,单击插入会改变操作状态,插入操作执行后回到追加模式。 260 | 如果用户单击插入改变模式,但是放弃插入,如何回到追加模式呢? 261 | 插入按钮增加一个取消操作模式,插入操作具体流程是: 262 | 未选中指令行 - 弹出对话框提示“未选中行” 263 | 选中指令行 - 弹出对话框提示“插入到当前行” 264 | 问题来了: 265 | 用户进入插入模式后如何退出,否则无法回到默认追加模式。 266 | 267 | 专注实现绝对位置运行指令的插入、移动和修改功能,其他指令可以借鉴。 268 | 首先对指令序列操作进行抽象,提高代码重用性和可读性。 269 | 270 | 271 | 272 | 2016-6-24 周五 273 | ================================= 274 | 程序文件json格式定义 275 | { 276 | title: 277 | content: 278 | params: [] 279 | data: 280 | } 281 | 282 | 2016-6-25 周六 283 | ================================= 284 | 早上7点开始,除了吃饭、午睡,基本上在思考和编码,大脑高负荷运转。 285 | 我在挑战自己的脑力、注意力、以及耐力的极限。 286 | 之前一直想却没做的代码重构,比如单指令和指令序列两个类的封装。 287 | 单指令包括类型、交互创建和json格式数据生成。 288 | 指令序列包括追加、插入、删除操作,文件读取和写入操作。 289 | 290 | 光是插入(鼠标选中行行前插入)和删除指令就够烧脑的。 291 | 292 | 2016-6-26 周日 293 | ================================ 294 | 项目开发到现在才明白关键工作是开发一套编码和编译系统。 295 | 编码是给人看的;编译是给机器看的(也可能是给人看的)。 296 | 比如,c代码给程序员看,编译成汇编代码人还是看得懂,再编译成机器码计算机才可能看懂。 297 | 298 | 新分支可以是开发版,也可以时稳定版,宗旨是隔离稳定代码与测试代码 299 | 目的不言自明,稳定版可以随时修复bug,不会影响开发版;开发版可以继续 300 | 向未知前行不至于影响发布的稳定版。 301 | 302 | 指令序列类似于汇编代码: 303 | mov 100 (绝对位置执行至100) 304 | add 100 (相对运行100,相当于绝对运行至200) 305 | oper 1,0 (1号参数值++) 306 | cmp 1,0,1,1 (1号参数值大于1时跳转至1行) 307 | 插入或删除行,会导致相对运行的基准和跳转行发生变化,具体如何变化需要编译器根据上下文判断。 308 | 309 | 编译过程就是根据通讯协议组成协议数据,然后发送。 310 | 311 | 目前的开发思路是默认指令行参数固定(因为不支持修改)所以指令数据也是现场可以编译的。 312 | 1 mov 100 313 | 2 add 200 314 | 3 add 100 315 | 4 add 400 316 | 5 mov 200 317 | 6 jmp 2 318 | === edit === 319 | 1 mov 100 320 | 2 add 200 321 | 3 add 100 322 | 4 mov 400 323 | 5 add 100 324 | 6 mov 200 325 | 7 jmp 2 326 | === compile === 327 | 1 mov 100 328 | 2 mov 300 329 | 3 mov 400 330 | 4 mov 400 331 | 5 mov 600 332 | 6 mov 200 333 | 7 jmp 2 334 | 相对运行均转成绝对运行 335 | 336 | 2016-6-30 周四 337 | ===================== 338 | 两个创意: 339 | 每条指令由人理解的字符组成,指令代码和参数组成; 340 | 根据模型返回行数,可以知道对应哪一行,即可知道行的指令类型和参数组成。 341 | 342 | 343 | 2016-7-1 周五 0:04 344 | ===================== 345 | 预期文本格式的程序写入貌似搞定,读取程序文本貌似行不通,各种bug,这里肯定是高风险的地方, 346 | 能不能校验一些非预期的字符,并处理得当。目前是严格按照预想的文本格式都无法正确读取程序行。 347 | 348 | 2016-7-20 周三 22:49 349 | ====================== 350 | 开发经验总结 351 | 不同功能模块采用专用计数器或其他属性,避免逻辑相互纠缠 352 | 静态变量操作需要静态方法 353 | 354 | 实现功能 355 | 下载时生成指令行数据, 356 | 选中行删除指令 357 | 选中行之前插入指令 358 | 359 | 预想实现功能 360 | 选中行修改指令 361 | 362 | bug 363 | 导入程序,关闭程序时崩溃 364 | 365 | 2016-8-2 周二 366 | ======================== 367 | 指令与指令集的重构工作已经完成,只是指令行修改功能迟迟没有实现。 368 | 之前将指令新增分为三种模式: 369 | 追加 370 | 修改 371 | 插入 372 | 其中,追加和插入已经实现,修改没有,设想是 373 | 用户选中指令行,左侧工具锁定对应指令及其参数,点“修改”进入修改模式, 374 | 用户修改参数后,单击“确定”修改选中行指令。 375 | -------------------------------------------------------------------------------- /doc/上位机程序开发文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/上位机程序开发文档.docx -------------------------------------------------------------------------------- /doc/主界面-20160508.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/主界面-20160508.jpg -------------------------------------------------------------------------------- /doc/主界面设计.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/主界面设计.png -------------------------------------------------------------------------------- /doc/使用说明书 - v2.0.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/使用说明书 - v2.0.docx -------------------------------------------------------------------------------- /doc/使用说明书 - v2.1.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/使用说明书 - v2.1.docx -------------------------------------------------------------------------------- /doc/指令列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/指令列表.png -------------------------------------------------------------------------------- /doc/测试-20160626.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/测试-20160626.jpg -------------------------------------------------------------------------------- /doc/通信协议-20160409.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160409.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160411.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160411.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160413.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160413.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160416.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160416.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160423.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160423.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160507.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160507.xlsx -------------------------------------------------------------------------------- /doc/通信协议-20160709.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通信协议-20160709.xlsx -------------------------------------------------------------------------------- /doc/通讯协议定义.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/doc/通讯协议定义.txt -------------------------------------------------------------------------------- /src/command.cpp: -------------------------------------------------------------------------------- 1 | #include "command.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "configdialog.h" 8 | 9 | Command::Command(int a, double b) 10 | { 11 | alpha = a; 12 | beta = b; 13 | } 14 | 15 | Command::Command(int *param, CMDTYPE type) : 16 | mpos(0), mp(0) 17 | { 18 | mType = type; 19 | 20 | quint8 buf[NUMBER_CMD]; 21 | 22 | switch (type) { 23 | case ABS://绝对运行 24 | abs(buf, param); 25 | break; 26 | case RELA://相对运行 27 | rela(buf, param); 28 | break; 29 | case SPD://设置速度 30 | spd(buf, param); 31 | break; 32 | case OPER: 33 | parse(buf, param, OPERATEPARAM); 34 | break; 35 | case DELAY: 36 | parse(buf, param, DELAY_CMD); 37 | break; 38 | case JMP: 39 | parse(buf, param, JMP_CMD); 40 | break; 41 | case CMP: 42 | parse(buf, param, CMP_CMD); 43 | break; 44 | case IOJMP: 45 | parse(buf, param, IOJUMP_CMD); 46 | break; 47 | case SETOUT: 48 | parse(buf, param, SETOUT_CMD); 49 | break; 50 | case INPUT: 51 | parse(buf, param, INPUT_CMD); 52 | break; 53 | case STOP: 54 | parse(buf, param, EMSTOP_CMD); 55 | break; 56 | case HEAD: 57 | parse(buf, param, CMDBATCHHEAD);//指令头部 58 | break; 59 | case HOME: 60 | parse(buf, param, HOME_CMD); 61 | break; 62 | default: 63 | break; 64 | } 65 | } 66 | 67 | void Command::pp() 68 | { 69 | qDebug() << QString("[alpha %1, beta %2]").arg(alpha).arg(beta); 70 | } 71 | //文件读取 72 | Command::Command(QJsonArray &arr, int type) : 73 | mpos(0), mp(0) 74 | { 75 | //params = param; 76 | mType = (CMDTYPE)type; 77 | quint8 buf[NUMBER_CMD]; 78 | 79 | switch (type) { 80 | case ABS://绝对运行 81 | fabs(buf, arr); 82 | break; 83 | case RELA://相对运行 84 | //parse(buf, arr, ABS_MOVE_CMD); 85 | frela(buf, arr); 86 | break; 87 | case SPD://设置速度 88 | //parse(buf, arr, SETMOVESPCMD); 89 | fspd(buf, arr); 90 | break; 91 | case OPER: 92 | parse(buf, arr, OPERATEPARAM); 93 | break; 94 | case DELAY: 95 | parse(buf, arr, DELAY_CMD); 96 | break; 97 | case JMP: 98 | parse(buf, arr, JMP_CMD); 99 | break; 100 | case CMP: 101 | parse(buf, arr, CMP_CMD); 102 | break; 103 | case IOJMP: 104 | parse(buf, arr, IOJUMP_CMD); 105 | break; 106 | case SETOUT: 107 | parse(buf, arr, SETOUT_CMD); 108 | break; 109 | case INPUT: 110 | parse(buf, arr, INPUT_CMD); 111 | break; 112 | default: 113 | break; 114 | } 115 | } 116 | 117 | Command::CMDTYPE Command::type() 118 | { 119 | return mType; 120 | } 121 | 122 | void Command::abs(quint8 *buf, int *param) 123 | { 124 | quint8 bufID[NUMBER_ID]; 125 | quint8 bufData[NUMBER_DA]; 126 | 127 | ps.clear(); 128 | convert(bufID, param[0], NUMBER_ID); //param[0] = id 129 | ps.append(param[0]); 130 | ps.append(param[1]); 131 | ps.append(param[2]); 132 | mp = param[1]; 133 | mpos = param[2]; 134 | 135 | convert(bufData, mpos*alpha, NUMBER_DA); 136 | buf[0] = bufID[0]; 137 | buf[1] = bufID[1]; 138 | buf[2] = ABS_MOVE_CMD; 139 | buf[3] = 0x01; 140 | buf[4] = 0x00; 141 | buf[5] = bufData[0]; 142 | buf[6] = bufData[1]; 143 | buf[7] = bufData[2]; 144 | buf[8] = bufData[3]; 145 | buf[9] = 0x00; 146 | 147 | array2qa(qa, buf, NUMBER_CMD); 148 | } 149 | 150 | void Command::rela(quint8 *buf, int *param) 151 | { 152 | quint8 bufID[NUMBER_ID]; 153 | quint8 bufData[NUMBER_DA]; 154 | 155 | convert(bufID, param[0], NUMBER_ID); //param[0] = id 156 | ps.clear(); 157 | ps.append(param[0]); 158 | ps.append(param[1]); 159 | ps.append(param[2]); 160 | 161 | mp = param[1]; 162 | mpos = param[2]; //pos + base 163 | 164 | convert(bufData, mp*alpha, NUMBER_DA); 165 | buf[0] = bufID[0]; 166 | buf[1] = bufID[1]; 167 | buf[2] = REL_MOVE_CMD; 168 | buf[3] = 0x01; 169 | buf[4] = 0x00; 170 | buf[5] = bufData[0]; 171 | buf[6] = bufData[1]; 172 | buf[7] = bufData[2]; 173 | buf[8] = bufData[3]; 174 | buf[9] = 0x00; 175 | 176 | array2qa(qa, buf, NUMBER_CMD); 177 | } 178 | 179 | void Command::spd(quint8 *buf, int *param) 180 | { 181 | quint8 bufID[NUMBER_ID]; 182 | quint8 bufData[NUMBER_DA]; 183 | 184 | convert(bufID, param[0], NUMBER_ID); //param[0] = id 185 | ps.clear(); 186 | ps.append(param[0]); 187 | ps.append(param[1]); 188 | 189 | int val = param[1] * beta; 190 | 191 | convert(bufData, val, NUMBER_DA); 192 | buf[0] = bufID[0]; 193 | buf[1] = bufID[1]; 194 | buf[2] = SETMOVESPCMD; 195 | buf[3] = 0x01; 196 | buf[4] = 0x00; 197 | buf[5] = bufData[0]; 198 | buf[6] = bufData[1]; 199 | buf[7] = bufData[2]; 200 | buf[8] = bufData[3]; 201 | buf[9] = 0x00; 202 | 203 | array2qa(qa, buf, NUMBER_CMD); 204 | } 205 | 206 | void Command::fabs(quint8 *buf, QJsonArray &arr) 207 | { 208 | quint8 bufID[NUMBER_ID]; 209 | quint8 bufData[NUMBER_DA]; 210 | int id = arr[0].toInt(); 211 | mp = arr[1].toInt(); 212 | mpos = arr[2].toInt(); 213 | ps.clear(); 214 | ps.append(id); 215 | ps.append(mp); 216 | ps.append(mpos); 217 | 218 | convert(bufID, id, NUMBER_ID); //param[0] = id 219 | 220 | convert(bufData, mpos*alpha, NUMBER_DA); 221 | buf[0] = bufID[0]; 222 | buf[1] = bufID[1]; 223 | buf[2] = ABS_MOVE_CMD; 224 | buf[3] = 0x01; 225 | buf[4] = 0x00; 226 | buf[5] = bufData[0]; 227 | buf[6] = bufData[1]; 228 | buf[7] = bufData[2]; 229 | buf[8] = bufData[3]; 230 | buf[9] = 0x00; 231 | 232 | array2qa(qa, buf, NUMBER_CMD); 233 | } 234 | 235 | void Command::frela(quint8 *buf, QJsonArray &arr) 236 | { 237 | quint8 bufID[NUMBER_ID]; 238 | quint8 bufData[NUMBER_DA]; 239 | int id = arr[0].toInt(); 240 | mp = arr[1].toInt(); 241 | mpos = arr[2].toInt(); 242 | ps.clear(); 243 | ps.append(id); 244 | ps.append(mp); 245 | ps.append(mpos); 246 | 247 | convert(bufID, id, NUMBER_ID); //param[0] = id 248 | convert(bufData, mp*alpha, NUMBER_DA); 249 | 250 | buf[0] = bufID[0]; 251 | buf[1] = bufID[1]; 252 | buf[2] = REL_MOVE_CMD; 253 | buf[3] = 0x01; 254 | buf[4] = 0x00; 255 | buf[5] = bufData[0]; 256 | buf[6] = bufData[1]; 257 | buf[7] = bufData[2]; 258 | buf[8] = bufData[3]; 259 | buf[9] = 0x00; 260 | 261 | array2qa(qa, buf, NUMBER_CMD); 262 | } 263 | 264 | void Command::fspd(quint8 *buf, QJsonArray &arr) 265 | { 266 | quint8 bufID[NUMBER_ID]; 267 | quint8 bufData[NUMBER_DA]; 268 | int id = arr[0].toInt(); 269 | int lsp = arr[1].toInt(); 270 | ps.clear(); 271 | ps.append(id); 272 | ps.append(lsp); 273 | 274 | convert(bufID, id, NUMBER_ID); //param[0] = id 275 | convert(bufData, lsp*beta, NUMBER_DA); 276 | 277 | buf[0] = bufID[0]; 278 | buf[1] = bufID[1]; 279 | buf[2] = SETMOVESPCMD; 280 | buf[3] = 0x01; 281 | buf[4] = 0x00; 282 | buf[5] = bufData[0]; 283 | buf[6] = bufData[1]; 284 | buf[7] = bufData[2]; 285 | buf[8] = bufData[3]; 286 | buf[9] = 0x00; 287 | 288 | array2qa(qa, buf, NUMBER_CMD); 289 | } 290 | 291 | void Command::parse(quint8 *buf, int *param, int def) 292 | { 293 | 294 | quint8 bufID[NUMBER_ID]; 295 | quint8 bufData[NUMBER_DA]; 296 | quint8 bufLow[NUMBER_LOW]; 297 | quint8 bufHigh[NUMBER_HIGH]; 298 | 299 | convert(bufID, param[0], NUMBER_ID); //param[0] = id 300 | ps.clear(); 301 | ps.append(param[0]); 302 | 303 | switch (def) { 304 | case HOME_CMD: 305 | ps.append(param[1]); 306 | mp = param[1]; 307 | mpos = 0; 308 | buf[0] = bufID[0]; 309 | buf[1] = bufID[1]; 310 | buf[2] = def; 311 | buf[3] = 0x01; 312 | buf[4] = 0x00; 313 | buf[5] = 0x00; 314 | buf[6] = 0x00; 315 | buf[7] = 0x00; 316 | buf[8] = 0x00; 317 | buf[9] = 0x00; 318 | break; 319 | case DELAY_CMD: //2 320 | case EMSTOP_CMD: 321 | case CMDBATCHHEAD: 322 | ps.append(param[1]); 323 | convert(bufData, param[1], NUMBER_DA); 324 | buf[0] = bufID[0]; 325 | buf[1] = bufID[1]; 326 | buf[2] = def; 327 | buf[3] = 0x01; 328 | buf[4] = 0x00; 329 | buf[5] = bufData[0]; 330 | buf[6] = bufData[1]; 331 | buf[7] = bufData[2]; 332 | buf[8] = bufData[3]; 333 | buf[9] = 0x00; 334 | //qDebug() << "stop " << param[1]; 335 | break; 336 | case OPERATEPARAM: //3 337 | ps.append(param[1]); 338 | ps.append(param[2]); 339 | convert(bufData, param[1]+1, NUMBER_DA); 340 | buf[0] = bufID[0]; 341 | buf[1] = bufID[1]; 342 | buf[2] = def; 343 | buf[3] = param[2]; 344 | buf[4] = 0x00; 345 | buf[5] = bufData[0]; 346 | buf[6] = bufData[1]; 347 | buf[7] = bufData[2]; 348 | buf[8] = bufData[3]; 349 | buf[9] = 0x00; 350 | break; 351 | case INPUT_CMD: //4 352 | case SETOUT_CMD: 353 | ps.append(param[1]); 354 | ps.append(param[2]); 355 | ps.append(param[3]); 356 | convert(bufLow, param[1], NUMBER_LOW); 357 | convert(bufHigh, param[2], NUMBER_HIGH); 358 | buf[0] = bufID[0]; 359 | buf[1] = bufID[1]; 360 | buf[2] = def; 361 | buf[3] = param[3]; 362 | buf[4] = 0x00; 363 | buf[5] = bufLow[0]; 364 | buf[6] = bufLow[1]; 365 | buf[7] = bufHigh[0]; 366 | buf[8] = bufHigh[1]; 367 | buf[9] = 0x00; 368 | break; 369 | case JMP_CMD: //4 370 | case IOJUMP_CMD: 371 | ps.append(param[1]); 372 | ps.append(param[2]); 373 | ps.append(param[3]); 374 | convert(bufLow, param[1], NUMBER_LOW); 375 | convert(bufHigh, param[2]-1, NUMBER_HIGH); //下位机0行开始 376 | buf[0] = bufID[0]; 377 | buf[1] = bufID[1]; 378 | buf[2] = def; 379 | buf[3] = param[3]; 380 | buf[4] = 0x00; 381 | buf[5] = bufLow[0]; 382 | buf[6] = bufLow[1]; 383 | buf[7] = bufHigh[0]; 384 | buf[8] = bufHigh[1]; 385 | buf[9] = 0x00; 386 | break; 387 | case CMP_CMD: //5 388 | ps.append(param[1]); 389 | ps.append(param[2]); 390 | ps.append(param[3]); 391 | ps.append(param[4]); 392 | convert(bufLow, param[1], NUMBER_LOW); 393 | convert(bufHigh, param[2]-1, NUMBER_HIGH); //下位机0行开始 394 | buf[0] = bufID[0]; 395 | buf[1] = bufID[1]; 396 | buf[2] = def; 397 | buf[3] = param[3]; 398 | buf[4] = param[4]+1; 399 | buf[5] = bufLow[0]; 400 | buf[6] = bufLow[1]; 401 | buf[7] = bufHigh[0]; 402 | buf[8] = bufHigh[1]; 403 | buf[9] = 0x00; 404 | break; 405 | default: 406 | break; 407 | } 408 | 409 | array2qa(qa, buf, NUMBER_CMD); 410 | //qDebug() << qa.toHex(); 411 | } 412 | 413 | void Command::parse(quint8 *buf, QJsonArray &arr, int def) 414 | { 415 | 416 | quint8 bufID[NUMBER_ID]; 417 | quint8 bufData[NUMBER_DA]; 418 | quint8 bufLow[NUMBER_LOW]; 419 | quint8 bufHigh[NUMBER_HIGH]; 420 | 421 | int id = arr[0].toInt(); 422 | convert(bufID, id, NUMBER_ID); //param[0] = id 423 | ps.clear(); 424 | ps.append(id); 425 | 426 | switch (def) { 427 | case HOME_CMD: 428 | ps.append(arr[1].toInt()); 429 | mp = ps.at(1); 430 | mpos = 0; 431 | buf[0] = bufID[0]; 432 | buf[1] = bufID[1]; 433 | buf[2] = def; 434 | buf[3] = 0x01; 435 | buf[4] = 0x00; 436 | buf[5] = 0x00; 437 | buf[6] = 0x00; 438 | buf[7] = 0x00; 439 | buf[8] = 0x00; 440 | buf[9] = 0x00; 441 | break; 442 | case DELAY_CMD: 443 | //int val = arr[1].toInt(); 444 | ps.append(arr[1].toInt()); 445 | convert(bufData, arr[1].toInt(), NUMBER_DA); 446 | buf[0] = bufID[0]; 447 | buf[1] = bufID[1]; 448 | buf[2] = def; 449 | buf[3] = 0x01; 450 | buf[4] = 0x00; 451 | buf[5] = bufData[0]; 452 | buf[6] = bufData[1]; 453 | buf[7] = bufData[2]; 454 | buf[8] = bufData[3]; 455 | buf[9] = 0x00; 456 | break; 457 | case OPERATEPARAM: //3 458 | //int op1 = arr[1].toInt(); 459 | //int op2 = arr[2].toInt(); 460 | ps.append(arr[1].toInt()); 461 | ps.append(arr[2].toInt()); 462 | convert(bufData, arr[1].toInt(), NUMBER_DA); 463 | buf[0] = bufID[0]; 464 | buf[1] = bufID[1]; 465 | buf[2] = def; 466 | buf[3] = arr[2].toInt(); 467 | buf[4] = 0x00; 468 | buf[5] = bufData[0]; 469 | buf[6] = bufData[1]; 470 | buf[7] = bufData[2]; 471 | buf[8] = bufData[3]; 472 | buf[9] = 0x00; 473 | break; 474 | case JMP_CMD://4 475 | case IOJUMP_CMD: 476 | //int jmp1 = arr[1].toInt(); 477 | //int jmp2 = arr[2].toInt()-1; 478 | //int jmp3 = arr[3].toInt(); 479 | ps.append(arr[1].toInt()); 480 | ps.append(arr[2].toInt()-1); 481 | ps.append(arr[3].toInt()); 482 | convert(bufLow, arr[1].toInt(), NUMBER_LOW); 483 | convert(bufHigh, arr[2].toInt()-1, NUMBER_HIGH); 484 | buf[0] = bufID[0]; 485 | buf[1] = bufID[1]; 486 | buf[2] = def; 487 | buf[3] = arr[3].toInt(); 488 | buf[4] = 0x00; 489 | buf[5] = bufLow[0]; 490 | buf[6] = bufLow[1]; 491 | buf[7] = bufHigh[0]; 492 | buf[8] = bufHigh[1]; 493 | buf[9] = 0x00; 494 | break; 495 | case INPUT_CMD: 496 | case SETOUT_CMD: 497 | //int io1 = arr[1].toInt(); 498 | //int io2 = arr[2].toInt(); 499 | //int io3 = arr[3].toInt(); 500 | ps.append(arr[1].toInt()); 501 | ps.append(arr[2].toInt()); 502 | ps.append(arr[3].toInt()); 503 | convert(bufLow, arr[1].toInt(), NUMBER_LOW); 504 | convert(bufHigh, arr[2].toInt(), NUMBER_HIGH); 505 | buf[0] = bufID[0]; 506 | buf[1] = bufID[1]; 507 | buf[2] = def; 508 | buf[3] = arr[3].toInt(); 509 | buf[4] = 0x00; 510 | buf[5] = bufLow[0]; 511 | buf[6] = bufLow[1]; 512 | buf[7] = bufHigh[0]; 513 | buf[8] = bufHigh[1]; 514 | buf[9] = 0x00; 515 | break; 516 | case CMP_CMD: //5 517 | //int cmp1 = arr[1].toInt(); 518 | //int cmp2 = arr[2].toInt()-1; 519 | //int cmp3 = arr[3].toInt(); 520 | //int cmp4 = arr[4].toInt(); 521 | ps.append(arr[1].toInt()); 522 | ps.append(arr[2].toInt()-1); 523 | ps.append(arr[3].toInt()); 524 | ps.append(arr[4].toInt()); 525 | convert(bufLow, arr[1].toInt(), NUMBER_LOW); 526 | convert(bufHigh, arr[2].toInt()-1, NUMBER_HIGH); 527 | buf[0] = bufID[0]; 528 | buf[1] = bufID[1]; 529 | buf[2] = def; 530 | buf[3] = arr[3].toInt(); 531 | buf[4] = arr[4].toInt(); 532 | buf[5] = bufLow[0]; 533 | buf[6] = bufLow[1]; 534 | buf[7] = bufHigh[0]; 535 | buf[8] = bufHigh[1]; 536 | buf[9] = 0x00; 537 | break; 538 | default: 539 | break; 540 | } 541 | 542 | array2qa(qa, buf, NUMBER_CMD); 543 | } 544 | 545 | Command::~Command() 546 | { 547 | //delete config; 548 | } 549 | 550 | 551 | QByteArray Command::data() const 552 | { 553 | 554 | return qa; 555 | } 556 | 557 | void Command::convert(quint8 *buf, int data, int size) 558 | { 559 | for(int i=0; i> (8*i); 561 | } 562 | 563 | void Command::array2qa(QByteArray &data, quint8 *buf, int size) 564 | { 565 | for(int i=0; i 5 | //#include 6 | /** 7 | * @brief 指令基类 8 | */ 9 | 10 | #define ABS_MOVE_CMD 0x01 //绝对运动 11 | #define REL_MOVE_CMD 0x02 //相对运动 12 | #define SETMOVESPCMD 0x03 //目标速度 13 | 14 | #define OPERATEPARAM 0x31 //操作参数命令 1)++ 2)-- 15 | #define JMP_CMD 0x32 //无条件跳转 16 | #define CMP_CMD 0x33 //有条件跳转 1)> 2)== 3< 17 | #define IOJUMP_CMD 0x34 //IO条件跳转 0-低电平 1-高电平 仅包括1-4号端口 18 | #define DELAY_CMD 0x35 //延时等待单位毫秒 19 | 20 | #define SETOUT_CMD 0x40 //设置输出IO端口值 21 | #define INPUT_CMD 0x41 //输入IO端口等待指令 22 | 23 | #define SETACCDURCMD 0xa1 //设置加速时间(单位ms) 24 | #define SETDECDURCMD 0xa2 //设置减速时间(单位ms) 25 | #define SETPOSMAXPOS 0xa3 //设置正向最大允许位置(单位mm) 26 | #define SETNEGMAXPOS 0xa4 //设置负向最大允许位置(单位mm) 27 | #define SETPLUSCTRLT 0xa5 //设置脉冲控制方式,0x01--外部脉冲控制; 其他:内部脉冲控制 28 | #define SETCODELOGDI 0xa6 //设置编码器逻辑方向 1-正向 0-负向 29 | #define SETSERBAUDRT 0xa7 //RS485波特率 30 | #define SETCANBAUDRT 0xa8 //CAN波特率 31 | #define SETDEVICEID 0xa9 //设备ID - CAN ID 32 | #define SETMOTORDIRE 0xaa //电机逻辑正方向 33 | 34 | #define SETMOTDIVCMD 0xb1 //设置电机细分 1,2,4,8,32,64,128,256 35 | #define SETCUGEARCMD 0xb2 //设置电机电流档位 1-32 36 | #define SETREFVOLCMD 0xb3 //设置参考电压 0 - 低 1 - 高 37 | #define SETSMARTCURR 0xb4 //设置智能电流控制值 0 - 设置电流值1/2; 1 - 设置电流值1/4 38 | 39 | #define BATCHCONFCMD 0xca //配置下载 40 | #define CMDBATCHHEAD 0xcd //指令下载 41 | 42 | #define EMSTOP_CMD 0x0f //设备停止 43 | 44 | #define NUMBER_ID 0x02 45 | #define NUMBER_DA 0x04 46 | #define NUMBER_CMD 0x0a 47 | #define NUMBER_HIGH 0x02 48 | #define NUMBER_LOW 0x02 49 | 50 | /* 51 | typedef struct { 52 | quint8 id[2]; //命令ID 53 | quint8 master; //命令码 54 | quint8 slave; //子命令 55 | quint8 reserve; //保留 56 | quint8 data[4]; //数据 57 | quint8 check; //校验 58 | } Cmd; 59 | */ 60 | 61 | class QJsonArray; 62 | class Command 63 | { 64 | public: 65 | enum CMDTYPE { 66 | ABS, RELA, SPD, OPER, JMP, CMP, IOJMP, DELAY, SETOUT, INPUT, STOP, HEAD 67 | }; 68 | explicit Command(int a, double b); 69 | 70 | Command(int *param, CMDTYPE type); 71 | Command(QJsonArray &arr, int type); 72 | 73 | //Command(QByteArray ¶m, CMDTYPE type); 74 | ~Command(); 75 | 76 | 77 | QByteArray data() const; //指令转换为字符数据 78 | Command::CMDTYPE type(); 79 | QJsonArray array() const; 80 | void pp(); 81 | 82 | long position(); 83 | long pos(); 84 | 85 | private: 86 | //void init(int alpha, double beta); //初始化参数 87 | 88 | void parse(quint8 *buf, int *param, int def); 89 | void parse(quint8 *buf, QJsonArray &arr, int def); 90 | 91 | void convert(quint8 *buf, int data, int size); //int -> quint8[4] 92 | void array2qa(QByteArray &data, quint8 *buf, int size); //quint8[4] -> QByteArray 93 | 94 | void abs(quint8 *buf, int *param); 95 | void rela(quint8 *buf, int *param); 96 | void spd(quint8 *buf, int *param); 97 | 98 | void fabs(quint8 *buf, QJsonArray &arr); 99 | void frela(quint8 *buf, QJsonArray &arr); 100 | void fspd(quint8 *buf, QJsonArray &arr); 101 | 102 | private: 103 | //quint8 array[NUMBER_CMD]; 104 | //ConfigDialog *config; 105 | QByteArray qa; 106 | CMDTYPE mType; 107 | //int *params; 108 | long mpos; 109 | long mp; 110 | QList ps; //参数列表 111 | }; 112 | 113 | #endif // COMMAND_H 114 | -------------------------------------------------------------------------------- /src/commanditemlist.cpp: -------------------------------------------------------------------------------- 1 | #include "commanditemlist.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | CommandItemList::CommandItemList(QObject *parent) : 12 | QObject(parent), row(0), rows(0), line(0), position(0) 13 | { 14 | 15 | model = new QStandardItemModel(0, 2, parent); 16 | model->setHeaderData(0, Qt::Horizontal, tr("指令类型")); 17 | model->setHeaderData(1, Qt::Horizontal, tr("指令内容")); 18 | 19 | } 20 | 21 | CommandItemList::~CommandItemList() 22 | { 23 | delete model; 24 | } 25 | 26 | void CommandItemList::setRowData(int arow, Command &cmd, QStringList &alist) 27 | { 28 | model->insertRow(arow, QModelIndex()); 29 | model->setData(model->index(arow, 0), alist.at(0), Qt::DisplayRole); 30 | model->setData(model->index(arow, 1), alist.at(1), Qt::DisplayRole); 31 | model->setData(model->index(arow, 0), cmd.type(), Qt::UserRole); 32 | model->setData(model->index(arow, 1), cmd.type(), Qt::UserRole); 33 | } 34 | 35 | //追加指令 36 | void CommandItemList::append(Command &cmd, QStringList &list) 37 | { 38 | 39 | setRowData(row, cmd, list); 40 | cmd_list.append(cmd); 41 | lists.append(list); 42 | int type = cmd.type(); 43 | if (type == Command::ABS) { 44 | position = cmd.position(); 45 | } 46 | if (type == Command::RELA) { 47 | position = cmd.position(); 48 | } 49 | if (type == Command::HOME) { 50 | position = 0; 51 | } 52 | moves.append(cmd.pos()); 53 | 54 | 55 | //qDebug() << tr("绝对位置 -- %1 row -- %2").arg(position).arg(row+1); 56 | //qDebug() << tr("当前指令 ") << cmd.data().toHex(); 57 | 58 | row++; 59 | rows++; 60 | 61 | } 62 | 63 | //删除 back to begin 64 | void CommandItemList::del() 65 | { 66 | row--; 67 | rows--; 68 | 69 | model->removeRow(row, QModelIndex()); 70 | cmd_list.removeAt(row); 71 | lists.removeAt(row); 72 | moves.removeAt(row); 73 | position -= moves.at(row); 74 | 75 | if (row < 0 || rows < 0) { 76 | row = 0; 77 | rows = 0; 78 | } 79 | 80 | //qDebug() << tr("绝对位置 -- %1 行 -- %2").arg(position).arg(row+1); 81 | //qDebug() << tr("删除 %1 行 追加行 %2").arg(line+1).arg(row+1); 82 | } 83 | 84 | //清空 85 | void CommandItemList::clear() 86 | { 87 | model->removeRows(0, rows, QModelIndex()); 88 | cmd_list.clear(); 89 | lists.clear(); 90 | moves.clear(); 91 | line = 0; 92 | row = 0; 93 | rows = 0; 94 | position = 0; 95 | } 96 | 97 | QAbstractItemModel* CommandItemList::pmodel() 98 | { 99 | return model; 100 | } 101 | 102 | int CommandItemList::size() 103 | { 104 | return rows; 105 | } 106 | 107 | QByteArray CommandItemList::qa() const 108 | { 109 | QByteArray qa; 110 | 111 | for (int i=0; i 4 | #include 5 | #include 6 | 7 | CommandLine::CommandLine(QObject *parent) : 8 | QObject(parent), row(0), rows(0) 9 | { 10 | model = new QStandardItemModel(0, 2, parent); 11 | model->setHeaderData(0, Qt::Horizontal, tr("指令类型")); 12 | model->setHeaderData(1, Qt::Horizontal, tr("指令内容")); 13 | 14 | line = new Line(); 15 | lines = new QList; 16 | } 17 | 18 | CommandLine::~CommandLine() 19 | { 20 | delete model; 21 | delete line; 22 | delete lines; 23 | } 24 | 25 | void CommandLine::setRowData(int arow, Line *line) 26 | { 27 | QStringList alist; 28 | line->strlist(alist); 29 | 30 | model->insertRow(arow, QModelIndex()); 31 | model->setData(model->index(arow, 0), alist.at(0), Qt::DisplayRole); 32 | model->setData(model->index(arow, 1), alist.at(1), Qt::DisplayRole); 33 | } 34 | 35 | 36 | bool CommandLine::read(const QString &fileName) 37 | { 38 | QFile file(fileName); 39 | if(!file.open(QIODevice::ReadOnly)) 40 | { 41 | qDebug() << "open program file to read failed."; 42 | return false; 43 | } 44 | 45 | clear(); 46 | //qDebug() << QString("row %1 rows %2").arg(row).arg(rows); 47 | //line = new Line(); 48 | QTextStream in(&file); 49 | while(!in.atEnd()) { 50 | QString str = in.readLine(); 51 | QStringList fields = str.split(" "); 52 | 53 | line = new Line(fields); 54 | //line->print(); 55 | //Line ln(fields); 56 | //ln.print(); 57 | //append(&ln); 58 | append(line); 59 | } 60 | 61 | //qDebug() << "read file success ============="; 62 | file.close(); 63 | return true; 64 | } 65 | 66 | bool CommandLine::write(QString &fileName) const 67 | { 68 | QFile file(fileName); 69 | if(!file.open(QIODevice::WriteOnly)) { 70 | qDebug() << "open program file to write failed."; 71 | return false; 72 | } 73 | 74 | QTextStream out(&file); 75 | for(int i=0; iat(i)->print(str); 79 | 80 | if (i == rows-1) 81 | out << str; 82 | else 83 | out << str << "\r\n"; 84 | } 85 | 86 | file.close(); 87 | return true; 88 | } 89 | 90 | void CommandLine::append(Line *ln) 91 | { 92 | //qDebug() << QString("row %1 rows %2").arg(row).arg(rows); 93 | setRowData(row, ln); 94 | lines->append(ln); 95 | row++; 96 | rows++; 97 | 98 | } 99 | 100 | void CommandLine::insert(Line *ln, int arow) 101 | { 102 | //row = arow; 103 | //qDebug() << QString("插入指令行 %1").arg(arow); 104 | setRowData(arow, ln); 105 | lines->insert(arow, ln); 106 | row++; 107 | rows++; 108 | } 109 | 110 | void CommandLine::edit(Line *ln, int arow) 111 | { 112 | //修改指令行 113 | //先删除再插入 114 | del(arow); 115 | insert(ln, arow); 116 | } 117 | 118 | void CommandLine::del(int arow) 119 | { 120 | //lines.removeAt(arow); 121 | lines->removeAt(arow); 122 | model->removeRow(arow, QModelIndex()); 123 | rows--; 124 | if(rows < 0) 125 | rows = 0; 126 | row = rows; 127 | } 128 | 129 | QAbstractItemModel *CommandLine::pmodel() 130 | { 131 | return model; 132 | } 133 | 134 | Line* CommandLine::getRowData(int arow) const 135 | { 136 | 137 | //lines.value(arow) 138 | //line->print(); 139 | //aline = lines->at(arow); 140 | //line->print(); 141 | //qDebug() << "type -- " << line->type(); 142 | //return lines.value(arow); 143 | //ln = lines->at(arow); 144 | //ln.print(); 145 | //lines->at(arow)->print(); 146 | //line->print(); 147 | return lines->at(arow); 148 | } 149 | 150 | void CommandLine::clear() 151 | { 152 | model->removeRows(0, rows, QModelIndex()); 153 | 154 | lines->clear(); 155 | row = 0; 156 | rows = 0; 157 | } 158 | 159 | int CommandLine::size() const 160 | { 161 | return rows; 162 | } 163 | 164 | int CommandLine::getRow() const 165 | { 166 | return row; 167 | } 168 | 169 | void CommandLine::show() 170 | { 171 | //qDebug() << "size -- " << lines->size(); 172 | qDebug() << QString("row %1 rows %2").arg(row).arg(rows); 173 | } 174 | 175 | QByteArray CommandLine::getCmdData() 176 | { 177 | QByteArray qa; 178 | 179 | for (int i=0; iat(i); 181 | qa.append(line->data()); 182 | } 183 | //qDebug() << qa.toHex(); 184 | return qa; 185 | } 186 | -------------------------------------------------------------------------------- /src/commandline.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMANDLINE_H 2 | #define COMMANDLINE_H 3 | #include 4 | 5 | #include "line.h" 6 | 7 | /** 8 | * @brief 指令组类 9 | */ 10 | class CommandLine : public QObject 11 | { 12 | public: 13 | explicit CommandLine(QObject *parent = 0); 14 | ~CommandLine(); 15 | 16 | void append(Line *ln); 17 | void del(int arow); 18 | void insert(Line *ln, int arow); 19 | void edit(Line *ln, int arow); 20 | void clear(); 21 | 22 | bool read(const QString &fileName); //读取程序文件 23 | bool write(QString &fileName) const; //写入程序文件 24 | 25 | QAbstractItemModel *pmodel(); 26 | 27 | Line* getRowData(int arow) const; 28 | 29 | int size() const; 30 | int getRow() const; 31 | 32 | void show(); 33 | 34 | QByteArray getCmdData(); 35 | 36 | private: 37 | void setRowData(int arow, Line *line); 38 | 39 | private: 40 | QAbstractItemModel *model; 41 | QList *lines; 42 | Line *line; 43 | 44 | int row; //追加指令游标 45 | int rows; 46 | }; 47 | 48 | #endif // COMMANDLINE_H 49 | -------------------------------------------------------------------------------- /src/config/save.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs": [ 3 | { 4 | "name": "acc_time", 5 | "value": 2000 6 | }, 7 | { 8 | "name": "can_baud", 9 | "value": 0 10 | }, 11 | { 12 | "name": "circle_len", 13 | "value": 50 14 | }, 15 | { 16 | "name": "code_type", 17 | "value": 0 18 | }, 19 | { 20 | "name": "count_in", 21 | "value": 5 22 | }, 23 | { 24 | "name": "count_out", 25 | "value": 1 26 | }, 27 | { 28 | "name": "dec_time", 29 | "value": 2000 30 | }, 31 | { 32 | "name": "device_id", 33 | "value": 5 34 | }, 35 | { 36 | "name": "elec_ctrl", 37 | "value": 0 38 | }, 39 | { 40 | "name": "elec_grade", 41 | "value": 2.5 42 | }, 43 | { 44 | "name": "elec_level", 45 | "value": 3 46 | }, 47 | { 48 | "name": "left_limit_config", 49 | "value": 0 50 | }, 51 | { 52 | "name": "left_limit_enable", 53 | "value": 1 54 | }, 55 | { 56 | "name": "max_current", 57 | "value": 4.5 58 | }, 59 | { 60 | "name": "motor_direct", 61 | "value": 0 62 | }, 63 | { 64 | "name": "negative_max", 65 | "value": -1000 66 | }, 67 | { 68 | "name": "pane_type", 69 | "value": 0 70 | }, 71 | { 72 | "name": "plus_type", 73 | "value": 0 74 | }, 75 | { 76 | "name": "positive_max", 77 | "value": 1000 78 | }, 79 | { 80 | "name": "right_limit_config", 81 | "value": 1 82 | }, 83 | { 84 | "name": "right_limit_enable", 85 | "value": 0 86 | }, 87 | { 88 | "name": "rs485_baud", 89 | "value": 4 90 | }, 91 | { 92 | "name": "vol_level", 93 | "value": 0 94 | } 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /src/configdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "configdialog.h" 2 | #include "ui_configdialog.h" 3 | #include "line.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | ConfigDialog::ConfigDialog(QWidget *parent) : 14 | QDialog(parent), 15 | ui(new Ui::ConfigDialog) 16 | { 17 | ui->setupUi(this); 18 | initUI(); 19 | updateConfigs(); 20 | initId = configDatas["device_id"]; 21 | setWindowTitle(tr("系统配置")); 22 | } 23 | 24 | ConfigDialog::~ConfigDialog() 25 | { 26 | delete ui; 27 | } 28 | 29 | int ConfigDialog::level(double base, double cmp) 30 | { 31 | 32 | //根据额定电流值判断电压参考值和电流档位 33 | 34 | int level = 1; 35 | double e = 0.0; 36 | 37 | for(int i=0; i<32; i++) { 38 | //qDebug() << QString("level %1, e %2").arg(level).arg(e); 39 | e = (level*base/32) - cmp; 40 | if(e > 0) 41 | break; 42 | level++; 43 | } 44 | 45 | return level-1; //0-31 46 | 47 | } 48 | 49 | void ConfigDialog::on_writeSerialBtn_clicked() 50 | { 51 | updateConfigs(); //更新配置数据 52 | 53 | int n = currentConfigs.elecLevel; 54 | int temp[] = {1,2,4,8,16,32,64,128,256}; 55 | 56 | int div = temp[n]; //电机细分等级 57 | int param = 200*div / currentConfigs.circleLen; //位移脉冲转换值 58 | 59 | 60 | 61 | quint8 id[2]; 62 | convert(initId, id, 2); 63 | //智能电流控制 64 | quint8 pec[4]; 65 | convert(currentConfigs.elecCtrl,pec,4); 66 | quint8 ec[] = {id[0],id[1],SETSMARTCURR,0x00,0x01,pec[0],pec[1],pec[2],pec[3],0x00}; 67 | QByteArray qEC; 68 | compact(ec, qEC, 10); 69 | 70 | //参考电压边界与电流档位需要额定电流与板型决定 71 | int volLevel = 0; // 0 or 1 72 | int elecLevel = 0; // 0 - 31 73 | double amp = currentConfigs.elecGrade; //额定电流值 74 | double maxCurr = currentConfigs.maxCurr; //最大电流限制 75 | if(amp > CMPCURRLOW) 76 | { 77 | volLevel = 0; //310mv 78 | if(amp > maxCurr) 79 | amp = maxCurr; 80 | elecLevel = level(CMPCURRHIGH, amp); 81 | } else { 82 | volLevel = 1; //165mv 83 | elecLevel = level(CMPCURRLOW, amp); 84 | } 85 | 86 | //参考电压 87 | quint8 pvl[4]; 88 | convert(volLevel, pvl, 4); 89 | quint8 vl[] = {id[0],id[1],SETREFVOLCMD,0x00,0x02,pvl[0],pvl[1],pvl[2],pvl[3],0x00}; 90 | QByteArray qVL; 91 | compact(vl, qVL, 10); 92 | //电流档位 93 | quint8 peg[4]; 94 | convert(elecLevel, peg, 4); 95 | quint8 eg[] = {id[0],id[1],SETCUGEARCMD,0x00,0x03,peg[0],peg[1],peg[2],peg[3],0x00}; 96 | QByteArray qEG; 97 | compact(eg, qEG, 10); 98 | //电机细分等级 99 | quint8 pel[4]; 100 | convert(div, pel, 4); 101 | QByteArray qEL; 102 | quint8 el[] = {id[0],id[1],SETMOTDIVCMD,0x00,0x04,pel[0],pel[1],pel[2],pel[3],0x00}; 103 | compact(el, qEL, 10); 104 | //限位复用功能 105 | QByteArray qLM; 106 | int ll = currentConfigs.leftLimitEn; 107 | int rl = currentConfigs.rightLimitEn; 108 | int lc = currentConfigs.leftLimitCfg; 109 | int rc = currentConfigs.rightLimitCfg; 110 | quint8 lm[] = {id[0],id[1],SETLIMITPOS,0x00,0x05,ll,lc,rl,rc,0x00}; 111 | compact(lm, qLM, 10); 112 | //电机逻辑方向 113 | quint8 pmd[4]; 114 | convert(currentConfigs.motorDirect, pmd, 4); 115 | quint8 md[] = {id[0],id[1],SETMOTORDIRE,0x01,0x06,pmd[0],pmd[1],pmd[2],pmd[3],0x00}; 116 | QByteArray qMD; 117 | compact(md, qMD, 10); 118 | //配置设备ID 119 | quint8 pid[4]; 120 | convert(currentConfigs.deviceId, pid, 4); 121 | QByteArray qID; 122 | quint8 did[] = {id[0],id[1],SETDEVICEID,0x00,0x07,pid[0],pid[1],pid[2],pid[3],0x00}; 123 | compact(did, qID, 10); 124 | //CAN 125 | quint8 pcan[4]; 126 | convert(currentConfigs.canBaud+1, pcan, 4); 127 | QByteArray qCAN; 128 | quint8 can[] = {id[0],id[1],SETCANBAUDRT,0x00,0x08,pcan[0],pcan[1],pcan[2],pcan[3],0x00}; 129 | compact(can, qCAN, 10); 130 | //RS485 131 | quint8 prs[4]; 132 | convert(currentConfigs.rsBaud+1,prs,4); 133 | QByteArray qRS; 134 | quint8 rs[] = {id[0],id[1],SETSERBAUDRT,0x00,0x09,prs[0],prs[1],prs[2],prs[3],0x00}; 135 | compact(rs,qRS,10); 136 | //逻辑编码方向 137 | quint8 pct[4]; 138 | convert(currentConfigs.codeType,pct,4); 139 | QByteArray qCT; 140 | quint8 ct[] = {id[0],id[1],SETCODELOGDI,0x00,0x0a,pct[0],pct[1],pct[2],pct[3],0x00}; 141 | compact(ct,qCT,10); 142 | //脉冲控制方式 143 | quint8 ppt[4]; 144 | convert(currentConfigs.plusType,ppt,4); 145 | QByteArray qPT; 146 | quint8 pt[] = {id[0],id[1],SETPLUSCTRLT,0x00,0x0b,ppt[0],ppt[1],ppt[2],ppt[3],0x00}; 147 | compact(pt,qPT,10); 148 | //负向最大允许位移 149 | quint8 pmn[4]; 150 | convert(param*currentConfigs.maxN,pmn,4); 151 | QByteArray qMN; 152 | quint8 mn[] = {id[0],id[1],SETNEGMAXPOS,0x00,0x0c,pmn[0],pmn[1],pmn[2],pmn[3],0x00}; 153 | compact(mn,qMN,10); 154 | //正向最大允许位移 155 | quint8 pmp[4]; 156 | convert(param*currentConfigs.maxP,pmp,4); 157 | QByteArray qMP; 158 | quint8 mp[] = {id[0],id[1],SETPOSMAXPOS,0x00,0x0d,pmp[0],pmp[1],pmp[2],pmp[3],0x00}; 159 | compact(mp,qMP,10); 160 | //减速时间 161 | quint8 pdt[4]; 162 | convert(currentConfigs.decTime,pdt,4); 163 | QByteArray qDT; 164 | quint8 dt[] = {id[0],id[1],SETDECDURCMD,0x00,0x0e,pdt[0],pdt[1],pdt[2],pdt[3],0x00}; 165 | compact(dt,qDT,10); 166 | //加速时间 167 | quint8 pat[4]; 168 | convert(currentConfigs.accTime,pat,4); 169 | QByteArray qAT; 170 | quint8 at[] = {id[0],id[1],SETACCDURCMD,0x00,0x0f,pat[0],pat[1],pat[2],pat[3],0x00}; 171 | compact(at,qAT,10); 172 | //组合指令数据 173 | QByteArray qHD; 174 | quint8 hd[] = {id[0],id[1],BATCHCONFCMD,0x00,0x01,0x0f,0x00,0x00,0x00,0x00}; 175 | compact(hd,qHD,10); 176 | 177 | QByteArray data; 178 | 179 | data.append(qHD).append(qAT).append(qDT).append(qMP).append(qMN).append(qPT) 180 | .append(qCT).append(qRS).append(qCAN) 181 | .append(qID).append(qMD).append(qLM).append(qEL).append(qEG).append(qVL).append(qEC); 182 | 183 | //data.append(qVL).append(qEG); 184 | //qDebug() << data.append(qLM).toHex(); 185 | 186 | emit sendConfig(data); 187 | 188 | saveConfigFile(Json); 189 | //tip(); 190 | } 191 | 192 | quint32 ConfigDialog::power(int index) 193 | { 194 | quint32 ret = 1; 195 | while(index--) { 196 | ret = ret * 2; 197 | } 198 | return ret; 199 | } 200 | 201 | void ConfigDialog::convert(int data, quint8 *p, int size) 202 | { 203 | for(int i=0; i < size; i++) { 204 | p[i] = data >> (8*i); 205 | } 206 | } 207 | 208 | void ConfigDialog::compact(quint8 *p, QByteArray &data, int size) 209 | { 210 | for(int i=0; ielecContrl->currentIndex(); //智能电流控制 231 | //int volLevel = ui->volLevel->currentIndex(); //参考电压 232 | double elecGrade = ui->elecGrade->value(); //电流档位 233 | int elecLevel = ui->motorLevel->currentIndex(); //电机细分等级 234 | //int codeType = ui->codeLogicDirect->currentIndex(); //逻辑编码方向 235 | int codeType = 0; 236 | int plusType = ui->plusType->currentIndex(); //脉冲控制方式 237 | int maxN = ui->maximumNegative->value(); //负向最大允许位移 238 | int maxP = ui->maximumPositive->value(); //正向最大允许位移 239 | int decTime = ui->servoDecTime->value(); //减速时间 240 | int accTime = ui->servoAccTime->value(); //加速时间 241 | int rsBaud = ui->rs485Baud->currentIndex(); //RS485波特率 242 | int canBaud = ui->canBaud->currentIndex(); //CAN波特率 243 | int deviceID = ui->deviceID->value(); //设备ID 244 | int motorDirect = ui->motorDirect->currentIndex(); //电机逻辑正方向 245 | int ll = ui->leftLimitEnable->currentIndex(); //左限位开关 1-开 0-关 246 | int rl = ui->rightLimitEnable->currentIndex(); //右限位开关 247 | int lc = ui->leftLimitConfig->currentIndex(); //左限位设置 1-高电平有效 0-低电平有效 248 | int rc = ui->rightLimitConfig->currentIndex(); //右限位设置 249 | 250 | //不需下载参数 251 | int circe = ui->circleLen->value(); //电机外轮圆周长 252 | int pane = ui->paneType->currentIndex(); //板型(0 - 57mm 1 - 42mm) 253 | 254 | //保存下载参数 255 | currentConfigs.elecCtrl = elecCtrl; 256 | //currentConfigs.volLevel = volLevel; 257 | currentConfigs.elecGrade = elecGrade; 258 | currentConfigs.elecLevel = elecLevel; 259 | currentConfigs.codeType = codeType; 260 | currentConfigs.plusType = plusType; 261 | currentConfigs.maxN = maxN; 262 | currentConfigs.maxP = maxP; 263 | currentConfigs.decTime = decTime; 264 | currentConfigs.accTime = accTime; 265 | currentConfigs.rsBaud = rsBaud; 266 | currentConfigs.canBaud = canBaud; 267 | currentConfigs.deviceId = deviceID; 268 | currentConfigs.motorDirect = motorDirect; 269 | currentConfigs.circleLen = circe; 270 | currentConfigs.leftLimitEn = ll; 271 | currentConfigs.leftLimitCfg = lc; 272 | currentConfigs.rightLimitEn = rl; 273 | currentConfigs.rightLimitCfg = rc; 274 | 275 | if(pane == 0) { 276 | currentConfigs.pane = SMI57XXXX; 277 | currentConfigs.maxCurr = 4.5; 278 | currentConfigs.countIn = 5; 279 | currentConfigs.countOut = 1; 280 | } else if(pane == 1) { 281 | currentConfigs.pane = SMI42XXXX; 282 | currentConfigs.maxCurr = 3.0; 283 | currentConfigs.countIn = 3; 284 | currentConfigs.countOut = 1; 285 | } 286 | 287 | setData(); 288 | } 289 | 290 | void ConfigDialog::setData() 291 | { 292 | configDatas["elec_ctrl"] = currentConfigs.elecCtrl; 293 | //configDatas["vol_level"] = currentConfigs.volLevel; 294 | configDatas["elec_grade"] = currentConfigs.elecGrade; 295 | configDatas["elec_level"] = currentConfigs.elecLevel; 296 | configDatas["code_type"] = currentConfigs.codeType; 297 | configDatas["plus_type"] = currentConfigs.plusType; 298 | configDatas["negative_max"] = currentConfigs.maxN; 299 | configDatas["positive_max"] = currentConfigs.maxP; 300 | configDatas["dec_time"] = currentConfigs.decTime; 301 | configDatas["acc_time"] = currentConfigs.accTime; 302 | configDatas["rs485_baud"] = currentConfigs.rsBaud; 303 | configDatas["can_baud"] = currentConfigs.canBaud; 304 | configDatas["device_id"] = currentConfigs.deviceId; 305 | configDatas["motor_direct"] = currentConfigs.motorDirect; 306 | configDatas["circle_len"] = currentConfigs.circleLen; 307 | configDatas["max_current"] = currentConfigs.maxCurr; 308 | configDatas["count_out"] = currentConfigs.countOut; 309 | configDatas["count_in"] = currentConfigs.countIn; 310 | configDatas["left_limit_enable"] = currentConfigs.leftLimitEn; 311 | configDatas["right_limit_enable"] = currentConfigs.rightLimitEn; 312 | configDatas["left_limit_config"] = currentConfigs.leftLimitCfg; 313 | configDatas["right_limit_config"] = currentConfigs.rightLimitCfg; 314 | configDatas["pane_type"] = currentConfigs.pane; 315 | } 316 | 317 | ConfigDialog::Configs ConfigDialog::configs() const 318 | { 319 | return currentConfigs; 320 | } 321 | 322 | bool ConfigDialog::saveConfigFile(SaveFormat saveFormat) const 323 | { 324 | QFile saveFile(saveFormat == Json 325 | ? QStringLiteral("save.json") 326 | : QStringLiteral("save.dat")); 327 | if(!saveFile.open(QIODevice::WriteOnly)) { 328 | //qWarning("不能打开文件!"); 329 | return false; 330 | } 331 | 332 | QJsonObject configObject; 333 | write(configObject); 334 | QJsonDocument saveDoc(configObject); 335 | saveFile.write(saveFormat == Json 336 | ? saveDoc.toJson() 337 | : saveDoc.toBinaryData()); 338 | return true; 339 | } 340 | 341 | void ConfigDialog::write(QJsonObject &json) const 342 | { 343 | QJsonArray configArray; 344 | QMapIterator i(configDatas); 345 | while(i.hasNext()) { 346 | i.next(); 347 | QJsonObject obj; 348 | obj["name"] = i.key(); 349 | obj["value"] = i.value(); 350 | configArray.append(obj); 351 | } 352 | 353 | json["configs"] = configArray; 354 | } 355 | 356 | void ConfigDialog::setUI() 357 | { 358 | ui->deviceID->setValue(configDatas["device_id"]); 359 | ui->rs485Baud->setCurrentIndex(configDatas["rs485_baud"]); 360 | ui->canBaud->setCurrentIndex(configDatas["can_baud"]); 361 | ui->elecContrl->setCurrentIndex(configDatas["elec_ctrl"]); 362 | //ui->volLevel->setCurrentIndex(configDatas["vol_level"]); 363 | ui->motorLevel->setCurrentIndex(configDatas["elec_level"]); 364 | //ui->codeLogicDirect->setCurrentIndex(configDatas["code_type"]); 365 | ui->plusType->setCurrentIndex(configDatas["plus_type"]); 366 | ui->elecGrade->setValue(configDatas["elec_grade"]); 367 | ui->maximumNegative->setValue(configDatas["negative_max"]); 368 | ui->maximumPositive->setValue(configDatas["positive_max"]); 369 | ui->servoAccTime->setValue(configDatas["acc_time"]); 370 | ui->servoDecTime->setValue(configDatas["dec_time"]); 371 | ui->circleLen->setValue(configDatas["circle_len"]); 372 | ui->leftLimitEnable->setCurrentIndex(configDatas["left_limit_enable"]); 373 | ui->leftLimitConfig->setCurrentIndex(configDatas["left_limit_config"]); 374 | ui->rightLimitEnable->setCurrentIndex(configDatas["right_limit_enable"]); 375 | ui->rightLimitConfig->setCurrentIndex(configDatas["right_limit_config"]); 376 | ui->paneType->setCurrentIndex(configDatas["pane_type"]); 377 | } 378 | 379 | void ConfigDialog::on_readConfigBtn_clicked() 380 | { 381 | //读取磁盘文件 382 | loadConfigFile(Json); 383 | 384 | setUI(); 385 | } 386 | 387 | bool ConfigDialog::loadConfigFile(SaveFormat saveFormat) 388 | { 389 | QFile loadFile(saveFormat == Json 390 | ? QStringLiteral("save.json") 391 | : QStringLiteral("save.dat")); 392 | 393 | if(!loadFile.open(QIODevice::ReadOnly)) { 394 | //qWarning("不能打开文件!"); 395 | return false; 396 | } 397 | 398 | QByteArray saveData = loadFile.readAll(); 399 | 400 | QJsonDocument loadDoc(saveFormat == Json 401 | ? QJsonDocument::fromJson(saveData) 402 | : QJsonDocument::fromBinaryData(saveData)); 403 | 404 | read(loadDoc.object()); //解析QJsonDocument文件 405 | 406 | return true; 407 | } 408 | 409 | void ConfigDialog::read(const QJsonObject &json) 410 | { 411 | //JSON格式文件解析出来 412 | QJsonArray configArray = json["configs"].toArray(); 413 | 414 | for (int i=0; i < configArray.size(); i++) { 415 | QJsonObject obj = configArray[i].toObject(); 416 | QString name = obj["name"].toString(); 417 | double value = obj["value"].toDouble(); 418 | configDatas.insert(name, value); 419 | } 420 | 421 | } 422 | 423 | void ConfigDialog::initUI() 424 | { 425 | //外部文件不存在,读取资源文件 426 | if(!loadConfigFile(Json)) 427 | { 428 | QFile loadFile(QStringLiteral(":/config/save.json")); 429 | 430 | if(!loadFile.open(QIODevice::ReadOnly)) { 431 | //qWarning("不能打开文件!"); 432 | return; 433 | } 434 | 435 | QByteArray saveData = loadFile.readAll(); 436 | 437 | QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); 438 | 439 | read(loadDoc.object()); //解析QJsonDocument文件 440 | } 441 | 442 | 443 | setUI(); 444 | 445 | } 446 | 447 | void ConfigDialog::initConnect() 448 | { 449 | 450 | } 451 | 452 | void ConfigDialog::tip() 453 | { 454 | QMessageBox::information(this,tr("下载配置参数"),tr("配置参数将下载至控制器生效!")); 455 | } 456 | 457 | void ConfigDialog::on_resetBtn_clicked() 458 | { 459 | QFile loadFile(QStringLiteral(":/config/save.json")); 460 | if(!loadFile.open(QIODevice::ReadOnly)) { 461 | //qWarning("不能打开文件!"); 462 | return; 463 | } 464 | 465 | QByteArray saveData = loadFile.readAll(); 466 | 467 | QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); 468 | read(loadDoc.object()); //解析QJsonDocument文件 469 | 470 | setUI(); 471 | 472 | } 473 | 474 | void ConfigDialog::on_applyBtn_clicked() 475 | { 476 | //配置生效发出配置更改信号 477 | //qDebug() << "emit change config signal"; 478 | int ret = QMessageBox::warning(this, tr("配置参数"), tr("是否确定修改当前参数并立即生效?\n"), 479 | QMessageBox::Ok | QMessageBox::Cancel); 480 | 481 | if(ret == QMessageBox::Ok) { 482 | updateConfigs(); 483 | int changedId = currentConfigs.deviceId; 484 | if (changedId != initId) { 485 | QMessageBox::information(this,tr("提示"),QString(tr("设备ID将被修改为%1").arg(changedId))); 486 | } 487 | emit changeConfigs(); 488 | } else if(ret == QMessageBox::Cancel){ 489 | //恢复配置参数 490 | on_readConfigBtn_clicked(); 491 | return; 492 | } 493 | 494 | 495 | } 496 | -------------------------------------------------------------------------------- /src/configdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGDIALOG_H 2 | #define CONFIGDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define CMPCURRHIGH 6.2 //最大电流档位值(A) 0.31V/0.05Om 9 | #define CMPCURRLOW 3.3 //最小电流档位值(A) 0.165V/0.05Om 10 | 11 | #define SMI57XXXX 0 //SMI57系列控制器 12 | #define SMI42XXXX 1 //SMI42系列控制器 13 | 14 | namespace Ui { 15 | class ConfigDialog; 16 | } 17 | 18 | class ConfigDialog : public QDialog 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | struct Configs { 24 | int elecCtrl; //待机电流 25 | //int volLevel; //参考电压 310mv - 0 165mv - 1 26 | double elecGrade; //额定电流 27 | int elecLevel; //电机细分等级 28 | int codeType; //逻辑编码方向 29 | int plusType; //脉冲方向 30 | int maxN; //负向最大允许位移 31 | int maxP; //正向最大允许位移 32 | int decTime; //减速时间 33 | int accTime; //加速时间 34 | int rsBaud; //RS485波特率 35 | int canBaud; //CAN波特率 36 | int deviceId; //设备ID 37 | int motorDirect; //电机逻辑正方向 0-顺时针,1-逆时针 38 | int circleLen; //外轮圆周长 39 | double maxCurr; //最大电流 40 | int countOut; //输出端口数 41 | int countIn; //输入端口数 42 | int leftLimitEn; //左限位使能 43 | int leftLimitCfg; //左限位设置 44 | int rightLimitEn; //右限位使能int 45 | int rightLimitCfg;//右限位设置 46 | int pane; //控制器类型 47 | }; 48 | 49 | explicit ConfigDialog(QWidget *parent = 0); 50 | ~ConfigDialog(); 51 | void receiveDate(const QByteArray &data); 52 | 53 | enum SaveFormat { 54 | Json, Binary 55 | }; 56 | 57 | bool loadConfigFile(SaveFormat saveFormat); 58 | bool saveConfigFile(SaveFormat saveFormat) const; 59 | 60 | Configs configs() const; 61 | void tip(); //提示重新载入软件 62 | 63 | signals: 64 | void sendConfig(const QByteArray &data); 65 | void changeConfigs(); 66 | 67 | private slots: 68 | void on_writeSerialBtn_clicked(); 69 | 70 | void on_saveConfigBtn_clicked(); 71 | 72 | void on_readConfigBtn_clicked(); 73 | 74 | void on_resetBtn_clicked(); 75 | 76 | void on_applyBtn_clicked(); 77 | 78 | private: 79 | quint32 power(int index); //return 2^index 80 | 81 | void convert(int data, quint8 *p, int size); //convert int to quint8* with size 82 | void compact(quint8 *p, QByteArray &data, int size); //convert quint8* to QByteArray with size 83 | 84 | void read(const QJsonObject &json); //读取json文件 85 | void write(QJsonObject &json) const; //写入json文件 86 | 87 | void data(const Configs *configs, QByteArray &qa); //配置结构转换为QByteArray 88 | 89 | void updateConfigs(); 90 | 91 | int level(double base, double cmp); //计算电流档位 92 | 93 | void setUI(); 94 | void setData(); 95 | 96 | private: 97 | void initUI(); 98 | void initConnect(); 99 | 100 | private: 101 | Ui::ConfigDialog *ui; 102 | QMap configDatas; 103 | Configs currentConfigs; 104 | int initId; 105 | }; 106 | 107 | #endif // CONFIGDIALOG_H 108 | -------------------------------------------------------------------------------- /src/configdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ConfigDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 599 10 | 462 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 22 | 23 | 24 | 控制器配置 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 通讯配置 33 | 34 | 35 | 36 | 30 37 | 38 | 39 | 40 | 41 | 30 42 | 43 | 44 | 45 | 46 | 设备ID 47 | 48 | 49 | 50 | 51 | 52 | 53 | 分为1至32等级 54 | 55 | 56 | 1 57 | 58 | 59 | 1000 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Qt::Vertical 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 1, 2, 4, 8, 16, 32, 64, 128, 256 78 | 79 | 80 | RS485波特率 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 细分等级分别为1, 2, 4, 8, 16, 32, 64, 128, 256 91 | 92 | 93 | false 94 | 95 | 96 | 9600 97 | 98 | 99 | 4 100 | 101 | 102 | 5 103 | 104 | 105 | 106 | 115200 107 | 108 | 109 | 110 | 111 | 57600 112 | 113 | 114 | 115 | 116 | 38400 117 | 118 | 119 | 120 | 121 | 19200 122 | 123 | 124 | 125 | 126 | 9600 127 | 128 | 129 | 130 | 131 | 4800 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | Qt::Vertical 142 | 143 | 144 | 145 | 146 | 147 | 148 | 30 149 | 150 | 151 | 152 | 153 | 1, 2, 4, 8, 16, 32, 64, 128, 256 154 | 155 | 156 | CAN波特率 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 细分等级分别为1, 2, 4, 8, 16, 32, 64, 128, 256 167 | 168 | 169 | false 170 | 171 | 172 | 1000K 173 | 174 | 175 | 5 176 | 177 | 178 | 179 | 1000K 180 | 181 | 182 | 183 | 184 | 500K 185 | 186 | 187 | 188 | 189 | 250K 190 | 191 | 192 | 193 | 194 | 125K 195 | 196 | 197 | 198 | 199 | 100K 200 | 201 | 202 | 203 | 204 | 50K 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 电机配置 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 额定电流(A) 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 正向最大允许位置(mm) 236 | 237 | 238 | 239 | 240 | 241 | 242 | 分为1至32等级 243 | 244 | 245 | 1 246 | 247 | 248 | 1000000 249 | 250 | 251 | 100 252 | 253 | 254 | 1000 255 | 256 | 257 | 258 | 259 | 260 | 261 | 负向最大允许位置(mm) 262 | 263 | 264 | 265 | 266 | 267 | 268 | -1000000 269 | 270 | 271 | 1000000 272 | 273 | 274 | 100 275 | 276 | 277 | 1000 278 | 279 | 280 | 281 | 282 | 283 | 284 | 加速度时间(ms) 285 | 286 | 287 | 288 | 289 | 290 | 291 | 1-99 292 | 293 | 294 | 10000 295 | 296 | 297 | 2000 298 | 299 | 300 | 301 | 302 | 303 | 304 | 减速度时间(ms) 305 | 306 | 307 | 308 | 309 | 310 | 311 | 1-99 312 | 313 | 314 | 10000 315 | 316 | 317 | 2000 318 | 319 | 320 | 321 | 322 | 323 | 324 | 电机圆周长(mm) 325 | 326 | 327 | 328 | 329 | 330 | 331 | 1000 332 | 333 | 334 | 200 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | Qt::Vertical 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 控制器型号 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | SMI57XXXX 361 | 362 | 363 | 364 | 365 | SMI42XXXX 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 待机电流 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | false 387 | 388 | 389 | 1/2电流值 390 | 391 | 392 | 2 393 | 394 | 395 | 396 | 1/2电流值 397 | 398 | 399 | 400 | 401 | 1/4电流值 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 电机逻辑正向 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | false 423 | 424 | 425 | 顺时针 426 | 427 | 428 | 2 429 | 430 | 431 | 432 | 顺时针 433 | 434 | 435 | 436 | 437 | 逆时针 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 1, 2, 4, 8, 16, 32, 64, 128, 256 446 | 447 | 448 | 电机细分等级 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 细分等级分别为1, 2, 4, 8, 16, 32, 64, 128, 256 459 | 460 | 461 | false 462 | 463 | 464 | 1 465 | 466 | 467 | 5 468 | 469 | 470 | 471 | 1 472 | 473 | 474 | 475 | 476 | 2 477 | 478 | 479 | 480 | 481 | 4 482 | 483 | 484 | 485 | 486 | 8 487 | 488 | 489 | 490 | 491 | 16 492 | 493 | 494 | 495 | 496 | 32 497 | 498 | 499 | 500 | 501 | 64 502 | 503 | 504 | 505 | 506 | 128 507 | 508 | 509 | 510 | 511 | 256 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 脉冲方式 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 内部脉冲控制 528 | 529 | 530 | 531 | 532 | 外部脉冲控制 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 限位配置 548 | 549 | 550 | 551 | 552 | 553 | 左限位 554 | 555 | 556 | 557 | 558 | 559 | 560 | 关闭 561 | 562 | 563 | 564 | 565 | 开启 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 低电平有效 575 | 576 | 577 | 578 | 579 | 高电平有效 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | Qt::Vertical 591 | 592 | 593 | 594 | 595 | 596 | 597 | 右限位 598 | 599 | 600 | 601 | 602 | 603 | 604 | 关闭 605 | 606 | 607 | 608 | 609 | 开启 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 低电平有效 619 | 620 | 621 | 622 | 623 | 高电平有效 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 重置配置 644 | 645 | 646 | 647 | 648 | 649 | 650 | 写入配置文件 651 | 652 | 653 | 654 | 655 | 656 | 657 | 读取配置文件 658 | 659 | 660 | 661 | 662 | 663 | 664 | Qt::Horizontal 665 | 666 | 667 | 668 | 40 669 | 20 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 配置生效 678 | 679 | 680 | 681 | 682 | 683 | 684 | 下载 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | -------------------------------------------------------------------------------- /src/console.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #include "console.h" 36 | 37 | #include 38 | 39 | #include 40 | 41 | Console::Console(QWidget *parent) 42 | : QPlainTextEdit(parent) 43 | , localEchoEnabled(false) 44 | { 45 | document()->setMaximumBlockCount(100); 46 | QPalette p = palette(); 47 | p.setColor(QPalette::Base, Qt::black); 48 | p.setColor(QPalette::Text, Qt::green); 49 | setPalette(p); 50 | 51 | } 52 | 53 | void Console::putData(const QByteArray &data) 54 | { 55 | insertPlainText(QString(data)); 56 | 57 | QScrollBar *bar = verticalScrollBar(); 58 | bar->setValue(bar->maximum()); 59 | } 60 | 61 | void Console::setLocalEchoEnabled(bool set) 62 | { 63 | localEchoEnabled = set; 64 | } 65 | 66 | void Console::keyPressEvent(QKeyEvent *e) 67 | { 68 | switch (e->key()) { 69 | case Qt::Key_Backspace: 70 | case Qt::Key_Left: 71 | case Qt::Key_Right: 72 | case Qt::Key_Up: 73 | case Qt::Key_Down: 74 | break; 75 | default: 76 | if (localEchoEnabled) 77 | QPlainTextEdit::keyPressEvent(e); 78 | emit getData(e->text().toLocal8Bit()); 79 | } 80 | } 81 | 82 | void Console::mousePressEvent(QMouseEvent *e) 83 | { 84 | Q_UNUSED(e) 85 | setFocus(); 86 | } 87 | 88 | void Console::mouseDoubleClickEvent(QMouseEvent *e) 89 | { 90 | Q_UNUSED(e) 91 | } 92 | 93 | void Console::contextMenuEvent(QContextMenuEvent *e) 94 | { 95 | Q_UNUSED(e) 96 | } 97 | -------------------------------------------------------------------------------- /src/console.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #ifndef CONSOLE_H 36 | #define CONSOLE_H 37 | 38 | #include 39 | 40 | class Console : public QPlainTextEdit 41 | { 42 | Q_OBJECT 43 | 44 | signals: 45 | void getData(const QByteArray &data); 46 | 47 | public: 48 | explicit Console(QWidget *parent = 0); 49 | 50 | void putData(const QByteArray &data); 51 | 52 | void setLocalEchoEnabled(bool set); 53 | 54 | protected: 55 | virtual void keyPressEvent(QKeyEvent *e); 56 | virtual void mousePressEvent(QMouseEvent *e); 57 | virtual void mouseDoubleClickEvent(QMouseEvent *e); 58 | virtual void contextMenuEvent(QContextMenuEvent *e); 59 | 60 | private: 61 | bool localEchoEnabled; 62 | 63 | }; 64 | 65 | #endif // CONSOLE_H 66 | -------------------------------------------------------------------------------- /src/form.cpp: -------------------------------------------------------------------------------- 1 | #include "form.h" 2 | #include "ui_form.h" 3 | 4 | #include "command.h" 5 | #include "configdialog.h" 6 | #include "line.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | Form::Form(QWidget *parent) : 19 | QWidget(parent), 20 | row(-1), 21 | runLine(-1), 22 | insertLine(-1), 23 | updateLine(-1), 24 | ui(new Ui::Form) 25 | { 26 | ui->setupUi(this); 27 | config = new ConfigDialog; 28 | 29 | int level = config->configs().elecLevel; 30 | int circle = config->configs().circleLen; 31 | int div[] = {1,2,4,8,16,32,64,128,256}; 32 | int deviceId = config->configs().deviceId; 33 | 34 | int alpha = 200 * div[level] / circle; 35 | //double beta = 0.4 * div[level] / circle; // 系数 200*100/50000 36 | double beta = 200 * div[level] / circle; //乘以线速度就是每秒脉冲数,最大值200k 37 | 38 | /* 39 | * 细分为256时,速度设置最大每秒脉冲为400k(否则还是200k不变),实际下发数值(每秒脉冲数)减半 40 | */ 41 | int maxSpd = 200000 / beta; //最大线速度 42 | //qDebug() << QString("level %1 and spd %2").arg(level).arg(maxSpd); 43 | 44 | if (level == 8) { 45 | maxSpd = 400000 / beta; 46 | beta = beta / 2; 47 | } 48 | 49 | //qDebug() << "max spd == " << maxSpd; 50 | ui->setRunSpd->setMaximum(maxSpd); 51 | 52 | initUI(); 53 | initConnect(); 54 | initModel(); 55 | 56 | spd_show(ui->setRunSpd->value()); 57 | 58 | ui->parentToolBox->setCurrentIndex(0); 59 | ui->moveToolBox->setCurrentIndex(0); 60 | 61 | line = new Line(alpha, beta, deviceId); 62 | //line->test(); 63 | //line = new Line; 64 | cl = new CommandLine(this); 65 | 66 | op = APP; 67 | quit = false; 68 | 69 | //connect(config, SIGNAL(changeConfigs()), this, SLOT(updateConfigs())); 70 | } 71 | 72 | Form::~Form() 73 | { 74 | delete ui; 75 | delete config; 76 | delete cl; 77 | delete line; 78 | } 79 | 80 | void Form::about() 81 | { 82 | QMessageBox::about(this, tr("控制器应用程序"),tr("==== V2.2 版应用程序 ===\n ---- 2016-8-2 ----")); 83 | } 84 | 85 | void Form::initUI() 86 | { 87 | int countIn = config->configs().countIn; 88 | ui->jumpParam->setMaximum(countIn); 89 | ui->inputParam->setMaximum(countIn); 90 | 91 | int maxN = config->configs().maxN; 92 | int maxP = config->configs().maxP; 93 | ui->absMoveDistance->setMaximum(maxP); 94 | ui->absMoveDistance->setMinimum(maxN); 95 | ui->relMoveDistance->setMaximum(maxP); 96 | ui->relMoveDistance->setMinimum(maxN); 97 | } 98 | 99 | void Form::initConnect() 100 | { 101 | //connect(ford_timer, SIGNAL(timeout()), this, SLOT(forward())); 102 | connect(ui->setRunSpd, SIGNAL(valueChanged(int)), this, SLOT(spd_show(int))); 103 | connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(tableDoubleClick(QModelIndex))); 104 | connect(ui->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(tableClick(QModelIndex))); 105 | connect(ui->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(showToolBox(QModelIndex))); 106 | } 107 | 108 | void Form::initModel() 109 | { 110 | /* 111 | model = new QStandardItemModel(0, 2, this); 112 | model->setHeaderData(0, Qt::Horizontal, tr("指令类型")); 113 | model->setHeaderData(1, Qt::Horizontal, tr("指令内容")); 114 | */ 115 | 116 | QHeaderView *headerView = ui->tableView->horizontalHeader(); 117 | headerView->setStretchLastSection(true); 118 | 119 | } 120 | 121 | bool Form::saveProgFile(QString fileName) const 122 | { 123 | return cl->write(fileName); 124 | } 125 | 126 | bool Form::loadProgFile(QString fileName) 127 | { 128 | bool ret = cl->read(fileName); 129 | 130 | ui->tableView->setModel(cl->pmodel()); 131 | return ret; 132 | } 133 | /* 134 | void Form::operate(Command &cmd, QStringList &list) 135 | { 136 | switch (op) { 137 | case APP: //默认追加 138 | //qDebug() << "========= APP ==========="; 139 | //指令序列 - 模型 140 | itemList->append(cmd, list); 141 | break; 142 | case EDIT://指令修改 143 | //qDebug() << "========= EDIT ==========="; 144 | break; 145 | case INSE://指令插入 默认前查 146 | //qDebug() << "========= INSE ==========="; 147 | //itemList->insert(cmd, list, mLine); 148 | //mLine++;//选中行递增 149 | break; 150 | default: 151 | break; 152 | } 153 | 154 | ui->tableView->setModel(itemList->pmodel()); 155 | } 156 | */ 157 | void Form::operate(Line *ln) 158 | { 159 | switch (op) { 160 | case APP: //默认追加 161 | //qDebug() << "========= APP ==========="; 162 | //指令序列 - 模型 163 | cl->append(ln); 164 | break; 165 | case EDIT://指令修改 166 | //qDebug() << "========= EDIT ==========="; 167 | break; 168 | case INSE://指令插入 默认前查 169 | //qDebug() << "========= INSE ==========="; 170 | //itemList->insert(cmd, list, mLine); 171 | //mLine++; 172 | break; 173 | default: 174 | break; 175 | } 176 | 177 | ui->tableView->setModel(cl->pmodel()); 178 | } 179 | 180 | void Form::operate(QList pa, CmdType type) 181 | { 182 | line = new Line(pa, type); 183 | 184 | switch (op) { 185 | case APP: //默认追加 186 | cl->append(line); 187 | break; 188 | case EDIT://修改指令参数 189 | cl->edit(line, updateLine); 190 | op = APP; 191 | updateLine = -1; 192 | break; 193 | case INSE://指令插入 默认前查 194 | cl->insert(line, insertLine); 195 | //ui->tableView->selectRow(insertLine); 196 | insertLine++; 197 | break; 198 | default: 199 | break; 200 | } 201 | 202 | ui->tableView->setModel(cl->pmodel()); 203 | //qDebug() << QString("app line %1").arg(cl->getRow()); 204 | //ui->tableView->selectRow(cl->getRow()); 205 | } 206 | 207 | 208 | void Form::on_absAddBtn_clicked() 209 | { 210 | int position = ui->absMoveDistance->value(); 211 | 212 | QList pa; 213 | pa << position; 214 | 215 | operate(pa, POS); 216 | } 217 | 218 | void Form::on_relaAddBtn_clicked() 219 | { 220 | int pos = ui->relMoveDistance->value(); 221 | 222 | QList pa; 223 | pa << pos; 224 | operate(pa, MOV); 225 | } 226 | 227 | void Form::on_setSpdBtn_clicked() 228 | { 229 | int lpd = ui->setRunSpd->value(); //线速度mm/s - 转速 - 每秒脉冲数 230 | 231 | //qDebug() << QString(tr("参数 %1 档位 %2%")).arg(beta).arg(spd); 232 | //线速度转成角速度转成频率 233 | QList pa; 234 | pa << lpd; 235 | 236 | operate(pa, SETSPD); 237 | 238 | } 239 | 240 | void Form::on_delayAddBtn_clicked() 241 | { 242 | int value = ui->delayVal->value(); 243 | 244 | QList pa; 245 | pa << value; 246 | operate(pa, DELAY); 247 | 248 | } 249 | 250 | void Form::on_homeAddBtn_clicked() 251 | { 252 | QList pa; 253 | pa << 0; 254 | operate(pa, HOME); 255 | /* 256 | int base = itemList->pos(); 257 | int pos = 0 - base; //绝对位置的偏移量 258 | 259 | int params[2] = {deviceId, pos}; 260 | Command acmd(params, Command::HOME); 261 | 262 | QStringList list; 263 | list << tr("零点设置指令") << QString(tr("当前位置设置为零点位置")); 264 | 265 | operate(acmd, list); 266 | */ 267 | } 268 | 269 | void Form::on_stepAct_clicked() 270 | { 271 | //cl->show(); 272 | if (runLine == -1) { 273 | QMessageBox::warning(this, tr("警告"), QString(tr("请选中指令行"))); 274 | return; 275 | } 276 | 277 | int limit = cl->size() - 1; 278 | 279 | if(runLine > limit) { 280 | runLine = limit; 281 | } 282 | 283 | ui->tableView->selectRow(runLine); 284 | //qDebug() << QString("run line %1 rows %2").arg(runLine).arg(limit); 285 | //qDebug() << cl->getRowData(runLine)->data().toHex(); 286 | sendData(cl->getRowData(runLine)->data()); 287 | 288 | runLine++; 289 | 290 | } 291 | 292 | void Form::spd_show(int lpd) 293 | { 294 | int circle = config->configs().circleLen; 295 | //int lpd = ui->setRunSpd->value(); 296 | double rps = (double)lpd / circle; 297 | ui->rpsLab->setText(QString(tr("转速:%1 rps(转每秒)")).arg(rps)); 298 | } 299 | 300 | void Form::on_stopAct_clicked() 301 | { 302 | QList pa; 303 | pa << 0; 304 | line = new Line(pa, STOP); 305 | 306 | 307 | //qDebug() << "stop " << stopcmd.data().toHex(); 308 | //emit sendData(stopcmd.data()); 309 | emit sendStop(line->data()); 310 | } 311 | 312 | void Form::on_forwardAct_clicked() 313 | { 314 | QByteArray qa; 315 | QList pa; 316 | pa << cl->size(); 317 | line = new Line(pa, HEAD); 318 | //line->print(); 319 | //qDebug() << cl->size(); 320 | qa.append(line->data()); 321 | qa.append(cl->getCmdData()); 322 | 323 | //qDebug() << qa.toHex(); 324 | emit sendData(qa); 325 | } 326 | 327 | void Form::on_opAddBtn_clicked() 328 | { 329 | int param = ui->opParam->value(); 330 | int opType = ui->opType->currentIndex(); //1-自增 2-自减 331 | 332 | QList pa; 333 | pa << param << opType; 334 | 335 | operate(pa, OPER); 336 | } 337 | 338 | void Form::on_jmpAddBtn_clicked() 339 | { 340 | int val = ui->jmpLine->value(); 341 | 342 | int rows = cl->size(); 343 | //qDebug() << tr("无条件跳转至 %1 行,总行数 %2").arg(line).arg(rows); 344 | if(rows == 0) { 345 | QMessageBox::warning(this, tr("警告"), QString(tr("请插入指令行"))); 346 | return; 347 | } 348 | 349 | if(val > rows) { 350 | QMessageBox::warning(this, tr("警告"), QString(tr("跳转行不能超过 %1 行")).arg(rows)); 351 | return; 352 | } 353 | 354 | QList pa; 355 | pa << val; 356 | 357 | operate(pa, JMP); 358 | } 359 | 360 | void Form::on_cmpAddBtn_clicked() 361 | { 362 | 363 | int val = ui->cmpLine->value(); 364 | int rows = cl->size(); 365 | 366 | if(val > rows) { 367 | QMessageBox::warning(this, tr("警告"), QString(tr("跳转行不能超过 %1 行")).arg(rows)); 368 | return; 369 | } 370 | 371 | int param = ui->cmpParam->value(); 372 | int type = ui->cmpType->currentIndex(); 373 | int value = ui->cmpVal->value(); 374 | 375 | QList pa; 376 | pa << param << type << value << val; 377 | 378 | operate(pa, CMP); 379 | } 380 | 381 | void Form::on_jumpAddBtn_clicked() 382 | { 383 | int val = ui->jumpLine->value(); 384 | int rows = cl->size(); 385 | if(val > rows) { 386 | QMessageBox::warning(this, tr("警告"), QString(tr("跳转行不能超过 %1 行")).arg(rows)); 387 | return; 388 | } 389 | 390 | int param = ui->jumpParam->value(); 391 | int state = ui->ioState->currentIndex();//0-低电平 1-高电平 392 | 393 | QList pa; 394 | pa << param << state << val; 395 | 396 | operate(pa,IOJMP); 397 | } 398 | 399 | void Form::on_inputAddBtn_clicked() //输入等待 400 | { 401 | int param = ui->inputParam->value(); 402 | int state = ui->inputState->currentIndex(); 403 | 404 | QList pa; 405 | pa << param << state; 406 | 407 | operate(pa, INPUT); 408 | } 409 | 410 | void Form::on_outputAddBtn_clicked() //主动输出 411 | { 412 | int param = ui->outputParam->value(); 413 | int state = ui->outputState->currentIndex(); 414 | 415 | QList pa; 416 | pa << param << state; 417 | operate(pa, SETOUT); 418 | } 419 | 420 | void Form::tableDoubleClick(const QModelIndex &/*index*/) 421 | { 422 | // 具体到某一行数据被双击 423 | // 需自定义一种模型,便于识别末行指令的类型 424 | // 然后展开相应的指令编辑区,用户修改指令 425 | // 数据模型还需要根据修改参数更新显示文本和指令 426 | //int nr = index.row(); 427 | //qDebug() << tr("%1 row double clicked. data %2").arg(nr).arg(index.data().toString()); 428 | 429 | //确定行 确定指令类型 430 | // 加入指令按钮有两种状态 新增和修改 431 | // 首次是新增 本方法改变状态为修改 432 | // 行确定修改模型 433 | // 类型确定修改指定模型行的数据 434 | // 指令和指令行对象均需要更新 435 | } 436 | 437 | void Form::tableClick(const QModelIndex &index) 438 | { 439 | int nr = index.row(); 440 | row = nr; 441 | runLine = nr; 442 | insertLine = nr; 443 | updateLine = nr; 444 | 445 | //line = cl->getRowData(row); 446 | //line->print(); 447 | } 448 | 449 | //ABS, RELA, SPD, OPER, JMP, CMP, IOJMP, DELAY, SETOUT, INPUT 450 | void Form::showToolBox(const QModelIndex &index) 451 | { 452 | line = cl->getRowData(index.row()); 453 | 454 | switch (line->type()) { 455 | case POS: 456 | ui->parentToolBox->setCurrentIndex(0); 457 | ui->moveToolBox->setCurrentIndex(0); 458 | break; 459 | case MOV: 460 | ui->parentToolBox->setCurrentIndex(0); 461 | ui->moveToolBox->setCurrentIndex(1); 462 | break; 463 | case SETSPD: 464 | ui->parentToolBox->setCurrentIndex(0); 465 | ui->moveToolBox->setCurrentIndex(2); 466 | break; 467 | case OPER: 468 | ui->parentToolBox->setCurrentIndex(1); 469 | ui->operateToolBox->setCurrentIndex(0); 470 | break; 471 | case JMP: 472 | ui->parentToolBox->setCurrentIndex(2); 473 | ui->condToolBox->setCurrentIndex(0); 474 | break; 475 | case CMP: 476 | ui->parentToolBox->setCurrentIndex(2); 477 | ui->condToolBox->setCurrentIndex(1); 478 | break; 479 | case IOJMP: 480 | ui->parentToolBox->setCurrentIndex(2); 481 | ui->condToolBox->setCurrentIndex(2); 482 | break; 483 | case INPUT: 484 | ui->parentToolBox->setCurrentIndex(3); 485 | ui->ioToolBox->setCurrentIndex(0); 486 | break; 487 | case SETOUT: 488 | ui->parentToolBox->setCurrentIndex(3); 489 | ui->ioToolBox->setCurrentIndex(1); 490 | break; 491 | case DELAY: 492 | ui->parentToolBox->setCurrentIndex(4); 493 | ui->auxToolBox->setCurrentIndex(0); 494 | break; 495 | case HOME: 496 | ui->parentToolBox->setCurrentIndex(4); 497 | ui->auxToolBox->setCurrentIndex(1); 498 | break; 499 | default: 500 | break; 501 | } 502 | } 503 | 504 | 505 | void Form::on_clearBtn_clicked() 506 | { 507 | cl->clear(); 508 | row = -1; 509 | runLine = -1; 510 | insertLine = -1; 511 | } 512 | 513 | void Form::on_deleteBtn_clicked() 514 | { 515 | if(row < 0) { 516 | QMessageBox::information(this, tr("提示"), tr("请选择指令行!")); 517 | return; 518 | } 519 | 520 | cl->del(row); 521 | //qDebug() << tr("%1 行已被删除!").arg(row+1); 522 | 523 | row = -1; 524 | } 525 | 526 | void Form::on_insertBtn_clicked() 527 | { 528 | //默认选中行之前插入指令 529 | if(insertLine == -1) { //未选中行提醒 530 | QMessageBox::information(this, tr("提示"), tr("请选择指令行!")); 531 | return; 532 | } else { 533 | if(!quit) {//非退出插入状态 534 | QMessageBox::information(this, tr("提示"), QString(tr("将在第%1行指令前插入指令,可以连续插入!").arg(insertLine+1))); 535 | ui->insertBtn->setText(tr("停止插入")); 536 | op = INSE; //切换为插入指令模式 537 | quit = true; 538 | //qDebug() << QString("选中行 %1").arg(row); 539 | } else {//退出插入状态 540 | ui->insertBtn->setText(tr("插入")); 541 | op = APP; 542 | insertLine = -1; 543 | quit = false; 544 | } 545 | } 546 | } 547 | 548 | void Form::on_editBtn_clicked() 549 | { 550 | //选中指令行校验 551 | if(updateLine == -1) { //未选中行提醒 552 | QMessageBox::information(this, tr("提示"), tr("请选择指令行!")); 553 | return; 554 | } else { 555 | QMessageBox::information(this, tr("提示"), QString(tr("请修改第%1行指令,可以是其他类型指令!")).arg(updateLine+1)); 556 | op = EDIT; //切换至修改模式 557 | } 558 | } 559 | 560 | void Form::updateConfigs(int level, int circle, int deviceId) 561 | { 562 | //qDebug() << "update configs"; 563 | 564 | int div[] = {1,2,4,8,16,32,64,128,256}; 565 | int alpha = 200 * div[level] / circle; 566 | //double beta = 0.4 * div[level] / circle; // 系数 200*100/50000 567 | int beta = 200 * div[level] / circle; //乘以线速度就是每秒脉冲数,最大值200k 568 | 569 | /* 570 | * 细分为256时,速度设置最大每秒脉冲为400k(否则还是200k不变),实际下发数值(每秒脉冲数)减半 571 | */ 572 | int maxSpd = 200000 / beta; //最大线速度 573 | //qDebug() << QString("level %1 and spd %2").arg(level).arg(maxSpd); 574 | 575 | if (level == 8) { 576 | maxSpd = 400000 / beta; 577 | beta = beta / 2; 578 | } 579 | 580 | //qDebug() << "max spd == " << maxSpd; 581 | ui->setRunSpd->setMaximum(maxSpd); 582 | 583 | line = new Line(alpha, beta, deviceId); 584 | } 585 | -------------------------------------------------------------------------------- /src/form.h: -------------------------------------------------------------------------------- 1 | #ifndef FORM_H 2 | #define FORM_H 3 | 4 | #include 5 | #include "commandline.h" 6 | 7 | namespace Ui { 8 | class Form; 9 | } 10 | class QAbstractItemModel; 11 | class ConfigDialog; 12 | 13 | class Form : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit Form(QWidget *parent = 0); 19 | ~Form(); 20 | 21 | bool loadProgFile(QString fileName); 22 | bool saveProgFile(QString fileName) const; 23 | 24 | enum OperType { 25 | APP, EDIT, INSE, QUIT 26 | }; 27 | //更新配置参数 28 | void updateConfigs(int level, int circle, int deviceId); 29 | 30 | public slots: 31 | void about(); 32 | 33 | signals: 34 | void sendData(const QByteArray &data); 35 | void sendStop(const QByteArray &data); 36 | 37 | private slots: 38 | 39 | void on_absAddBtn_clicked(); //绝对运动 40 | 41 | void on_relaAddBtn_clicked(); //相对运动 42 | 43 | void on_stopAct_clicked(); //停止 44 | 45 | void on_forwardAct_clicked(); //打包下载 46 | 47 | void on_stepAct_clicked(); //单步运行 48 | 49 | void on_setSpdBtn_clicked(); 50 | 51 | void on_opAddBtn_clicked(); 52 | 53 | void on_jmpAddBtn_clicked(); 54 | 55 | void on_cmpAddBtn_clicked(); 56 | 57 | void on_jumpAddBtn_clicked(); 58 | 59 | void on_inputAddBtn_clicked(); 60 | 61 | void on_outputAddBtn_clicked(); 62 | 63 | void on_delayAddBtn_clicked(); 64 | 65 | void on_homeAddBtn_clicked(); 66 | 67 | void spd_show(int); 68 | 69 | void tableDoubleClick(const QModelIndex &); //双击事件 70 | 71 | void tableClick(const QModelIndex &index); //单击事件 72 | 73 | void showToolBox(const QModelIndex &index); 74 | 75 | 76 | private slots: 77 | void on_clearBtn_clicked(); //清空 78 | void on_deleteBtn_clicked(); //删除 79 | void on_insertBtn_clicked(); //插入 80 | void on_editBtn_clicked(); //修改 81 | 82 | private: 83 | void initUI(); 84 | void initConnect(); 85 | void initModel(); 86 | 87 | //void operate(Command &cmd, QStringList &list); 88 | 89 | void operate(Line *ln); 90 | void operate(QList pa, CmdType type); 91 | 92 | private: 93 | Ui::Form *ui; 94 | CommandLine *cl; 95 | Line *line; 96 | ConfigDialog *config; 97 | 98 | OperType op; 99 | bool quit; 100 | int row; //选中行 101 | int runLine; //单步执行行 102 | int insertLine; //插入指令行 103 | int updateLine; //修改指令行 104 | }; 105 | 106 | #endif // FORM_H 107 | -------------------------------------------------------------------------------- /src/form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | 7 | 0 8 | 0 9 | 957 10 | 552 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 22 | 23 | 24 | 25 | 0 26 | 0 27 | 277 28 | 404 29 | 30 | 31 | 32 | 运动指令 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 40 | 41 | 42 | 43 | 0 44 | 0 45 | 259 46 | 308 47 | 48 | 49 | 50 | 绝对位置运动 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 运行距离(mm) 59 | 60 | 61 | 62 | 63 | 64 | 65 | -10000 66 | 67 | 68 | 10000 69 | 70 | 71 | 100 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Qt::Vertical 81 | 82 | 83 | 84 | 20 85 | 305 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 确定 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 0 103 | 0 104 | 259 105 | 308 106 | 107 | 108 | 109 | 相对位置运动 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 运行距离(mm) 118 | 119 | 120 | 121 | 122 | 123 | 124 | -10000 125 | 126 | 127 | 10000 128 | 129 | 130 | 100 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | Qt::Vertical 140 | 141 | 142 | 143 | 20 144 | 307 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 确定 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 0 162 | 0 163 | 259 164 | 308 165 | 166 | 167 | 168 | 速度设置 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 线速度(mm/s) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 0 184 | 185 | 186 | 100000 187 | 188 | 189 | 100 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | Qt::Vertical 206 | 207 | 208 | 209 | 20 210 | 242 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 确定 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 0 232 | 0 233 | 277 234 | 404 235 | 236 | 237 | 238 | 操作指令 239 | 240 | 241 | 242 | 243 | 244 | 0 245 | 246 | 247 | 248 | 249 | 0 250 | 0 251 | 259 252 | 360 253 | 254 | 255 | 256 | 操作参数 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 参数编号 265 | 266 | 267 | 268 | 269 | 270 | 271 | 1 272 | 273 | 274 | 20 275 | 276 | 277 | 1 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 操作类型 289 | 290 | 291 | 292 | 293 | 294 | 295 | 自增 296 | 297 | 298 | 299 | 自增 300 | 301 | 302 | 303 | 304 | 自减 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | Qt::Vertical 315 | 316 | 317 | 318 | 20 319 | 268 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 确定 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 0 341 | 0 342 | 277 343 | 404 344 | 345 | 346 | 347 | 条件指令 348 | 349 | 350 | 351 | 352 | 353 | 2 354 | 355 | 356 | 357 | 358 | 0 359 | 0 360 | 126 361 | 75 362 | 363 | 364 | 365 | 无条件跳转 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 跳转至行数 374 | 375 | 376 | 377 | 378 | 379 | 380 | 1 381 | 382 | 383 | 20 384 | 385 | 386 | 1 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | Qt::Vertical 396 | 397 | 398 | 399 | 20 400 | 294 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 确定 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 0 418 | 0 419 | 158 420 | 131 421 | 422 | 423 | 424 | 有条件跳转 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 参数编号 433 | 434 | 435 | 436 | 437 | 438 | 439 | 1 440 | 441 | 442 | 20 443 | 444 | 445 | 1 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 判断类型 457 | 458 | 459 | 460 | 461 | 462 | 463 | > 464 | 465 | 466 | 467 | > 468 | 469 | 470 | 471 | 472 | == 473 | 474 | 475 | 476 | 477 | < 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 20 486 | 487 | 488 | 1 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 跳转至行数 500 | 501 | 502 | 503 | 504 | 505 | 506 | 1 507 | 508 | 509 | 20 510 | 511 | 512 | 1 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | Qt::Vertical 522 | 523 | 524 | 525 | 20 526 | 240 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 确定 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 0 544 | 0 545 | 259 546 | 308 547 | 548 | 549 | 550 | IO条件跳转 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 端口编号 559 | 560 | 561 | 562 | 563 | 564 | 565 | 1 566 | 567 | 568 | 100 569 | 570 | 571 | 1 572 | 573 | 574 | 575 | 576 | 577 | 578 | 低电平 579 | 580 | 581 | 582 | 低电平 583 | 584 | 585 | 586 | 587 | 高电平 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 跳转至行数 600 | 601 | 602 | 603 | 604 | 605 | 606 | 1 607 | 608 | 609 | 10000 610 | 611 | 612 | 1 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | Qt::Vertical 622 | 623 | 624 | 625 | 20 626 | 214 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 确定 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 0 648 | 0 649 | 277 650 | 404 651 | 652 | 653 | 654 | IO指令 655 | 656 | 657 | 658 | 659 | 660 | 1 661 | 662 | 663 | 664 | 665 | 0 666 | 0 667 | 136 668 | 103 669 | 670 | 671 | 672 | 输入IO等待 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | IO编号 681 | 682 | 683 | 684 | 685 | 686 | 687 | 1 688 | 689 | 690 | 100 691 | 692 | 693 | 1 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 电平状态 705 | 706 | 707 | 708 | 709 | 710 | 711 | 高电平 712 | 713 | 714 | 1 715 | 716 | 717 | 718 | 低电平 719 | 720 | 721 | 722 | 723 | 高电平 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | Qt::Vertical 734 | 735 | 736 | 737 | 20 738 | 240 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 确定 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 0 756 | 0 757 | 259 758 | 334 759 | 760 | 761 | 762 | 输出IO设置 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | IO编号 771 | 772 | 773 | 774 | 775 | 776 | 777 | 1 778 | 779 | 780 | 1 781 | 782 | 783 | 1 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 电平状态 795 | 796 | 797 | 798 | 799 | 800 | 801 | 接通 802 | 803 | 804 | 1 805 | 806 | 807 | 808 | 断开 809 | 810 | 811 | 812 | 813 | 接通 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | Qt::Vertical 824 | 825 | 826 | 827 | 20 828 | 240 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 确定 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 0 850 | 0 851 | 277 852 | 404 853 | 854 | 855 | 856 | 辅助指令 857 | 858 | 859 | 860 | 861 | 862 | 1 863 | 864 | 865 | 866 | 867 | 0 868 | 0 869 | 150 870 | 75 871 | 872 | 873 | 874 | 延时指令 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 延时时间(ms) 883 | 884 | 885 | 886 | 887 | 888 | 889 | 6500 890 | 891 | 892 | 100 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | Qt::Vertical 902 | 903 | 904 | 905 | 20 906 | 282 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 确定 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 0 924 | 0 925 | 259 926 | 334 927 | 928 | 929 | 930 | 设置零点 931 | 932 | 933 | 934 | 935 | 936 | 提示:将当前位置设置为零点位置。 937 | 938 | 939 | 940 | 941 | 942 | 943 | 确定 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | Qt::Vertical 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | false 968 | 969 | 970 | QAbstractItemView::SelectRows 971 | 972 | 973 | false 974 | 975 | 976 | 120 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | Qt::Horizontal 986 | 987 | 988 | 989 | 40 990 | 20 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 单步 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 停止 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 下载 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | Qt::Vertical 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 修改 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 插入 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 删除 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 清空 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | Qt::Vertical 1061 | 1062 | 1063 | 1064 | 20 1065 | 40 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | -------------------------------------------------------------------------------- /src/images/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/app.ico -------------------------------------------------------------------------------- /src/images/application-exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/application-exit.png -------------------------------------------------------------------------------- /src/images/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/clear.png -------------------------------------------------------------------------------- /src/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/close.png -------------------------------------------------------------------------------- /src/images/connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/connect.png -------------------------------------------------------------------------------- /src/images/disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/disconnect.png -------------------------------------------------------------------------------- /src/images/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/help.png -------------------------------------------------------------------------------- /src/images/help_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/help_48dp.png -------------------------------------------------------------------------------- /src/images/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/link.png -------------------------------------------------------------------------------- /src/images/link_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/link_off.png -------------------------------------------------------------------------------- /src/images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/open.png -------------------------------------------------------------------------------- /src/images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/save.png -------------------------------------------------------------------------------- /src/images/serial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/serial.png -------------------------------------------------------------------------------- /src/images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/settings.png -------------------------------------------------------------------------------- /src/images/settings_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eeyoo/step-servo-tuner/5be2929e8352d16134335c49901b4c507ff56039/src/images/settings_new.png -------------------------------------------------------------------------------- /src/line.cpp: -------------------------------------------------------------------------------- 1 | #include "line.h" 2 | 3 | #include 4 | 5 | Line::Line() 6 | { 7 | 8 | } 9 | 10 | Line::Line(QList params, CmdType type) 11 | { 12 | mType = type; 13 | mParams = params; 14 | } 15 | 16 | Line::Line(int a, double b, int id) { 17 | alpha = a; 18 | beta = b; 19 | deviceId = id; 20 | } 21 | 22 | Line::Line(QStringList &list) 23 | { 24 | //QString convert to enum type 25 | QString s = QString(list[0]).toUpper(); 26 | str2key(s); 27 | //qDebug() << QString("type %1 -- %2").arg(s).arg(mType); 28 | mParams.clear(); 29 | 30 | switch (mType) { 31 | case POS: 32 | case MOV: 33 | case SETSPD: 34 | case DELAY: 35 | case JMP: 36 | mParams << QString(list[1]).toInt(); 37 | //qDebug() << QString("type %1 params %2").arg(s).arg(mParams[0]); 38 | break; 39 | case OPER: 40 | case SETOUT: 41 | case INPUT: 42 | mParams << QString(list[1]).toInt(); 43 | mParams << QString(list[2]).toInt(); 44 | //qDebug() << QString("type %1 params %2 %3").arg(s).arg(mParams[0]).arg(mParams[1]); 45 | break; 46 | case IOJMP: 47 | mParams << QString(list[1]).toInt(); 48 | mParams << QString(list[2]).toInt(); 49 | mParams << QString(list[3]).toInt(); 50 | //qDebug() << QString("type %1 params %2 %3 %4").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]); 51 | break; 52 | case CMP: 53 | mParams << QString(list[1]).toInt(); 54 | mParams << QString(list[2]).toInt(); 55 | mParams << QString(list[3]).toInt(); 56 | mParams << QString(list[4]).toInt(); 57 | //qDebug() << QString("type %1 params %2 %3 %4 %5").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]).arg(mParams[3]); 58 | break; 59 | default: 60 | break; 61 | } 62 | 63 | } 64 | 65 | void Line::print() 66 | { 67 | QString s; 68 | translate(mType, s); 69 | 70 | switch (mType) { 71 | case POS: 72 | case MOV: 73 | case SETSPD: 74 | case DELAY: 75 | case JMP: 76 | qDebug() << QString("%1 %2").arg(s).arg(mParams[0]); 77 | break; 78 | case OPER: 79 | case SETOUT: 80 | case INPUT: 81 | //s = "INPUT"; 82 | qDebug() << QString("%1 %2 %3").arg(s).arg(mParams[0]).arg(mParams[1]); 83 | break; 84 | case IOJMP: 85 | //s = "IOJMP"; 86 | qDebug() << QString("%1 %2 %3 %4").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]); 87 | break; 88 | case CMP: 89 | //s = "CMP"; 90 | qDebug() << QString("%1 %2 %3 %4 %5").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]).arg(mParams[3]); 91 | break; 92 | default: 93 | break; 94 | } 95 | //qDebug() << QString("[%1 %2]").arg(s).arg(mParams[0]); 96 | } 97 | 98 | void Line::print(QString &str) 99 | { 100 | QString s; 101 | translate(mType, s); 102 | 103 | switch (mType) { 104 | case HOME: 105 | str = QString("%1").arg(s); 106 | //qDebug() << str; 107 | break; 108 | case POS: 109 | case MOV: 110 | case SETSPD: 111 | case DELAY: 112 | case JMP: 113 | str = QString("%1 %2").arg(s).arg(mParams[0]); 114 | //qDebug() << str; 115 | break; 116 | case OPER: 117 | case SETOUT: 118 | case INPUT: 119 | //s = "INPUT"; 120 | str = QString("%1 %2 %3").arg(s).arg(mParams[0]).arg(mParams[1]); 121 | //qDebug() << str; 122 | break; 123 | case IOJMP: 124 | //s = "IOJMP"; 125 | str = QString("%1 %2 %3 %4").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]); 126 | //qDebug() << str; 127 | break; 128 | case CMP: 129 | //s = "CMP"; 130 | str = QString("%1 %2 %3 %4 %5").arg(s).arg(mParams[0]).arg(mParams[1]).arg(mParams[2]).arg(mParams[3]); 131 | //qDebug() << str; 132 | break; 133 | default: 134 | break; 135 | } 136 | } 137 | 138 | //POS, MOV, SETSPD, OPER, JMP, CMP, IOJMP, DELAY, SETOUT, INPUT 139 | QString Line::translate(CmdType type, QString &s) 140 | { 141 | switch (type) { 142 | case POS: 143 | s = "POS"; 144 | break; 145 | case MOV: 146 | s = "MOV"; 147 | break; 148 | case SETSPD: 149 | s = "SETSPD"; 150 | break; 151 | case OPER: 152 | s = "OPER"; 153 | break; 154 | case JMP: 155 | s = "JMP"; 156 | break; 157 | case CMP: 158 | s = "CMP"; 159 | break; 160 | case IOJMP: 161 | s = "IOJMP"; 162 | break; 163 | case DELAY: 164 | s = "DELAY"; 165 | break; 166 | case SETOUT: 167 | s = "SETOUT"; 168 | break; 169 | case INPUT: 170 | s = "INPUT"; 171 | break; 172 | case HOME: 173 | s = "SETHOME"; 174 | break; 175 | default: 176 | break; 177 | } 178 | 179 | return s; 180 | } 181 | 182 | //POS, MOV, SETSPD, OPER, JMP, CMP, IOJMP, DELAY, SETOUT, INPUT 183 | void Line::str2key(QString &s) 184 | { 185 | if (s == "POS") 186 | mType = POS; 187 | else if (s == "MOV") 188 | mType = MOV; 189 | else if (s == "SETSPD") 190 | mType = SETSPD; 191 | else if (s == "OPER") 192 | mType = OPER; 193 | else if (s == "JMP") 194 | mType = JMP; 195 | else if (s == "CMP") 196 | mType = CMP; 197 | else if (s == "IOJMP") 198 | mType = IOJMP; 199 | else if (s == "DELAY") 200 | mType = DELAY; 201 | else if (s == "SETOUT") 202 | mType = SETOUT; 203 | else if (s == "INPUT") 204 | mType = INPUT; 205 | else if (s == "SETHOME") 206 | mType = HOME; 207 | } 208 | 209 | void Line::strlist(QStringList &list) const 210 | { 211 | //qDebug() << "line strlist called and type " << mType; 212 | 213 | switch (mType) { 214 | case POS: 215 | list << "绝对运行指令" << QString("绝对运行距离至 %1mm").arg(mParams[0]); 216 | //qDebug() << list[0] << " " << list[1]; 217 | break; 218 | case MOV: 219 | //s = "MOV"; 220 | list << "相对运行指令" << QString("相对运行距离 %1mm").arg(mParams[0]); 221 | break; 222 | case SETSPD: 223 | //s = "SETSPD"; 224 | list << "设置速度指令" << QString("线速度设置为 %1 mm/s").arg(mParams[0]); 225 | break; 226 | case DELAY: 227 | //s = "DELAY"; 228 | list << "延时等待指令" << QString("延时等待 %1 毫秒").arg(mParams[0]); 229 | break; 230 | case HOME: 231 | list << "零点设置指令" << QString("当前位置设置为零点位置"); 232 | break; 233 | case OPER: 234 | //s = "OPER"; 235 | if(mParams[1] == 0) 236 | list << "操作参数指令" << QString("编号 %1 参数 ++").arg(mParams[0]); 237 | else if(mParams[1] == 1) 238 | list << "操作参数指令" << QString("编号 %1 参数 --").arg(mParams[0]); 239 | break; 240 | case JMP: 241 | //s = "JMP"; 242 | list << "无条件跳转指令" << QString("无条件跳转至 %1 行").arg(mParams[0]); 243 | break; 244 | case CMP: 245 | //s = "CMP"; 246 | list << "有条件跳转指令"; 247 | if(mParams[1] == 0) 248 | list << QString("编号 %1 参数大于 %2 跳转至 %3 行").arg(mParams[0]).arg(mParams[2]).arg(mParams[3]); 249 | if(mParams[1] == 1) 250 | list << QString("编号 %1 参数等于 %2 跳转至 %3 行").arg(mParams[0]).arg(mParams[2]).arg(mParams[3]); 251 | if(mParams[1] == 2) 252 | list << QString("编号 %1 参数小于 %2 跳转至 %3 行").arg(mParams[0]).arg(mParams[2]).arg(mParams[3]); 253 | break; 254 | case IOJMP: 255 | //s = "IOJMP"; 256 | list << "IO条件跳转指令"; 257 | if(!mParams[1]) 258 | list << QString("编号 %1 IO端口低电平跳转至 %2 行").arg(mParams[0]).arg(mParams[2]); 259 | else 260 | list << QString("编号 %1 IO端口高电平跳转至 %2 行").arg(mParams[0]).arg(mParams[2]); 261 | break; 262 | case INPUT: 263 | list << "输入等待指令"; 264 | if(!mParams[1]) 265 | list << QString("编号 %1 输入端口低电平等待").arg(mParams[0]); 266 | else 267 | list << QString("编号 %1 输入端口高电平等待").arg(mParams[0]); 268 | break; 269 | case SETOUT: 270 | list << "输出设置指令"; 271 | if(!mParams[1]) 272 | list << QString("设置编号 %1 输出端口断开").arg(mParams[0]); 273 | else 274 | list << QString("设置编号 %1 输出端口接通").arg(mParams[0]); 275 | break; 276 | default: 277 | break; 278 | } 279 | } 280 | 281 | CmdType Line::type() 282 | { 283 | return mType; 284 | } 285 | 286 | void Line::convert(quint8 *buf, int data, int size) 287 | { 288 | for(int i=0; i> (8*i); 290 | } 291 | 292 | void Line::array2qa(QByteArray &data, quint8 *buf, int size) 293 | { 294 | for(int i=0; i 10 | 11 | #define ABS_MOVE_CMD 0x01 //绝对运动 12 | #define REL_MOVE_CMD 0x02 //相对运动 13 | #define SETMOVESPCMD 0x03 //目标速度 14 | 15 | #define OPERATEPARAM 0x31 //操作参数命令 1)++ 2)-- 16 | #define JMP_CMD 0x32 //无条件跳转 17 | #define CMP_CMD 0x33 //有条件跳转 1)> 2)== 3< 18 | #define IOJUMP_CMD 0x34 //IO条件跳转 0-低电平 1-高电平 仅包括1-4号端口 19 | #define DELAY_CMD 0x35 //延时等待单位毫秒 20 | #define HOME_CMD 0x36 //回到零点 21 | 22 | #define SETOUT_CMD 0x40 //设置输出IO端口值 23 | #define INPUT_CMD 0x41 //输入IO端口等待指令 24 | 25 | #define SETACCDURCMD 0xa1 //设置加速时间(单位ms) 26 | #define SETDECDURCMD 0xa2 //设置减速时间(单位ms) 27 | #define SETPOSMAXPOS 0xa3 //设置正向最大允许位置(单位mm) 28 | #define SETNEGMAXPOS 0xa4 //设置负向最大允许位置(单位mm) 29 | #define SETPLUSCTRLT 0xa5 //设置脉冲控制方式,0x01--外部脉冲控制; 其他:内部脉冲控制 30 | #define SETCODELOGDI 0xa6 //设置编码器逻辑方向 1-正向 0-负向 31 | #define SETSERBAUDRT 0xa7 //RS485波特率 32 | #define SETCANBAUDRT 0xa8 //CAN波特率 33 | #define SETDEVICEID 0xa9 //设备ID - CAN ID 34 | #define SETMOTORDIRE 0xaa //电机逻辑正方向 35 | #define SETLIMITPOS 0xab //设置左右限位 36 | 37 | #define SETMOTDIVCMD 0xb1 //设置电机细分 1,2,4,8,32,64,128,256 38 | #define SETCUGEARCMD 0xb2 //设置电机电流档位 1-32 39 | #define SETREFVOLCMD 0xb3 //设置参考电压 0 - 低 1 - 高 40 | #define SETSMARTCURR 0xb4 //设置智能电流控制值 0 - 设置电流值1/2; 1 - 设置电流值1/4 41 | 42 | #define BATCHCONFCMD 0xca //配置下载 43 | #define CMDBATCHHEAD 0xcd //指令下载 44 | 45 | #define EMSTOP_CMD 0x0f //设备停止 46 | 47 | #define NUMBER_ID 0x02 48 | #define NUMBER_DA 0x04 49 | #define NUMBER_CMD 0x0a 50 | #define NUMBER_HIGH 0x02 51 | #define NUMBER_LOW 0x02 52 | 53 | static int alpha; //位移转换脉冲数参数 54 | static double beta; //线速度与脉冲转换参数 55 | static int deviceId; //设备ID 56 | 57 | enum CmdType { 58 | POS, MOV, SETSPD, OPER, JMP, CMP, IOJMP, DELAY, SETOUT, INPUT, HEAD, STOP, HOME 59 | }; 60 | 61 | class Line 62 | { 63 | public: 64 | explicit Line(); 65 | Line(int a, double b, int id); 66 | 67 | 68 | Line(QList params, CmdType type); 69 | Line(QStringList &list); 70 | 71 | void print(); 72 | void strlist(QStringList &list) const; 73 | 74 | void print(QString &str); 75 | CmdType type(); 76 | 77 | QByteArray data() const; 78 | 79 | //void test(); 80 | 81 | private: 82 | QString translate(CmdType type, QString &s); 83 | void str2key(QString &s); 84 | 85 | static void convert(quint8 *buf, int data, int size); //int -> quint8[4] 86 | static void array2qa(QByteArray &data, quint8 *buf, int size); //quint8[4] -> QByteArray 87 | 88 | private: 89 | CmdType mType; 90 | QList mParams; 91 | 92 | }; 93 | 94 | #endif // LINE_H 95 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #include 36 | 37 | #include "mainwindow.h" 38 | 39 | int main(int argc, char *argv[]) 40 | { 41 | QApplication a(argc, argv); 42 | MainWindow w; 43 | w.show(); 44 | return a.exec(); 45 | } 46 | -------------------------------------------------------------------------------- /src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #include "mainwindow.h" 36 | #include "ui_mainwindow.h" 37 | #include "console.h" 38 | #include "settingsdialog.h" 39 | #include "form.h" 40 | #include "configdialog.h" 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | 50 | 51 | MainWindow::MainWindow(QWidget *parent) : 52 | QMainWindow(parent), 53 | runStatus(true), // 上电运行 54 | ui(new Ui::MainWindow) 55 | { 56 | ui->setupUi(this); 57 | 58 | form = new Form; 59 | setCentralWidget(form); 60 | setWindowTitle(QWidget::tr("步进电机快速调试程序")); 61 | 62 | serial = new QSerialPort(this); 63 | 64 | settings = new SettingsDialog; 65 | config = new ConfigDialog; 66 | 67 | ui->actionConnect->setEnabled(true); 68 | ui->actionDisconnect->setEnabled(false); 69 | 70 | ui->actionConfigure->setEnabled(true); 71 | ui->actionQuit->setEnabled(true); 72 | 73 | status = new QLabel; 74 | ui->statusBar->addWidget(status); 75 | 76 | initActionsConnections(); 77 | 78 | connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, 79 | SLOT(handleError(QSerialPort::SerialPortError))); 80 | 81 | connect(serial, SIGNAL(readyRead()), this, SLOT(readData())); 82 | 83 | connect(form, SIGNAL(sendData(QByteArray)), this, SLOT(writeData(QByteArray))); 84 | connect(form, SIGNAL(sendStop(QByteArray)), this, SLOT(writeStop(QByteArray))); 85 | 86 | connect(config, SIGNAL(sendConfig(QByteArray)), this, SLOT(writeConfig(QByteArray))); 87 | 88 | connect(config, SIGNAL(changeConfigs()), this, SLOT(updateConfigs())); 89 | } 90 | 91 | MainWindow::~MainWindow() 92 | { 93 | delete settings; 94 | delete config; 95 | delete form; 96 | delete ui; 97 | } 98 | 99 | void MainWindow::updateConfigs() 100 | { 101 | //qDebug() << "mainwindow test slots"; 102 | ConfigDialog::Configs c = config->configs(); 103 | form->updateConfigs(c.elecLevel, c.circleLen, c.deviceId); 104 | } 105 | 106 | void MainWindow::openSerialPort() 107 | { 108 | SettingsDialog::Settings p = settings->settings(); 109 | serial->setPortName(p.name); 110 | serial->setBaudRate(p.baudRate); 111 | serial->setDataBits(p.dataBits); 112 | serial->setParity(p.parity); 113 | serial->setStopBits(p.stopBits); 114 | serial->setFlowControl(p.flowControl); 115 | if (serial->open(QIODevice::ReadWrite)) { 116 | 117 | ui->actionConnect->setEnabled(false); 118 | ui->actionDisconnect->setEnabled(true); 119 | ui->actionConfigure->setEnabled(false); 120 | /* 121 | showStatusMessage(tr("连接 %1 : 波特率 %2, %3位, 校验%4, 停止位%5, 控制流%6") 122 | .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits) 123 | .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl)); 124 | */ 125 | QString status = tr("串口连接成功\n端口%1, 波特率%2, 数据%3位, 校验方式 %4, 停止位%5位, 控制流%6") 126 | .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits) 127 | .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl); 128 | QMessageBox::information(this,tr("串口连接"),status); 129 | } else { 130 | QMessageBox::critical(this, tr("串口连接错误"), serial->errorString()); 131 | 132 | showStatusMessage(tr("连接错误")); 133 | } 134 | } 135 | 136 | void MainWindow::closeSerialPort() 137 | { 138 | if (serial->isOpen()) 139 | { 140 | serial->close(); 141 | } 142 | 143 | ui->actionConnect->setEnabled(true); 144 | ui->actionDisconnect->setEnabled(false); 145 | ui->actionConfigure->setEnabled(true); 146 | //showStatusMessage(tr("断开连接")); 147 | QMessageBox::information(this, tr("串口连接"), tr("串口已断开连接")); 148 | } 149 | 150 | void MainWindow::about() 151 | { 152 | QMessageBox::about(this, tr("About Simple Terminal"), 153 | tr("The Simple Terminal example demonstrates how to " 154 | "use the Qt Serial Port module in modern GUI applications " 155 | "using Qt, with a menu bar, toolbars, and a status bar.")); 156 | } 157 | 158 | void MainWindow::writeData(const QByteArray &data) 159 | { 160 | //串口发送数据 - 缓存写数据 161 | //showStatusMessage(tr("发送指令数据:") + data.toHex()); 162 | //qDebug() << data.toHex(); 163 | 164 | if(!serial->isOpen()) 165 | { 166 | QMessageBox::warning(this,tr("警告"),tr("请打开串口!")); 167 | return; 168 | } 169 | //未接收到停止状态反馈不能下载程序 170 | if(runStatus) { 171 | QMessageBox::warning(this, tr("警告"), tr("请停止运行")); 172 | return; 173 | } 174 | 175 | serial->write(data); 176 | } 177 | 178 | //停止专用 179 | void MainWindow::writeStop(const QByteArray &data) 180 | { 181 | 182 | if(!serial->isOpen()) 183 | { 184 | QMessageBox::warning(this,tr("警告"),tr("请打开串口!")); 185 | return; 186 | } 187 | 188 | serial->write(data); 189 | } 190 | 191 | void MainWindow::writeConfig(const QByteArray &data) 192 | { 193 | //showStatusMessage(tr("发送指令数据:") + data.toHex()); 194 | 195 | if(!serial->isOpen()) 196 | { 197 | QMessageBox::warning(this,tr("警告"),tr("请打开串口!")); 198 | return; 199 | } 200 | 201 | serial->write(data); 202 | 203 | config->tip(); 204 | } 205 | 206 | void MainWindow::readData() 207 | { 208 | //缓存读数据 - 串口接收数据 209 | QByteArray recv = serial->readAll(); 210 | int size = recv.size(); 211 | //qDebug() << QString::fromLatin1(data.toHex().data()); 212 | 213 | 214 | if(size > 2) { 215 | 216 | int ret = (quint8) recv.at(2); 217 | //qDebug() << QString::number(ret); 218 | switch (ret) { 219 | case BATCHCONFCMD: 220 | QMessageBox::information(this, tr("下载提示"), tr("下载配置成功!")); 221 | break; 222 | case CMDBATCHHEAD: 223 | runStatus = true; //设备运行状态 224 | QMessageBox::information(this, tr("下载提示"), tr("下载程序成功!")); 225 | break; 226 | case EMSTOP_CMD: 227 | runStatus = false; //设备停止状态 228 | QMessageBox::information(this, tr("设备状态"), tr("设备已停止")); 229 | default: 230 | //QMessageBox::information(this, tr("下载提示"), tr("下载数据成功!")); 231 | break; 232 | } 233 | } 234 | 235 | } 236 | 237 | void MainWindow::handleError(QSerialPort::SerialPortError error) 238 | { 239 | if (error == QSerialPort::ResourceError) { 240 | QMessageBox::critical(this, tr("Critical Error"), serial->errorString()); 241 | closeSerialPort(); 242 | } 243 | } 244 | 245 | void MainWindow::initActionsConnections() 246 | { 247 | connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(openSerialPort())); 248 | connect(ui->actionDisconnect, SIGNAL(triggered()), this, SLOT(closeSerialPort())); 249 | connect(ui->actionConfigure, SIGNAL(triggered()), settings, SLOT(show())); 250 | connect(ui->actionSystem, SIGNAL(triggered()), config, SLOT(show())); 251 | connect(ui->actionAbout, SIGNAL(triggered()), form, SLOT(about())); 252 | 253 | connect(ui->actionOpenProg, SIGNAL(triggered(bool)), this, SLOT(openProgFile())); 254 | connect(ui->actionSaveProg, SIGNAL(triggered(bool)), this, SLOT(saveProgFile())); 255 | 256 | connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(closeAll())); 257 | } 258 | 259 | void MainWindow::showStatusMessage(const QString &message) 260 | { 261 | status->setText(message); 262 | //statusBar()->showMessage(message, 1000); 263 | } 264 | 265 | void MainWindow::closeAll() 266 | { 267 | close(); 268 | config->close(); 269 | settings->close(); 270 | } 271 | 272 | void MainWindow::closeEvent(QCloseEvent */*e*/) 273 | { 274 | closeAll(); 275 | } 276 | 277 | void MainWindow::openProgFile() 278 | { 279 | //打开默认文件目录等待用户选中载入文件,限制打开文件格式 280 | QString fileName = QFileDialog::getOpenFileName(this, tr("打开程序文件"), 281 | "", 282 | tr("程序 (*.prog)")); 283 | //qDebug() << "打开文件名: " + fileName; 284 | //读取文件流内容,调用程序form载入程序指令方法 285 | if(form->loadProgFile(fileName)) 286 | qDebug() << "load prog file successful."; 287 | else 288 | qDebug() << "load failed."; 289 | } 290 | 291 | void MainWindow::saveProgFile() 292 | { 293 | //打开文件保存对话框,提示用户输入文件名以待保存 294 | QString fileName = QFileDialog::getSaveFileName(this, tr("保存程序文件"), 295 | "程序.prog", 296 | tr("程序 (*.prog)")); 297 | 298 | bool ret = form->saveProgFile(fileName); 299 | 300 | //保存为磁盘文件 301 | if(ret) { 302 | qDebug() << "save prog file successful."; 303 | } else { 304 | qDebug() << "save prog file failed."; 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #ifndef MAINWINDOW_H 36 | #define MAINWINDOW_H 37 | 38 | #include 39 | 40 | #include 41 | 42 | #include 43 | 44 | QT_BEGIN_NAMESPACE 45 | namespace Ui { 46 | class MainWindow; 47 | } 48 | 49 | QT_END_NAMESPACE 50 | 51 | class QLabel; 52 | class Form; 53 | class Command; 54 | class SettingsDialog; 55 | class ConfigDialog; 56 | class File; 57 | 58 | class MainWindow : public QMainWindow 59 | { 60 | Q_OBJECT 61 | 62 | public: 63 | explicit MainWindow(QWidget *parent = 0); 64 | ~MainWindow(); 65 | 66 | protected: 67 | void closeEvent(QCloseEvent *); 68 | 69 | 70 | private slots: 71 | void openSerialPort(); 72 | void closeSerialPort(); 73 | void about(); 74 | void writeData(const QByteArray &data); 75 | void writeStop(const QByteArray &data); 76 | void readData(); 77 | void writeConfig(const QByteArray &data); 78 | void closeAll(); 79 | 80 | void openProgFile(); //导入程序文件 81 | void saveProgFile(); //保存程序文件 82 | 83 | void handleError(QSerialPort::SerialPortError error); 84 | 85 | void updateConfigs(); 86 | 87 | private: 88 | void initActionsConnections(); 89 | 90 | private: 91 | void showStatusMessage(const QString &message); 92 | 93 | Ui::MainWindow *ui; 94 | QLabel *status; 95 | SettingsDialog *settings; //串口设置界面 96 | QSerialPort *serial; 97 | Form *form; 98 | ConfigDialog *config; //程序初始化设置界面 99 | bool runStatus; 100 | }; 101 | 102 | #endif // MAINWINDOW_H 103 | -------------------------------------------------------------------------------- /src/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 902 10 | 535 11 | 12 | 13 | 14 | Simple Terminal 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 0 23 | 0 24 | 902 25 | 23 26 | 27 | 28 | 29 | 30 | 操作 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 工具 42 | 43 | 44 | 45 | 46 | 47 | 48 | 帮助 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | toolBar 60 | 61 | 62 | TopToolBarArea 63 | 64 | 65 | false 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | :/images/help_48dp.png:/images/help_48dp.png 80 | 81 | 82 | 帮助 83 | 84 | 85 | 帮助 86 | 87 | 88 | Alt+A 89 | 90 | 91 | 92 | 93 | About Qt 94 | 95 | 96 | 97 | 98 | 99 | :/images/link.png:/images/link.png 100 | 101 | 102 | 连接 103 | 104 | 105 | 连接 106 | 107 | 108 | 开启串口通信 109 | 110 | 111 | Ctrl+O 112 | 113 | 114 | 115 | 116 | 117 | :/images/link_off.png:/images/link_off.png 118 | 119 | 120 | 断开 121 | 122 | 123 | 断开 124 | 125 | 126 | 断开串口通信 127 | 128 | 129 | Ctrl+D 130 | 131 | 132 | 133 | 134 | 135 | :/images/serial.png:/images/serial.png 136 | 137 | 138 | 串口配置 139 | 140 | 141 | 串口配置 142 | 143 | 144 | Alt+C 145 | 146 | 147 | 148 | 149 | 150 | :/images/close.png:/images/close.png 151 | 152 | 153 | 退出 154 | 155 | 156 | 157 | 158 | 159 | :/images/settings_new.png:/images/settings_new.png 160 | 161 | 162 | 系统配置 163 | 164 | 165 | Alt+S 166 | 167 | 168 | 169 | 170 | 171 | :/images/open.png:/images/open.png 172 | 173 | 174 | 打开程序 175 | 176 | 177 | 178 | 179 | 180 | :/images/save.png:/images/save.png 181 | 182 | 183 | 保存程序 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /src/settingsdialog.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #include "settingsdialog.h" 36 | #include "ui_settingsdialog.h" 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | QT_USE_NAMESPACE 43 | 44 | static const char blankString[] = QT_TRANSLATE_NOOP(tr("串口设置"), "N/A"); 45 | 46 | SettingsDialog::SettingsDialog(QWidget *parent) : 47 | QDialog(parent), 48 | ui(new Ui::SettingsDialog) 49 | { 50 | ui->setupUi(this); 51 | 52 | intValidator = new QIntValidator(0, 4000000, this); 53 | 54 | ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert); 55 | 56 | connect(ui->applyButton, SIGNAL(clicked()), 57 | this, SLOT(apply())); 58 | connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)), 59 | this, SLOT(showPortInfo(int))); 60 | connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)), 61 | this, SLOT(checkCustomBaudRatePolicy(int))); 62 | connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)), 63 | this, SLOT(checkCustomDevicePathPolicy(int))); 64 | 65 | fillPortsParameters(); 66 | fillPortsInfo(); 67 | 68 | updateSettings(); 69 | 70 | setWindowTitle(tr("串口配置")); 71 | } 72 | 73 | SettingsDialog::~SettingsDialog() 74 | { 75 | delete ui; 76 | } 77 | 78 | SettingsDialog::Settings SettingsDialog::settings() const 79 | { 80 | return currentSettings; 81 | } 82 | 83 | void SettingsDialog::showPortInfo(int idx) 84 | { 85 | if (idx == -1) 86 | return; 87 | 88 | QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList(); 89 | ui->descriptionLabel->setText(tr("描述: %1").arg(list.count() > 1 ? list.at(1) : tr(blankString))); 90 | ui->manufacturerLabel->setText(tr("制造商: %1").arg(list.count() > 2 ? list.at(2) : tr(blankString))); 91 | ui->serialNumberLabel->setText(tr("串口端口: %1").arg(list.count() > 3 ? list.at(3) : tr(blankString))); 92 | ui->locationLabel->setText(tr("地址: %1").arg(list.count() > 4 ? list.at(4) : tr(blankString))); 93 | ui->vidLabel->setText(tr("厂家ID: %1").arg(list.count() > 5 ? list.at(5) : tr(blankString))); 94 | ui->pidLabel->setText(tr("产品ID: %1").arg(list.count() > 6 ? list.at(6) : tr(blankString))); 95 | } 96 | 97 | void SettingsDialog::apply() 98 | { 99 | updateSettings(); 100 | hide(); 101 | } 102 | 103 | void SettingsDialog::checkCustomBaudRatePolicy(int idx) 104 | { 105 | bool isCustomBaudRate = !ui->baudRateBox->itemData(idx).isValid(); 106 | ui->baudRateBox->setEditable(isCustomBaudRate); 107 | if (isCustomBaudRate) { 108 | ui->baudRateBox->clearEditText(); 109 | QLineEdit *edit = ui->baudRateBox->lineEdit(); 110 | edit->setValidator(intValidator); 111 | } 112 | } 113 | 114 | void SettingsDialog::checkCustomDevicePathPolicy(int idx) 115 | { 116 | bool isCustomPath = !ui->serialPortInfoListBox->itemData(idx).isValid(); 117 | ui->serialPortInfoListBox->setEditable(isCustomPath); 118 | if (isCustomPath) 119 | ui->serialPortInfoListBox->clearEditText(); 120 | } 121 | 122 | void SettingsDialog::fillPortsParameters() 123 | { 124 | ui->baudRateBox->addItem(QStringLiteral("4800"), QSerialPort::Baud4800); 125 | ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); 126 | ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); 127 | ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); 128 | ui->baudRateBox->addItem(QStringLiteral("57600"), QSerialPort::Baud57600); 129 | ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); 130 | ui->baudRateBox->addItem(tr("自定义")); 131 | ui->baudRateBox->setCurrentIndex(1); 132 | 133 | ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5); 134 | ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6); 135 | ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7); 136 | ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8); 137 | ui->dataBitsBox->setCurrentIndex(3); 138 | 139 | ui->parityBox->addItem(tr("None"), QSerialPort::NoParity); 140 | ui->parityBox->addItem(tr("Even"), QSerialPort::EvenParity); 141 | ui->parityBox->addItem(tr("Odd"), QSerialPort::OddParity); 142 | ui->parityBox->addItem(tr("Mark"), QSerialPort::MarkParity); 143 | ui->parityBox->addItem(tr("Space"), QSerialPort::SpaceParity); 144 | 145 | ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop); 146 | #ifdef Q_OS_WIN 147 | ui->stopBitsBox->addItem(tr("1.5"), QSerialPort::OneAndHalfStop); 148 | #endif 149 | ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop); 150 | 151 | ui->flowControlBox->addItem(tr("None"), QSerialPort::NoFlowControl); 152 | ui->flowControlBox->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl); 153 | ui->flowControlBox->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl); 154 | } 155 | 156 | void SettingsDialog::fillPortsInfo() 157 | { 158 | ui->serialPortInfoListBox->clear(); 159 | QString description; 160 | QString manufacturer; 161 | QString serialNumber; 162 | foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { 163 | QStringList list; 164 | description = info.description(); 165 | manufacturer = info.manufacturer(); 166 | serialNumber = info.serialNumber(); 167 | list << info.portName() 168 | << (!description.isEmpty() ? description : blankString) 169 | << (!manufacturer.isEmpty() ? manufacturer : blankString) 170 | << (!serialNumber.isEmpty() ? serialNumber : blankString) 171 | << info.systemLocation() 172 | << (info.vendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : blankString) 173 | << (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : blankString); 174 | 175 | ui->serialPortInfoListBox->addItem(list.first(), list); 176 | } 177 | 178 | ui->serialPortInfoListBox->addItem(tr("自定义")); 179 | } 180 | 181 | void SettingsDialog::updateSettings() 182 | { 183 | currentSettings.name = ui->serialPortInfoListBox->currentText(); 184 | 185 | if (ui->baudRateBox->currentIndex() == 4) { 186 | currentSettings.baudRate = ui->baudRateBox->currentText().toInt(); 187 | } else { 188 | currentSettings.baudRate = static_cast( 189 | ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt()); 190 | } 191 | currentSettings.stringBaudRate = QString::number(currentSettings.baudRate); 192 | 193 | currentSettings.dataBits = static_cast( 194 | ui->dataBitsBox->itemData(ui->dataBitsBox->currentIndex()).toInt()); 195 | currentSettings.stringDataBits = ui->dataBitsBox->currentText(); 196 | 197 | currentSettings.parity = static_cast( 198 | ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt()); 199 | currentSettings.stringParity = ui->parityBox->currentText(); 200 | 201 | currentSettings.stopBits = static_cast( 202 | ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt()); 203 | currentSettings.stringStopBits = ui->stopBitsBox->currentText(); 204 | 205 | currentSettings.flowControl = static_cast( 206 | ui->flowControlBox->itemData(ui->flowControlBox->currentIndex()).toInt()); 207 | currentSettings.stringFlowControl = ui->flowControlBox->currentText(); 208 | 209 | //currentSettings.localEchoEnabled = ui->localEchoCheckBox->isChecked(); 210 | } 211 | -------------------------------------------------------------------------------- /src/settingsdialog.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Denis Shienkov 4 | ** Copyright (C) 2012 Laszlo Papp 5 | ** Contact: http://www.qt.io/licensing/ 6 | ** 7 | ** This file is part of the QtSerialPort module of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL21$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and The Qt Company. For licensing terms 15 | ** and conditions see http://www.qt.io/terms-conditions. For further 16 | ** information use the contact form at http://www.qt.io/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 or version 3 as published by the Free 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 23 | ** following information to ensure the GNU Lesser General Public License 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** As a special exception, The Qt Company gives you certain additional 28 | ** rights. These rights are described in The Qt Company LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #ifndef SETTINGSDIALOG_H 36 | #define SETTINGSDIALOG_H 37 | 38 | #include 39 | #include 40 | 41 | QT_USE_NAMESPACE 42 | 43 | QT_BEGIN_NAMESPACE 44 | 45 | namespace Ui { 46 | class SettingsDialog; 47 | } 48 | 49 | class QIntValidator; 50 | 51 | QT_END_NAMESPACE 52 | 53 | class SettingsDialog : public QDialog 54 | { 55 | Q_OBJECT 56 | 57 | public: 58 | struct Settings { 59 | QString name; 60 | qint32 baudRate; 61 | QString stringBaudRate; 62 | QSerialPort::DataBits dataBits; 63 | QString stringDataBits; 64 | QSerialPort::Parity parity; 65 | QString stringParity; 66 | QSerialPort::StopBits stopBits; 67 | QString stringStopBits; 68 | QSerialPort::FlowControl flowControl; 69 | QString stringFlowControl; 70 | //bool localEchoEnabled; 71 | }; 72 | 73 | explicit SettingsDialog(QWidget *parent = 0); 74 | ~SettingsDialog(); 75 | 76 | Settings settings() const; 77 | 78 | private slots: 79 | void showPortInfo(int idx); 80 | void apply(); 81 | void checkCustomBaudRatePolicy(int idx); 82 | void checkCustomDevicePathPolicy(int idx); 83 | 84 | private: 85 | void fillPortsParameters(); 86 | void fillPortsInfo(); 87 | void updateSettings(); 88 | 89 | private: 90 | Ui::SettingsDialog *ui; 91 | Settings currentSettings; 92 | QIntValidator *intValidator; 93 | }; 94 | 95 | #endif // SETTINGSDIALOG_H 96 | -------------------------------------------------------------------------------- /src/settingsdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SettingsDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 395 10 | 292 11 | 12 | 13 | 14 | Settings 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 选择串口 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 描述: 32 | 33 | 34 | 35 | 36 | 37 | 38 | 厂家: 39 | 40 | 41 | 42 | 43 | 44 | 45 | 串口端口: 46 | 47 | 48 | 49 | 50 | 51 | 52 | 地址: 53 | 54 | 55 | 56 | 57 | 58 | 59 | 制造商ID: 60 | 61 | 62 | 63 | 64 | 65 | 66 | 产品ID: 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 串口参数配置 77 | 78 | 79 | 80 | 81 | 82 | 波特率: 83 | 84 | 85 | 86 | 87 | 88 | 89 | -1 90 | 91 | 92 | 93 | 94 | 95 | 96 | 数据位数: 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 奇偶校验: 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 停止位数: 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 控制流: 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | Qt::Horizontal 144 | 145 | 146 | 147 | 96 148 | 20 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 确定 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /src/tuner.pro: -------------------------------------------------------------------------------- 1 | QT += widgets serialport 2 | 3 | TARGET = tuner 4 | TEMPLATE = app 5 | 6 | SOURCES += \ 7 | main.cpp \ 8 | mainwindow.cpp \ 9 | settingsdialog.cpp \ 10 | form.cpp \ 11 | configdialog.cpp \ 12 | line.cpp \ 13 | commandline.cpp 14 | 15 | 16 | HEADERS += \ 17 | mainwindow.h \ 18 | settingsdialog.h \ 19 | form.h \ 20 | configdialog.h \ 21 | line.h \ 22 | commandline.h 23 | 24 | 25 | FORMS += \ 26 | mainwindow.ui \ 27 | settingsdialog.ui \ 28 | form.ui \ 29 | configdialog.ui 30 | 31 | RESOURCES += \ 32 | tuner.qrc 33 | 34 | DISTFILES += \ 35 | ../doc/todo.txt 36 | 37 | RC_ICONS = images/app.ico 38 | -------------------------------------------------------------------------------- /src/tuner.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/connect.png 4 | images/disconnect.png 5 | images/application-exit.png 6 | images/settings.png 7 | images/clear.png 8 | images/link.png 9 | images/link_off.png 10 | images/open.png 11 | images/save.png 12 | images/serial.png 13 | images/settings_new.png 14 | images/close.png 15 | images/app.ico 16 | images/help.png 17 | images/help_48dp.png 18 | config/save.json 19 | 20 | 21 | --------------------------------------------------------------------------------