这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【STM32F769】移植开源nrmicroshell

共2条 1/1 1 跳转至

【STM32F769】移植开源nrmicroshell

助工
2025-02-23 17:49:09     打赏


在进行调试和维护时,常常需要与单片机进行交互,获取、设置某些参数或执行某些操作,nr_micro_shell正是为满足这一需求,针对资源较少的MCU编写的基本命令行工具。虽然RT_Thread组件中已经提供了强大的finsh命令行交互工具,但对于ROM、RAM资源较少的单片机,finsh还是略显的庞大,在这些平台上,若仍想保留基本的命令行交互功能,nr_micro_shell是一个不错的选择。

nr_micro_shell具有以下优点

1.占用资源少,使用简单,灵活方便。使用过程只涉及两个shell_init()和shell()两个函数,无论是使用RTOS还是裸机都可以方便的应用该工具,不需要额外的编码工作。

2.交互体验好。完全类似于linux shell命令行,当串口终端支持ANSI(如Hypertrm终端)时,其不仅支持基本的命令行交互,还提供Tab键命令补全,查询历史命令,方向键移动光标修改功能。

3.扩展性好。nr_micro_shell为用户提供自定义命令的标准函数原型,只需要按照命令编写命令函数,并注册命令函数,即可使用命令。

nr_micro_shell和相同配置下的finsh (finsh不使用msh)占用资源对比


原始工程

添加nr_micro_shell增加量

添加finsh增加量

ROM

63660

+3832

+26908

RAM

4696

+1104

+1304

两者配置都为

· 最多3条历史命令。

· 支持Tab补全 。

· 命令行最大长度为100。

· 最多10个命令参数。

· 命令行线程堆栈为512字节。

1、下载源码:

https://gitee.com/nrush/nr_micro_shell.git

2、添加到工程,在前面移植基础工程的基础之上添加移植代码。

 image.png

然后添加进编译,将目录添加进CmakeLists

 image.png

3、编写用户代码:

Shell_uart.c/h

Shell_uart.c中首先启动shell_init();   //NR_MICRO_SHELL

然后编写stm32 UART的接收、错误的三个回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)   //shell
    {
        if(((g_shell_uart.rx.write_i+1)&0x1ff) != g_shell_uart.rx.read_i)
        {
            g_shell_uart.rx.buff[g_shell_uart.rx.write_i++] = uart_recv_buff[0] & 0xff;
            g_shell_uart.rx.write_i &= 0x1ff;//256Byte
        }
        HAL_UART_Receive_IT(huart,uart_recv_buff,1);//
    }
}


//
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)   //shell
    {
        HAL_UART_Receive_IT(huart,uart_recv_buff,1);//
    }
}

在接收函数中,我们将接收的字符缓存到缓冲区。

loop函数中,我们判断如果有数据,就通过shell(g_shell_uart.rx.buff[g_shell_uart.rx.read_i++]);将接收到的字符回传给串口。

 

void shell_usart_loop(void)
{
    if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
        shell(g_shell_uart.rx.buff[g_shell_uart.rx.read_i++]);
        g_shell_uart.rx.read_i &= 0x1ff; //256Byte
    }

}


4、增加shell 命令:

#include "string.h"
#include "ctype.h"

static void list_cmd(void)
{
    unsigned int i = 0;
    for (i = 0; nr_shell.static_cmd[i].fp != NULL; i++)
    {
        shell_printf("%s\t\t", nr_shell.static_cmd[i].cmd);
        if (nr_shell.static_cmd[i].description != NULL)
            shell_printf("\"%s\"\t\t", nr_shell.static_cmd[i].description);
        shell_printf("\r\n");
    }
}
/**
 * @brief ls command
 */
void shell_ls_cmd(char argc, char *argv)
{
    if (argc > 1)
    {
        if (!strcmp("cmd", &argv[argv[1]]))
        {
            list_cmd();
        }
        else if (!strcmp("-v", &argv[argv[1]]))
        {
            shell_printf("ls version 1.0.\r\n");
        }
        else // if (!strcmp("-h", &argv[argv[1]]))
        {
            goto exit_lable;
        }
        return;
    }
    shell_printf("ls need more arguments!\r\n\r\n");

exit_lable:
    shell_printf("useage: ls [options]\r\n");
    shell_printf("options: \r\n");
    shell_printf("\t -h \t: show help\r\n");
    shell_printf("\t -v \t: show version\r\n");
    shell_printf("\t cmd \t: show all commands\r\n");
}

void shell_help_cmd(char argc, char *argv)
{
    list_cmd();
}

/**
 * @brief test command
 */
void shell_test_cmd(char argc, char *argv)
{
    unsigned int i;
    shell_printf("test command:\r\n");
    for (i = 0; i < argc; i++)
    {
        shell_printf("paras %d: %s\r\n", i, &(argv[argv[i]]));
    }
}

#ifdef NR_SHELL_USING_EXPORT_CMD
NR_SHELL_CMD_EXPORT(help, shell_help_cmd, "help");
NR_SHELL_CMD_EXPORT(ls, shell_ls_cmd, "list cmd");
NR_SHELL_CMD_EXPORT(test, shell_test_cmd, "test cmd");

#else
const static_cmd_st static_cmd[] =
    {
        {"help", shell_help_cmd, "list cmd"},
        {"ls", shell_ls_cmd, "list cmd"},
        {"test", shell_test_cmd, "test cmd"},

        {"\0", NULL}};

#endif


运行效果:

 image.png

通过shell的移植,就可以很好的跟F769进行交互了。

使用命令控制板载LED的开关

添加命令:

void shell_led_cmd(char argc, char *argv)
{
    if(argc ==  2)
    {
        if(!strcmp("LED", &argv[argv[0]]) )
        {
            if(!strcmp("on", &argv[argv[1]]))
            {
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
                shell_printf("LED on\r\n");
            }
            else if(!strcmp("off", &argv[argv[1]]))
            {
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET);
                shell_printf("LED off\r\n");
            }
            else
            {
                shell_printf("ERRO CMD:led %s\r\n", argv[1]);
            }
        }
        else
        {
            shell_printf("ERRO CMD:led %s\r\n", argv[0]);
        }
    }
}

再把命令添加进cmd组:

const static_cmd_st static_cmd[] =
    {
        {"help", shell_help_cmd, "list cmd"},
        {"ls", shell_ls_cmd, "list cmd"},
        {"test", shell_test_cmd, "test cmd"},
        {"LED", shell_led_cmd, "LED on/off"},
        {"\0", NULL}
    };

在终端中就可以实时控制LED的关与灭了:

| \ | |  _ \  |  \/  (_) ___ _ __ ___   / ___|| |__   ___| | |
|  \| | |_) | | |\/| | |/ __| '__/ _ \  \___ \| '_ \ / _ \ | |
| |\  |  _ <  | |  | | | (__| | | (_) |  ___) | | | |  __/ | |
|_| \_|_| \_\ |_|  |_|_|\___|_|  \___/  |____/|_| |_|\___|_|_|

nr@root:ls cmd
help            "list cmd"
ls              "list cmd"
test            "test cmd"
LED             "LED on/off"
nr@root:LED on
LED on
nr@root:LED off
LED off
nr@root:





关键词: STM32F769     nr_micro_shell    

院士
2025-02-24 23:36:27     打赏
2楼

我倒是挺犹豫要不要在我的项目里面引入第三方shell库的


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]