衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

單片機上如何做shell命令行交互

麥辣雞腿堡 ? 來源:嵌入式軟件那些事 ? 作者:靜以修身 ? 2023-11-01 15:16 ? 次閱讀

做過嵌入式Linux開發或使用過桌面Linux系統的童鞋們,肯定對shell命令交互印象比較深刻,然而我們大多數搞嵌入式軟件開發的碼農都是基于單片機,比如51、STM32等進行開發的,在單片機上能否做個shell命令行交互?答案當然是可以的,在網上類似的文章和代碼一搜一籮筐, 基本原理: 監測用戶的輸入,然后到一個命令查找表里過濾是否可以找到該命令,如果可以則調用對應的處理函數,當然做的好點的話還可以向處理函數傳遞參數

主要的數據結構及解析函數定義如下,注意這里函數指針的定義,Argc代表參數的個數,可以為0、1、2...,Argv用于存放具體的參數,可能有些童鞋要問為啥定義成CHAR **,這是因為我們在shell交互窗口輸入的內容都會被當作ASCII碼字符串,所以只能用CHAR *來指向它們,另外又因為我們可能會輸入多個字符串參數(多個參數以空格進行間隔),所以要使用二級指針CHAR **,可能有的同學會發現,我們平時見的標準main函數的原型就是這樣定義的

int main(int argc, char *argv[])

char *argv[]與char **argv是等價的,這個就不需要解釋了吧,采用這種定義方式可以非常靈活,具體見下面的用法示例:

#define SHELL_MAX_PARA_NUM      20                         //最多支持20個命令參數


// 函數指針
typedef UINT8 (* Cmd_Analys_Fun_P)(UINT8 Argc, CHAR **Argv);


typedef struct
{
    CHAR *pName;
    Cmd_Analys_Fun_P pCmdFunc;    // 命令解析函數
} S_Shell_Cmd;


/***************************************************************
* 函數名稱: Shell_Proc
* 功能描述: Shell交互處理
* 輸入參數: 
* 輸出參數: 
* 返 回 值: 
****************************************************************/
UINT8 Shell_Proc(CHAR *ucCmd, UINT8 ucCmdLength)
{
    UINT8 Result;


    Result = Cmd_Analys(Shell_Cmd, S_NUM(Shell_Cmd), ucCmd, ucCmdLength);
    if ((Result EQ 1) || (Result EQ 2))
    {
        //vConsoleLog("[shell]#");
    }


    return Result;
}


/***************************************************************
* 函數名稱: Cmd_Analys
* 功能描述: 命令解析
* 輸入參數: 
* 輸出參數: 
* 返 回 值:  
****************************************************************/
LOCAL UINT8 Cmd_Analys(CONST S_Shell_Cmd Shell_Cmd[], UINT8 Num, CHAR Cmd[], UINT8 Len)
{
    UINT8 i, j;
    UINT8 Argc, Cmd_Len;
    CHAR  *(Argv[SHELL_MAX_PARA_NUM]);


    Cmd_Len = 0;
    for (i = 0; i < Len; i++)
    {
        if ((Cmd[i] EQ 'r') || (Cmd[i] EQ 'n')) // 找到回車換行鍵, 說明已經輸入了一條完整命令
        {
            Cmd_Len = i;            // 記錄命令長度
            Cmd[i] = '?';
            break;
        }
        else if (Cmd[i] EQ ' ')     // 空格全部替換成'?'
        {
            Cmd[i] = '?';
        }
    }


    if (i EQ Len)                   // 沒有找到命令
    {
        return 0;
    }


    if (Cmd_Len EQ 0)               // 全部輸入的是空格或者回車
    {
        vConsoleLog("rnShell:");  // 提示輸入新的命令
        return 1;
    }


    for (i = 0; i < Num; i++)
    {
        if (strcmp(Shell_Cmd[i].pName, Cmd) != 0)
        {
            continue;
        }


        j = (UINT8)strlen(Cmd);
        Argc = 0;
        while (j < Cmd_Len)
        {
            if (Cmd[j] EQ '?' && Cmd[j + 1] != '?') // 前一個是空格,后一個非空格,說明是一個新參數
            {
                if (Argc < SHELL_MAX_PARA_NUM)
                {
                    Argv[Argc] = &Cmd[j + 1];
                    Argc++;
                }
                else
                {
                    break;
                }
            }


            j++;
        }


        // 執行命令
        (*Shell_Cmd[i].pCmdFunc)(Argc, Argv);
        break;
    }


    if (i EQ Num)
    {
        vConsoleLog("Cmd Error!");
        return 2;
    }


    return 1;
}

**用法1:**只有命令,沒有參數

/***************************************************************
* 函數名稱: RebootTerminal
* 功能描述: 重啟終端
* 輸入參數: 
* 輸出參數: 
* 返 回 值: 
****************************************************************/
LOCAL UINT8 RebootTerminal(UINT8 argc, CHAR **argv)
{
    //發起復位請求
    udwResetTimeCounter = 0;
    blResetRequestFlag  = TRUE;
    vConsoleLog("Terminal Prepare Reboot ...");


    return 1;
}

**用法2:**命令+1個參數

/***************************************************************
* 函數名稱: ConsoleOutputRedirect
* 功能描述: console輸出重定向
* 輸入參數: 
* 輸出參數: 
* 返 回 值: 
****************************************************************/
LOCAL UINT8 ConsoleOutputRedirect(UINT8 argc, CHAR **argv)
{
    if (argc != 1)
    {
        vConsoleLog("miss argumentrn");
        return 0;
    }

    if (!strcmp(argv[0], "on"))
    {
        ucConsoleRedirectFlag = 1;
        vConsoleLog("console output redirect to tcpconsolern");
    }
    else if (!strcmp(argv[0], "off"))
    {
        ucConsoleRedirectFlag = 0;
        vConsoleLog("console output redirect to localconsolern");
    }
    else
    {
        vConsoleLog("error argumentrn");
        return 0;
    }


    return 1;
}

**用法3:**命令+N個參數

/***************************************************************
* 函數名稱: SetTerminalTime
* 功能描述: 設置終端時間
* 輸入參數: 
* 輸出參數: 
* 返 回 值: 
****************************************************************/
LOCAL UINT8 SetTerminalTime(UINT8 argc, CHAR **argv)
{
    UINT8 ucTime[6];


    if (argc != 6)
    {
        vConsoleLog("Param Err! argc = %d", argc);
        return 0;
    }


    ucTime[0] = strtoul(argv[0], NULL, 0);
    ucTime[1] = strtoul(argv[1], NULL, 0);
    ucTime[2] = strtoul(argv[2], NULL, 0);
    ucTime[3] = strtoul(argv[3], NULL, 0);
    ucTime[4] = strtoul(argv[4], NULL, 0);
    ucTime[5] = strtoul(argv[5], NULL, 0);


    ucTimeTestFlag = 1;


    stCurrentTime.ucYear  = ucTime[0];
    stCurrentTime.ucMonth = ucTime[1];
    stCurrentTime.ucDay   = ucTime[2];
    stCurrentTime.ucHour  = ucTime[3];
    stCurrentTime.ucMin   = ucTime[4];
    stCurrentTime.ucSec   = ucTime[5];


    vConsoleLog("SetTerminalTime: %02d/%02d/%02d %02d:%02d:%02d", ucTime[0], ucTime[1], ucTime[2], 
                                                                  ucTime[3], ucTime[4], ucTime[5]);


    return 1;
}

以上三種用法,基本可以涵蓋現實中的各種使用需求!

以上就是shell命令的基本用法,至于如何捕捉用戶的輸入,方式和方法就很多了,不過常用的就下面的幾種情況:

  1. 終端設備上的串口(這種最常見)
  2. 終端設備上的網口(稍微有點門檻,后面會專門寫一篇STM32的文章介紹這種用法)
  3. 如果終端設備已經登錄了后臺主站云平臺,直接在云平臺上給終端設備下發shell命令
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5092

    文章

    19178

    瀏覽量

    307697
  • Linux
    +關注

    關注

    87

    文章

    11345

    瀏覽量

    210401
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62977
  • 系統
    +關注

    關注

    1

    文章

    1019

    瀏覽量

    21431
收藏 人收藏

    評論

    相關推薦

    curl wget bond:深入解析命令行工具的差異與應用場景

    curl curl 是一個用于與服務器進行數據傳輸的命令行工具。它支持多種協議,包括 HTTP、HTTPS、 FTP 等。 基本用法 獲取網頁內容: curl http://example.com
    的頭像 發表于 01-24 09:20 ?75次閱讀

    圖形用戶界面與命令行接口的比較

    在計算機科學和信息技術領域,用戶與計算機交互的方式主要分為兩種:圖形用戶界面(GUI)和命令行接口(CLI)。這兩種界面各有優勢和局限性,適用于不同的場景和用戶需求。 1. 定義與基本特征 圖形用戶
    的頭像 發表于 11-12 14:38 ?547次閱讀

    Mobaxterm 的命令行使用方法

    的遠程桌面協議(如RDP和VNC),以及文件傳輸協議(如FTP和SFTP)。本文將詳細介紹如何使用Mobaxterm的命令行功能。 2. 安裝 Mobaxterm 在開始之前,確保你已經安裝
    的頭像 發表于 11-11 09:08 ?2076次閱讀

    Linux系統中shell命令解析

    shell是Linux系統的用戶界面,提供了用戶與內核交互的一種接口,它接收用戶輸入的命令并到送到內核去執行,因此也被稱為Linux的命令解釋器。
    的頭像 發表于 11-05 15:40 ?379次閱讀

    APM32F411板的python+pyocd命令行操作

    前段時間學習了一下如何使用pyocd配合APM32F411VCTINY板在命令行下給它進行各種騷操作,在使用一段時間后就想著:pyocd是基于python的,那是不是也可以使用python腳本+pyocd使用起來呢?
    的頭像 發表于 10-18 16:21 ?438次閱讀
    APM32F411板的python+pyocd<b class='flag-5'>命令行</b>操作

    shell具有的功能和特點

    Shell 是一個命令行解釋器,用于與操作系統進行交互。它提供了一種方便的方式來執行命令、管理文件和目錄、運行程序等。以下是 Shell
    的頭像 發表于 08-30 14:48 ?696次閱讀

    使用idf4.3在命令行打開menuconfig,如何才能開啟lwip配置界面?

    請問使用idf4.3在命令行打開menuconfig,如何才能開啟lwip配置界面。
    發表于 06-21 06:08

    鴻蒙ArkUI-X跨平臺開發:【命令行工具(ACE Tools)】

    ACE Tools是一套為ArkUI-X項目跨平臺應用開發者提供的命令行工具,支持在Windows/Ubuntu/macOS平臺運行,用于構建OpenHarmony/HarmonyOS、Android和iOS平臺的應用程序,其功能包括開發環境檢查,新建項目,編譯打包,安裝調試等。
    的頭像 發表于 05-21 17:39 ?1988次閱讀
    鴻蒙ArkUI-X跨平臺開發:【<b class='flag-5'>命令行</b>工具(ACE Tools)】

    高效云端管理的秘訣——華為云命令行工具 KooCLI

    發現了云上命令行工具,我的云端管理效率從此得到了質的飛躍。 我從華為云官方產品幫助文檔中了解了 KooCLI 工具,文檔中介紹的便捷操作和高效管理讓我心動不已,于是,我開啟了我的體驗。通過簡單的命令行輸入,我能夠快速完成
    的頭像 發表于 05-10 00:25 ?736次閱讀
    高效云端管理的秘訣——華為云<b class='flag-5'>命令行</b>工具 KooCLI

    鴻蒙OpenHarmony南向:【Hi3516標準系統入門(命令行方式)】

    除小型系統外,Hi3516DV300開發板還支持標準系統。此章節簡要介紹如何使用命令行在Hi3516DV300開發板上進行標準系統的開發。
    的頭像 發表于 05-08 09:26 ?942次閱讀
    鴻蒙OpenHarmony南向:【Hi3516標準系統入門(<b class='flag-5'>命令行</b>方式)】

    STM8 flash loader命令行調用錯誤的原因?

    [td]我目前在用flash loader的命令行,編寫自己的上位機軟件來升級程序,但是在用命令行調用的時候一直出錯,有人能幫忙分析下嗎? 我編寫的bat文件
    發表于 05-06 07:23

    HarmonyOS開發:【基于命令行(安裝庫和工具集)】

    使用命令行進行設備開發時,可以通過以下步驟安裝編譯OpenHarmony需要的庫和工具。
    的頭像 發表于 04-25 21:03 ?482次閱讀
    HarmonyOS開發:【基于<b class='flag-5'>命令行</b>(安裝庫和工具集)】

    香港vps的centos如何切換命令行和桌面?

    要在CentOS上切換命令行和桌面環境,您可以通過以下步驟進行: 1、安裝桌面環境:如果您的CentOS VPS上還沒有安裝圖形桌面環境,您需要安裝一個。一般來說,常用的桌面環境有GNOME、KDE
    的頭像 發表于 04-10 17:41 ?712次閱讀

    STM32G070RB使用jlink命令行下載無法識別芯片怎么解決?

    STM32G070RB 使用jlink命令行下載無法識別芯片,想手動添加芯片,請問哪里可以下載驅動.elf文件 或者有什么方法能夠實現jlink命令行下載
    發表于 04-02 06:15

    人機交互的三個階段 人機交互的常用方式

    交互經歷的三個階段:命令行界面交互階段、圖形用戶界面交互階段、自然和諧的人機交互階段。
    的頭像 發表于 03-13 17:25 ?3382次閱讀
    功夫百家乐的玩法技巧和规则 | 百家乐官网规则澳门| 百家乐黏土筹码| 百家乐稳赚秘籍| 真人百家乐官网源代码| 荔波县| 百家乐接线玩法| 皇冠网上69691| 大发888 迅雷快传| 找查百家乐玩法技巧| 百家乐玩法窍门| 百家乐官网平注胜进与负追| 凉城县| 998棋牌游戏| 百家乐免费体验金| 百家乐的路怎样看| 送58百家乐官网的玩法技巧和规则| 怎么玩百家乐官网能赢钱| 博盈| 大发888娱乐总代理qq| 博彩百家乐字谜总汇| 刀把状的房子做生意| 网上百家乐官网打牌| 澳门百家乐官网娱乐城开户| 娱乐城注册送38| 娱乐城开户送现金| 太阳城娱乐网88| 模拟百家乐的玩法技巧和规则| 云鼎百家乐官网代理| 百家乐官网存1000送| 百家乐官网娱乐城备用网址| 南宫市| 维多利亚娱乐| 博彩论坛18good| 大发888亚洲| 威尼斯人娱乐城老品牌值得您信赖lm0| 百家乐电子路单谁| 澳门百家乐的赢钱不倒翁| 皇冠百家乐皇冠网| 百家乐官网网上赌局| 百家乐官网游戏机的玩法|