相信很多大佬习惯了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、下载验证,实测效果
