相信很多大佬习惯了linux下shell交互,也非常喜欢敲命令的感觉,那么在单片机这种资源紧张的环境下,是否可以达到这种效果呢,答案是肯定的。下面我移植网络上大神写的nr_micro_shell开源框架来实现shell的效果。
一、nr_micro_shell的核心优势
1、资源占用极低
ROM/RAM消耗显著低于FINSH:在相同配置下(3条历史命令、100字符命令行长度),nr_micro_shell的ROM增量仅3.8KB,RAM增量约1.1KB,而FINSH的ROM增量高达26.9KB,RAM增量1.3KB
适用场景:适合ROM <64KB、RAM <8KB的低端MCU(如STM32F0/F1系列)。
2、交互体验接近Linux Shell
功能丰富:支持Tab补全、方向键移动光标、历史命令查询(最多3条)。
兼容性:适配支持ANSI转义的终端(如PuTTY、SecureCRT),命令行交互流畅。
3、移植便捷性
代码依赖少:仅需实现shell_init()和shell()两个核心函数,支持裸机和RTOS
硬件适配简单:通过宏定义绑定串口收发函数即可完成移植
4、扩展性强
自定义命令灵活:通过结构体或宏定义注册命令函数,支持参数解析(如argc和argv)。
二、与FINSH的对比分析
| 对比维度 | nr_micro_shell | FINSH | 
| 资源占用 | ROM+3.8KB, RAM+1.1KB | ROM+26.9KB, RAM+1.3KB | 
| 交互功能 | 基础命令补全、历史命令 | 支持复杂命令(如free、ps)、脚本执行 | 
| 依赖环境 | 无依赖,裸机友好 | 依赖RT-Thread操作系统 | 
| 开发复杂度 | 代码量小(核心代码约3KB),适合快速集成 | 需理解RT-Thread组件架构,集成成本较高 | 
| 适用场景 | 资源受限的单片机调试、参数配置 | 复杂嵌入式系统(需多任务管理、动态模块加载) | 
三、移植流程
1、下载源码
在如下网址压缩下载解压备用
nr_micro_shell: shell for MCU. 单片机命令行交互。
2、创建串口工程
3、在工程目录下创建nr_micro_shell文件夹
4、复制shell源码文件到刚创立的文件夹中
源码的文件夹,要复制的文件


复制好的文件

5、修改代码
1)增加宏定义
注释宏定义,表示不使用rt-threadOS

2)在主函数添加初始化代码
int main(void)
{
  /* USER CODE BEGIN 1 */
    char c;
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  shell_init();
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
      shell(c);
  }
  /* USER CODE END 3 */
}
3)将shell函数在串口回调函数里调用
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart == &huart1) {
        shell(g_usart1Rxdata);
        //UsartSendData(g_usart1Rxdata);
        HAL_UART_Receive_IT(&huart1, (uint8_t*)&g_usart1Rxdata, 1);
    }
}
4)自定义指令
/**
 * @brief mcu_type command
 */
void shell_hardinfo_cmd(char argc, char *argv)
{
    unsigned int i;
    if (argc > 1)
    {
        if (!strcmp("-name", &argv[argv[1]]))
        {
            shell_printf("NUCLEO-U385RG\r\n");
        }
        else if (!strcmp("-pcb", &argv[argv[1]]))
        {
            shell_printf("MB1841E\r\n");
        }
        else if (!strcmp("-ram", &argv[argv[1]]))
        {
            shell_printf("256KB\r\n");
        }
        else if (!strcmp("-rom", &argv[argv[1]]))
        {
            shell_printf("up to 1MB\r\n");
        }
        else if (!strcmp("-h", &argv[argv[1]]))
        {
            shell_printf("useage: hardinfo [options]\r\n");
            shell_printf("options: \r\n");
            shell_printf("\t -name \t: show board name\r\n");
            shell_printf("\t -pcb \t: show pcb name\r\n");
            shell_printf("\t -rom \t: show mcu rom \r\n");
            shell_printf("\t -ram \t: show mcu ram\r\n");
        }
    }
    else
    {
        shell_printf("ls need more arguments!\r\n");
    }
}
6、下载验证,实测效果
