说到嵌入式的实时系统,你们首先想到的是否是 闻名遐迩的 UCOS 呢? UCOS 简单,易移植,在关键部分移植汇编语言,是入坑 RTOS [1]的不二选择.接触了一段时间以后,偶然在网上看到,原子哥(正点原子) 的开源教材里头也有介绍 RT-Thread OS 系统,而后开始了解和使用Rt-thread. 它的优点是:商用无风险,不限任务个数,各类协议栈齐全(尤为在 IoT方面),兼容部分POSIX接口(linux接口).java
图片来自网络截图侵删linux
RT-thread 是一个中国人本身开发的开源的RTOS ,借鉴了linux的部分想法.甚至能够复用linux的驱动接口.同时高度可裁剪和丰富的协议栈.固然如今的菜鸟小编都用不到这些. 但是有一个功能小编但是眼红的很,那就是它的 串口 shell 功能,让单片机跟电脑的命令行同样执行命令.git
用过gcc 或者java 的小伙伴都知道,能够直接在命令行敲 gcc *.c 或者javac *.java 就能够直接编译文件, 这个 gcc javac 就是我们的*.exe 文件,那么在单片机里,我定义了一个 printcircle (int r);这个函数,那么咱们可不能够直接在串口助手里给单片机发信息: printcircle 30 \n 是否是他就能够执行printcirc这个函数而且r = 30 呢? 答案固然是能够的.github
rt-thread 中的shell 就能够作到.而且更加完善.可是单片机支持这样的命令行操做,但是我们的串口助手并不能像cmd窗口同样啊.著名的Xcom 串口调试软件,不支持这个功能.因而我萌生了作一个上位机适配这个shell 的想法.shell
个人想法很简单,就是作一个窗口尽可能让他像咱们的命令行. 可是串口仍是须要扫描,检查串口.因此我在最下面增长了几个按钮.同时尽可能关联快捷键.尽可能作到少操做鼠标.通过几天的打磨,思考,如今已经有点样子了.有须要的同窗能够移步:数组
Github: https://github.com/KimAlittleStar/UART_SHELL网络
程序下载: https://github.com/KimAlittleStar/UART_SHELL/releasesapp
百度云: https://pan.baidu.com/s/12Soblpsm5CUIeg1eEZEp1Q 提取码: hyhnide
软件说明:按下回车就是发送消息.方向上键是发送消息的历史记录.有如下几个BUG: 函数
按方向下键不能看到下一条历史记录.
如今暂时不能发送 带有\n 的字符串,也不能发送 HEX
若是光标在字符中间的时候按下了回车,那么接收到的消息是会从光标处开始插入
发送字符给单片机的时候,是发送最后一行的字符.文本太长会自动换行显示,可是仍然是一行.
以上的bug我还在修,由于如今是在实习工做,可能修bug 的速度会慢一些.Ps:win10/win7 64bit 实测可用.
接下来是里面的一些具体的逻辑想法:
首先UI界面布局,这个不赘述,须要注意的就是使用*.ui文件的时候注意将你须要用到的对象的名称修改掉,否则你可能过了几天,你就不记得你的变量名那个是哪一个了.没错我就经历过.
以后 开启串口.
void Widget::openprot() { if(activePort->isOpen()) //若是串口打开着就关闭 { // activePort->clear(); activePort->close(); ui->pushButton_2->setText("打开串口"); ui->tLine_message->setText("串口"+ui->cBox_Portlist->currentText()+"已关闭"); }else{ //关闭着就打开 activePort->setPortName(ui->cBox_Portlist->currentText()); if(activePort->open(QIODevice::ReadWrite)== true) { int a = ui->cBox_Baudlist->currentText().toInt(); activePort->setBaudRate(a,QSerialPort::AllDirections);//设置波特率和读写方向 activePort->setDataBits(QSerialPort::Data8); //数据位为8位 activePort->setFlowControl(QSerialPort::NoFlowControl);//无流控制 activePort->setParity(QSerialPort::NoParity); //无校验位 activePort->setStopBits(QSerialPort::OneStop); //一位中止位 ui->tLine_message->setText(ui->cBox_Portlist->currentText()+"打开成功"); connect(activePort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); ui->pushButton_2->setText("关闭串口"); ui->tEdit_shell->setFocus(); }else { ui->tLine_message->setText("打开失败,检查串口是否被占用"); ui->pushButton_2->setText("打开串口"); } } }
监听按键,若是按键按到了 方向上 下 和enter键那么就执行相应的操做.同时我 也预留了一个 tab 键,为之后自定义关键字,作到字符按提示.
1 if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Up) { 2 QTextCursor tc = ui->tEdit_shell->textCursor(); 3 4 if(history.size() == 0) return true;//若是没有历史记录,则不操做 5 6 if(historyNum != history.size())//若是当前不是第一次按上键,则要删除上一次补全的历史记录 7 { 8 if(historyNum == 0) 9 tc.movePosition(QTextCursor::Left,QTextCursor::KeepAnchor,history[0].length()); 10 else { 11 tc.movePosition(QTextCursor::Left,QTextCursor::KeepAnchor,history[historyNum].length()); 12 } 13 tc.removeSelectedText(); 14 } 15 if(historyNum == 0) 16 historyNum = history.size(); 17 18 ui->tEdit_shell->insertPlainText(history[historyNum-1]); //插入上一个输入的历史记录 19 qout<<history[historyNum-1]<<"history size "<< history.length(); 20 historyNum--; 21 qout<<"使用上一个记录"<<endl; 22 23 return true;
若是按下了enter 把最后一行的文本获取到,用串口发送出去,将发出去的字符写入一个数组,记录下来以便提供历史记录
1 if(k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter) 2 { 3 txtcur.movePosition(QTextCursor::End,QTextCursor::MoveAnchor); 4 txtcur.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor); 5 txtcur.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor); 6 QString msg = txtcur.selectedText(); 7 history.append(msg); 8 sendText(msg); 9 10 historyNum = history.size(); 11 ui->tEdit_shell->append(""); 12 return true;
若是按下了方向上键,不上移光标,而后判断是否是最后一个的输入记录,若是是,直接在光标位置处插入上一次发送的文本,若是不是最后一个历史记录,删除当前历史的历史记录语句,插入更加前面一条历史语句.
若是删除时发现已经删除到最后一行的开始,则删除无效.
1 if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Backspace) { 2 QTextCursor tc = ui->tEdit_shell->textCursor(); 3 int oldposition = tc.position(); 4 tc.movePosition(QTextCursor::StartOfLine); 5 if((tc.blockNumber()+1) == maxline && oldposition == tc.position()) 6 { 7 return true; 8 }
恩,逻辑上仍是比较简单的.每一个人均可以作到.
然而,为了能用上好(装)用(逼)的 shell 串口,咱们就要去移植一个rt-thread系统吗? NO NO NO.小编也想到这个问题,因而乎,本身编写了一个.c.h 文件,只需一个声明,输入字符串进入执行函数,就会自动调用你想要调用的函数.具体请期待明日更新哦.
RTOS [1] Real Time Operating System 实时操做系统,. 名称是根据操做系统的工做特性而言的,实时是指物理进程的真实时间. 摘自百度百科 [RTOS] 且RTOS多为抢占式操做系统.
为了可以更好的交流,小编悄摸的申请了一个公众号: 奔跑的程序猿 ,感兴趣的能够关注一波.