說到嵌入式的實時系統,你們首先想到的是否是 聞名遐邇的 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多爲搶佔式操做系統.
爲了可以更好的交流,小編悄摸的申請了一個公衆號: 奔跑的程序猿 ,感興趣的能夠關注一波.