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

2022-08-31 15:31:12 浏览数 (1)

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

在使用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的文件,并将这个文件添加到工程中。

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

代码语言:javascript复制
#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,这个文件中包含了项目中所用到的操作系统和外设头文件。

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

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

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

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

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

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

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

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

代码语言:javascript复制
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次。编译下载文件。

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

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

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

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

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

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

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

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

函数的入参为 int argcchar**argv

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

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

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

在test.c 中添加代码

代码语言:javascript复制
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>'nn" );
        return;
    }
    if ( !rt_strcmp( argv[1], "start" ) )
    {
			  led_flag = 1;
        rt_kprintf( "The LED starts flashing!nn" );
    }
    else if ( !rt_strcmp( argv[1], "stop" ) )
    {
			  led_flag = 0;
        rt_kprintf( "The LED stop flashing!nn" );
    }
    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执行线程中添加标志位控制代码

代码语言:javascript复制
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

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

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

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

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

0 人点赞