letter-shell介绍
letter-shell是一个体积小巧,功能完善的嵌入式shell。
创建项目
先使用STM32CubeMX创建一个CMake项目,由于我们需要使用串口收发数据,所以把串口1打开。
安装letter-shell
到letter-shell Github仓库下载letter-shell。把下载好的文件解压,存放至项目目录下的letter-shell文件夹中。
在letter-shell文件夹中,创建CMakeLists.txt文件,写入如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cmake_minimum_required(VERSION 3.22)
add_library(letter-shell STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/shell.c ${CMAKE_CURRENT_SOURCE_DIR}/src/shell_cmd_list.c ${CMAKE_CURRENT_SOURCE_DIR}/src/shell_companion.c ${CMAKE_CURRENT_SOURCE_DIR}/src/shell_ext.c )
target_include_directories(letter-shell PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src )
target_link_libraries(letter-shell PUBLIC stm32cubemx)
|
之后在项目的CMakeLists.txt中,导入此库。
1 2 3 4 5 6 7 8 9 10 11 12
| add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/letter-shell ${CMAKE_CURRENT_BINARY_DIR}/letter-shell)
target_link_libraries(${CMAKE_PROJECT_NAME} stm32cubemx ... letter-shell ... )
|
配置letter-shell
在letter-shell/src目录下的shell.cfg文件中,修改
1 2 3
| #define SHELL_USING_CMD_EXPORT 1
#define SHELL_GET_TICK() HAL_GetTick()
|
配置链接文件
由于我们在配置中使用了命令导出方式,故需要修改链接文件。
在STM32F103xx_FLASH.ld文件中,
添加下述内容:
1 2 3 4 5 6 7 8 9
| .shell_command : { . = ALIGN(4) _shell_command_start = . KEEP(*(shellCommand)) . = ALIGN(4) _shell_command_end = . } >FLASH
|
创建接口
此处我们使用中断方式,因此只需要初始化shellWrite,以及在合适时机调用shellHandler即可。
在项目创建serial_shell.h/c文件,并加入到CMakeLists.txt中。
1 2 3 4
| add_executable(${CMAKE_PROJECT_NAME} Core/Inc/serial_shell.h Core/Src/serial_shell.c)
|
我们一共需要准备shell初始化,串口写入和解析串口读取三个接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
#pragma once
#include <shell.h> #include <stdint.h>
extern Shell shell;
signed short shell_write(char* bytes, unsigned short len);
void shell_init();
void shell_parse_input(uint16_t size);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
#include "serial_shell.h"
#include <usart.h>
Shell shell; char shellBuffer[512]; uint8_t buffer[32];
signed short shell_write(char* bytes, unsigned short len) { HAL_UART_Transmit(&huart1, (uint8_t*)bytes, len, 50); return len; }
void shell_init() { shell.write = shell_write; shellInit(&shell, shellBuffer, sizeof(shellBuffer)); HAL_UARTEx_ReceiveToIdle_IT(&huart1, buffer, sizeof(buffer)); }
void shell_parse_input(uint16_t size) { for (size_t i = 0; i < size; i++) { shellHandler(&shell, buffer[i]); } HAL_UARTEx_ReceiveToIdle_IT(&huart1, buffer, sizeof(buffer)); }
|
之后在main.c中,调用初始化函数与串口解析函数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); MX_USART1_UART_Init(); shell_init();
while (1) { } }
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart == &huart1) { shell_parse_input(Size); } }
|
效果呈现
编译并烧录程序后,打开串口调试工具,推荐SecureCRT,即可看到启动后的效果。
1 2 3 4 5 6 7 8 9 10 11
| _ _ _ _ _ _ | | ___| |_| |_ ___ _ __ ___| |__ ___| | | | | / _ \ __| __/ _ \ '__| / __| '_ \ / _ \ | | | |__| __/ |_| || __/ | \__ \ | | | __/ | | |_____\___|\__|\__\___|_| |___/_| |_|\___|_|_|
Build: Jul 30 2026 17:52:22 Version: 3.1.2 Copyright: (c) 2020 Letter
letter:/$
|
自定义使用
函数定义
详见官方Github链接
变量调用
详见官方Github链接