在使用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中间中添加一个简单的测试代码

#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文件中再添加两个函数并注册测试一下。

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中添加下面的代码。

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命令,控制台上打印出的字符串和测试函数中相同,说明带参数的命令注册也成功了。

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

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

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

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

RT-Thread中自定义 FinSH 命令相关推荐

  1. RT-Thread中自定义MSH命令传入的参数是字符串,需用户自行检查和解析

    如下是在将安富莱的dac8563模块对接到潘多拉开发板RT-Thread SPI设备框架中时导出到RT-Thread的自定义MSH命令,需要注意的是MSH传入的是字符串,需要自行对字符串进行解析处理. ...

  2. bsd协议开源框架tcp服务器,搬运RT Thread中BSD Socket实现UDP及TCP例子

    /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * ...

  3. 关于RT thread系统节拍时钟的配置

    关于RT thread系统节拍时钟的配置                  -----本文基于rt-thread-3.1.3版本编写 首先,使用RTthread OS时,要配置(或者明白)它的系统节拍 ...

  4. 正点原子delay函数移植到rt thread操作系统(HAL库)

    正点原子教程中涉及到的操作系统只涉及了UCOS的教程,其中例程的system文件夹中的delay.c函数只是适配了UCOS. 下面将delay.c函数移植到rt thread中,使用的bsp是rt t ...

  5. linux 自定义shell命令,如何在Linux中自定义bash命令提示符

    前言 众所周知, bash (the B ourne- A gain Sh ell)是目前绝大多数 Linux 发行版使用的默认 shell.本文将会介绍如何通过添加颜色和样式来自定义 bash 命令 ...

  6. Jupyter notebook中自定义支持天软TSl语言的魔术命令

    自定义支持TSL的魔术命令 前言 功能 使用范例 核心代码 相关链接 前言 越来越习惯在jupyter notebook中进行数据分析,但是平时也离不开天软TSL,频繁在两者之间切换了切换去也麻烦,在 ...

  7. Laravel自定义artisan命令在Sell中运行

    Laravel自定义artisan命令在Sell中运行 Artisan 是 Laravel 自带的命令行接口,它为我们在开发过程中提供了很多有用的命令. Console目录 app/Console 目 ...

  8. 在EmberZNet中创建自定义CLI命令

    在Zigbee项目中,您可以找到许多可用于调试的预构建CLI命令.对于每个工程师来说,开发产品都很方便.如果在控制台上键入" help",则可以找到以下CLI命令,包括但不限于: ...

  9. RT Thread之 Uart2 操作

    官网连接:https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/uar ...

最新文章

  1. 问题1-2:能否说:“电路交换和面向连接是等同的,而分组交换和无连接是等同的”? 答:不行。这在概念上是很不一样的。这点可举例说明如下。...
  2. 分布式系统 缓存穿透与失效时的雪崩效应
  3. mysql安装到最后报错_mysql 安装到最后一步时,start service 为失败状态
  4. python爬虫框架排行榜-哪种Python框架适合你?简单介绍几种主流Python框架
  5. Athentech Perfectly Clear中文版
  6. 处理大并发之四 libevent demo详细分析(对比epoll)
  7. python axis 0_axis=0在sum()和dropna()中的行为似乎不同
  8. 将Java 8日期时间API与JSF和Java EE 7结合使用
  9. android aop 权限检查,AOP简单拦截实现验证权限功能
  10. 最有效的七大性能测试技术
  11. 如何快速入行云计算?云计算的学习要点有哪些?
  12. 编译GDAL支持MySQL
  13. c++ 三角函数_精准备考 | 初中数学三角函数知识点全归纳
  14. 微信打开网页:如需浏览,请长按网址复制后使用浏览器访问怎么解决
  15. 信用评分模型详解(上)之 评分卡模型
  16. 改进YOLOv5系列:首发结合 RepLKNet 构建 最新 RepLKDeXt 结构|CVPR2022 超大卷积核, 越大越暴力,大到31x31, 涨点高效
  17. 180127 逆向-JarvisOJ(BrokenDriver)(静态分析解法)
  18. Delphi7 将Excel导入数据库
  19. 波特率dlm_ARM学习随笔(13)UART的理解
  20. html贝塞尔曲线在线,【HTML+js+纯前端】三次方贝塞尔曲线手工拟合小工具

热门文章

  1. Java 并发:第三部分 - 同步锁
  2. 为GridView-Delete列添加确认对话框(2种方法)
  3. rabbitMQ:知识点
  4. Scrapy学习篇(三)之创建项目
  5. 红皮书:变量、作用域和内存问题(四)
  6. MySQL Spatial Extensions 地理信息
  7. Android模拟器PANIC: Could not open:问题解决方法
  8. 搜索引擎广告计费系统如何防恶意点击
  9. oracle中的合并查询
  10. 【Java】MapReduce 程序五步走的思想详细描述