前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RT-Thread中自定义 FinSH 命令「建议收藏」

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

作者头像
全栈程序员站长
发布2022-08-31 15:31:12
7640
发布2022-08-31 15:31:12
举报

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

在使用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 命令「建议收藏」
RT-Thread中自定义 FinSH 命令「建议收藏」

然后在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,这个文件中包含了项目中所用到的操作系统和外设头文件。

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

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

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

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

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

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

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

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

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

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

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

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

用同样的方式,在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次。编译下载文件。

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

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

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

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

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

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

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

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

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

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

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

代码语言:javascript
复制
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 argcchar**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 命令「建议收藏」
RT-Thread中自定义 FinSH 命令「建议收藏」

通过这个带命令的功能可以用来调试代码,在程序运行过程中通过外部命令改变函数的某个参数,来控制程序执行的过程。这里就用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>'\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执行线程中添加标志位控制代码

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

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

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

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档