RT-Thread中自定义 FinSH 命令「建议收藏」

RT-Thread中自定义 FinSH 命令「建议收藏」在使用RT-Thread中的FinSH命令时,除了系统默认的FinSH命令以外,我们还可以自定义FinSH命令。下面就来演示一下如何自定义FinSH命令。关于FinSH命令的详细用法请参考官方资料https://www.rt-thread.org/document/site/programming-manual/finsh/finsh/。要使用FinSH命令首先要添加FinSH组件,添加组件的详细过程见手把手教你移植RT-Thread系统,FinSH组件添加成后,打开建立…

大家好,又见面了,我是你们的朋友全栈君。

       在使用RT-Thread中的FinSH 命令时,除了系统默认的FinSH命令以外,我们还可以自定义FinSH命令。下面就来演示一下如何自定义FinSH命令。关于FinSH命令的详细用法请参考官方资料https://www.rt-thread.org/document/site/programming-manual/finsh/finsh/

       要使用FinSH 命令首先要添加FinSH组件,添加组件的详细过程见手把手教你移植RT-Thread系统,FinSH组件添加成后,打开建立好的工程,在工程中USER文件夹下新建一个test.c的文件,并将这个文件添加到工程中。

RT-Thread中自定义 FinSH 命令「建议收藏」

然后在test.c中间中添加一个简单的测试代码

#include "board.h"

void test_hello( void )
{
    rt_kprintf( "this is test hello!\n" );
}

MSH_CMD_EXPORT( test_hello, say hello to RT - Thread );

添加头文件board.h,这个文件中包含了项目中所用到的操作系统和外设头文件。

RT-Thread中自定义 FinSH 命令「建议收藏」

       下面新建一个函数,这个函数实现的功能就是打印一句话,用它来简单的测试一下,我们自定义的命令。

最后一行代码是自定义FinSH 命令的关键代码,MSH_CMD_EXPORT()函数用于将用户自定义的命令导出。这个函数的原型在官网中有说明。

RT-Thread中自定义 FinSH 命令「建议收藏」

        第一个参数是要导出命令的名字,在这里指的是自定义的函数名。这个名字必须和函数名要一样,否则命令就不会正确执行。同时要注意这个函数名不能和工程中其他函数同名,否则在执行命令时会出错。第二个命令是自定义命令的描述,实际上是一个字符串,可以随便写。

       自定义FinSH 命令就完成了,就是这么简单。这个函数不需要在系统中初始化,也不需要在其他地方调用。只要用MSH_CMD_EXPORT()函数注册之后,这个函数在变系统编译的时候,就会自动添加到FinSH 命令的列表中。使用的时候可以在控制台上调用。下来打开控制台,编译下载程序。

RT-Thread中自定义 FinSH 命令「建议收藏」

控制台上打印出系统信息,下来按一下键盘上的Tab键,就会打印出当前支持的所有命令。

RT-Thread中自定义 FinSH 命令「建议收藏」

第一个命名就是test_hello命令,说明自定义的命令注册成功了。在控制台上输入test_hello,然后按回车键。

RT-Thread中自定义 FinSH 命令「建议收藏」

字符串打印成功,说明自定义的函数已经成功运行了。

用同样的方式,在test.c文件中再添加两个函数并注册测试一下。

void test_hello( void )
{
    rt_kprintf( "this is test hello!\n" );
}
MSH_CMD_EXPORT( test_hello, say hello to RT - Thread );

void test1( void )
{
    rt_int8_t i;
    for( i = 0; i < 3; i++ )
        rt_kprintf( "test %d!\n", i );
}
MSH_CMD_EXPORT( test1, test1 to RT - Thread );

void test2( void )
{
    rt_int8_t i = 10;
    while( i )
    {
        LED2_TOGGLE;
        rt_thread_delay( 500 );
        i--;
    }
}
MSH_CMD_EXPORT( test2, test1 to RT - Thread );

又添加了test1和test2两个函数,test1循环打印3次,test2让LED2翻转10次。编译下载文件。

RT-Thread中自定义 FinSH 命令「建议收藏」

在控制台上可以看到自定义的3个命令都出现了,挨个测试下。

RT-Thread中自定义 FinSH 命令「建议收藏」

        test_hello和test1打印数据成功,test2是翻转LED指示灯的状态,在控制台上看不到效果。但是在开发板上可以看到LED2闪烁。说明自定义的3个命令都成功了。

        在这里要注意一个问题,自定义的函数不能是死循环,由于这个函数是有控制台调用的,如果自定义了一个死循环的话,控制台调用这个函数之后也就进入死循环了。如果这时候想要在控制台上输入其他命名的话,就输入不了了。

       比如,这里将test2中的while循环设置为死循环。

RT-Thread中自定义 FinSH 命令「建议收藏」

编译下载代码,并在控制台上执行test2命令。

RT-Thread中自定义 FinSH 命令「建议收藏」

        这时会发现控制台的光标会一直在那闪烁,键盘输入指令时没有任何反应。说明控制台程序已经进入死循环中了。所以在使用FinSH 自定义命令时函数体必须为有限的循环,不能为无限循环。

        自定义命令还支持带参数的命令,下面再添加一个带参数的函数。在test.c中添加下面的代码。

static void test_cmd( int argc, char**argv )
{
    if ( argc < 2 )
    {
        rt_kprintf( "Please input'test_cmd <cmd1|cmd2>'\n\n" );
        return;
    }
    if ( !rt_strcmp( argv[1], "cmd1" ) )
    {
        rt_kprintf( "cmd1 command test!\n\n" );
    }
    else if ( !rt_strcmp( argv[1], "cmd2" ) )
    {
        rt_kprintf( "cmd2 command test!\n\n" );
    }
    else
    {
        rt_kprintf( "Please input'test_cmd <cmd1|cmd2>'\n	\n" );
    }
}
MSH_CMD_EXPORT( test_cmd, cmd sample:test_cmd < cmd1 | cmd2 > );

   函数的入参为 int argc 和 char**argv

       1、argc是命令行总的参数个数,argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数。
       2、char *argv[]是一个字符数组,其大小是int argc,主要用于命令行参数argv[]参数,数组里每个元素代表一个参数     

       最后使用MSH_CMD_EXPORT()函数注册带参数的命令函数。编译下载工程,然后在控制台上输入”test_cmd cmd1″给函数传递cmd1命令,然后在输入”test_cmd cmd2″给函数传递cmd2命令,控制台上打印出的字符串和测试函数中相同,说明带参数的命令注册也成功了。

RT-Thread中自定义 FinSH 命令「建议收藏」

      通过这个带命令的功能可以用来调试代码,在程序运行过程中通过外部命令改变函数的某个参数,来控制程序执行的过程。这里就用LED闪烁的例子来演示,比如可以在控制台发送 statrt 命令,让LED灯开始闪烁,发送stop的命令让LED停止闪烁。LED的闪烁是在LED线程中执行的,那么如何通过命令去控制LED线程呢?这里可以使用一个标志位控制,在LED线程运行过程中实时监测标志位的值。当标志位为1时,闪烁 LED灯,当标志位值为0时,停止闪烁 LED 灯。然后在命令函数中只需要改变标志位的值就行了。

     在test.c 中添加代码

extern rt_int8_t led_flag;

//在控制台上输入  test_cmd cmd1 就会打印出对应的输出
static void led_cmd( int argc, char**argv )
{
    if ( argc < 2 )
    {
        rt_kprintf( "Please input'led_cmd <start|stop>'\n\n" );
        return;
    }
    if ( !rt_strcmp( argv[1], "start" ) )
    {
			  led_flag = 1;
        rt_kprintf( "The LED starts flashing!\n\n" );
    }
    else if ( !rt_strcmp( argv[1], "stop" ) )
    {
			  led_flag = 0;
        rt_kprintf( "The LED stop flashing!\n\n" );
    }
    else
    {
        rt_kprintf( "Please input'led_cmd <start|stop>'\n	\n" );
    }
}
MSH_CMD_EXPORT( led_cmd, cmd sample:led_cmd < start | stop > );

       通过start和stop的命令来设置标志位的值

       在主函数的LED执行线程中添加标志位控制代码

static void led1_thread_entry( void* parameter )
{
    while ( 1 )
    {
        if( led_flag )
        {
            LED1_ON;
            rt_thread_delay( 500 ); /* 延时500个tick */
            LED1_OFF;
            rt_thread_delay( 500 ); /* 延时500个tick */
        }
        else
        {
            rt_thread_delay( 1000 ); /* 延时500个tick */
        }
    }
}

       在LED线程中根据标志位来选则是否闪烁LED

      编译下载代码,然后在控制台上输入命令

RT-Thread中自定义 FinSH 命令「建议收藏」

       在控制台上输入 led_cmd 命令后,开发板上的LED灯开始闪烁,在控制台上输入led_cmd stop命令后,开发板上的LED灯停止闪烁。这样通过控制台命令,来控制程序的执行流程。这样在调试代码的时候,就可以实时改变系统某些参数,方便代码的调试与监控。

工程代码下载地址 在rt-thread实时系统上自定义Finsh命令

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143237.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号