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命令
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5068

    文章

    19008

    浏览量

    302976
  • Linux
    +关注

    关注

    87

    文章

    11219

    浏览量

    208872
  • 函数
    +关注

    关注

    3

    文章

    4303

    浏览量

    62411
  • 系统
    +关注

    关注

    1

    文章

    1006

    浏览量

    21310
收藏 人收藏

    评论

    相关推荐

    图形用户界面与命令行接口的比较

    在计算机科学和信息技术领域,用户与计算机交互的方式主要分为两种:图形用户界面(GUI)和命令行接口(CLI)。这两种界面各有优势和局限性,适用于不同的场景和用户需求。 1. 定义与基本特征 图形用户
    的头像 发表于 11-12 14:38 201次阅读

    shell具有的功能和特点

    Shell 是一个命令行解释器,用于与操作系统进行交互。它提供了一种方便的方式来执行命令、管理文件和目录、运行程序等。以下是 Shell
    的头像 发表于 08-30 14:48 352次阅读

    高效云端管理的秘诀——华为云命令行工具 KooCLI

    发现了云上命令行工具,我的云端管理效率从此得到了质的飞跃。 我从华为云官方产品帮助文档中了解了 KooCLI 工具,文档中介绍的便捷操作和高效管理让我心动不已,于是,我开启了我的体验。通过简单的命令行输入,我能够快速完成
    的头像 发表于 05-10 00:25 675次阅读
    高效云端管理的秘诀——华为云<b class='flag-5'>命令行</b>工具 KooCLI

    鸿蒙OpenHarmony南向:【Hi3516标准系统入门(命令行方式)】

    除小型系统外,Hi3516DV300开发板还支持标准系统。此章节简要介绍如何使用命令行在Hi3516DV300开发板上进行标准系统的开发。
    的头像 发表于 05-08 09:26 813次阅读
    鸿蒙OpenHarmony南向:【Hi3516标准系统入门(<b class='flag-5'>命令行</b>方式)】

    HarmonyOS开发:【基于命令行(安装库和工具集)】

    使用命令行进行设备开发时,可以通过以下步骤安装编译OpenHarmony需要的库和工具。
    的头像 发表于 04-25 21:03 365次阅读
    HarmonyOS开发:【基于<b class='flag-5'>命令行</b>(安装库和工具集)】

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

    要在CentOS上切换命令行和桌面环境,您可以通过以下步骤进行: 1、安装桌面环境:如果您的CentOS VPS上还没有安装图形桌面环境,您需要安装一个。一般来说,常用的桌面环境有GNOME、KDE
    的头像 发表于 04-10 17:41 568次阅读

    人机交互的三个阶段 人机交互的常用方式

    交互经历的三个阶段:命令行界面交互阶段、图形用户界面交互阶段、自然和谐的人机交互阶段。
    的头像 发表于 03-13 17:25 2769次阅读

    tasking的命令行控制中如何生成makefiles文件?

    tasking的命令行控制中如何生成makefiles文件?
    发表于 02-06 07:56

    在Linux上如何通过命令行来更改日期和时间?

    在Linux上如何通过命令行来更改日期和时间? 在Linux上,我们可以使用命令行工具来更改日期和时间。操作系统中有一个专门的命令被称为“date”命令,它允许我们更改系统的当前日期和
    的头像 发表于 01-16 17:10 2732次阅读

    如何在ELF 1开发板实现命令行显示中文

    自busybox1.17.0以后的版本对中文的支持进行了限制,命令行不做修改是无法显示中文的。今天小编就带各位小伙伴了解一下如何实现在busybox1.17.0以上版本对命令行显示中文的支持。步骤一
    的头像 发表于 12-06 16:07 516次阅读
    如何在ELF 1开发板实现<b class='flag-5'>命令行</b>显示中文

    idea如何输入命令行参数

    在许多软件开发和系统管理的任务中,我们经常需要向应用程序传递命令行参数。命令行参数是在运行时传递给程序的值,用于指定程序的行为和配置选项。本文将详细介绍如何在不同的编程语言和操作系统中输入命令行参数
    的头像 发表于 12-06 15:01 1072次阅读

    eclipse怎么使用命令行

    命令行中使用Eclipse来完成一些特定的任务。本文将详细介绍如何在命令行中使用Eclipse。 首先,我们需要确保已经正确安装了JDK(Java Development Kit)和Eclipse
    的头像 发表于 12-06 11:26 2414次阅读

    Uboot启动延时和读取命令行输入

    就会中断等待,进入命令行输入模式。 如果没有配置启动延时功能或者启动延时超过了设置的时间, U-Boot 运行启动命令行参数,启动命令参数在顶层配置文件中,由 CONFIG_BOOTCOMMAND 宏定义。 2.读取
    的头像 发表于 12-04 17:16 1480次阅读

    python shell怎么用

    Python Shell是一种交互式解释器,可以通过命令行直接运行Python代码。在Shell中,可以输入一行代码并立即得到结果,非常适合于测试、尝试新代码或进行简单的任务。本文将详
    的头像 发表于 11-29 14:36 1098次阅读

    如何在命令行中配置DDS

    DDS这么好,那该如何配置和使用呢?我们先带大家入个门。 案例一:在命令行中配置DDS 我们先来试一试在命令行中配置DDS的参数。 启动第一个终端,我们使用best_effort创建一个发布者节点
    的头像 发表于 11-24 18:03 930次阅读
    如何在<b class='flag-5'>命令行</b>中配置DDS