讓串口調試助手像命令行同樣

說到嵌入式的實時系統,你們首先想到的是否是 聞名遐邇的 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:  函數

  1. 按方向下鍵不能看到下一條歷史記錄.

  2. 如今暫時不能發送 帶有\n 的字符串,也不能發送 HEX

  3. 若是光標在字符中間的時候按下了回車,那麼接收到的消息是會從光標處開始插入

 

發送字符給單片機的時候,是發送最後一行的字符.文本太長會自動換行顯示,可是仍然是一行.

以上的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;
View Code

 

若是按下了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;
View Code

 

若是按下了方向上鍵,不上移光標,而後判斷是否是最後一個的輸入記錄,若是是,直接在光標位置處插入上一次發送的文本,若是不是最後一個歷史記錄,刪除當前歷史的歷史記錄語句,插入更加前面一條歷史語句.

若是刪除時發現已經刪除到最後一行的開始,則刪除無效.

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                 }
View Code

 

恩,邏輯上仍是比較簡單的.每一個人均可以作到.

然而,爲了能用上好(裝)用(逼)的 shell 串口,咱們就要去移植一個rt-thread系統嗎? NO NO NO.小編也想到這個問題,因而乎,本身編寫了一個.c.h 文件,只需一個聲明,輸入字符串進入執行函數,就會自動調用你想要調用的函數.具體請期待明日更新哦.

 

RTOS [1]    Real Time  Operating System  實時操做系統,. 名稱是根據操做系統的工做特性而言的,實時是指物理進程的真實時間.  摘自百度百科 [RTOS]    且RTOS多爲搶佔式操做系統.

 爲了可以更好的交流,小編悄摸的申請了一個公衆號: 奔跑的程序猿 ,感興趣的能夠關注一波. 

相關文章
相關標籤/搜索