[--------------点击下面,进入总目录索引--------------]
STM32系列精品Demo集 - 总目录
图示:Letter Shell效果演示
一、为什么要移植Letter shell
- Linux下强大的命令行工具用起来即为顺手,所以移植一款命令行工具到STM平台非常有意义 。
- 工程中集成一款交互式shell,为项目开发调试提供便捷,开发者自定义测试命令,使得更加灵活。
二、移植步骤
2.1、获取Letter Shell源码
https://github.com/NevermindZZT/letter-shell
图示:Letter Shell源码结构
上述源码结构中,若不想深入了解实现机制,只想简单使用起来,后续移植只需关心上述框出文件即可!
2.2、shell_port.c
数据源移植
shell_port.c
主要用于配置Uart数据通道,说白了就是将shell_port.c中的读写接口移植为STM32平台的Uart发送接收接口。
Shell shell;
char shellBuffer[512];
/**
* @brief 用户shell写
*
* @param data 数据
*/
void userShellWrite(char data)
{
ControlUartSendData(UART0_CHANNEL, data);
}
/**
* @brief 用户shell读
*
* @param data 数据
* @return char 状态
*/
signed char userShellRead(char *data)
{
*data = 0;
while (!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET))
{
}
*data = USART_ReceiveData(USART1);
return 0; //返回0标识数据已经准备OK
}
/**
* @brief 用户shell初始化
*
*/
void userShellInit(void)
{
char data = 0;
shell.write = userShellWrite;
shell.read = userShellRead;
shellInit(&shell, shellBuffer, 512);
}
2.3、shell_cfg.h
平台配置移植
图示:shell_cfg.h配置宏定义
!!!!!对于上述宏开关,小伙伴们可自行尝试,博主在移植过程中仅关注了下述几个宏,其它保持默认即可。!!!!!
/**
* @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
* 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell
* 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
*/
#define SHELL_TASK_WHILE 0 /*裸机操作不执行线程,关闭此宏*/
/**
* @brief 获取系统时间(ms)
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
*/
#define SHELL_GET_TICK() 0 /*裸机操作不实现此接口,关闭此宏*/
/**
* @brief shell默认用户
*/
#define SHELL_DEFAULT_USER "MicroShell" /*修改默认用户名*/
2.4、启动Letter Shell任务
2.4.1、启动方式一
/**
* @brief shell 任务
*
* @param param 参数(shell对象)
*
*/
void shellTask(void *param)
{
Shell *shell = (Shell *)param;
char data;
/* 可以看到shell->read如果返回0,则认为串口有数据,调用shellHandler去处理,所以也就衍生了启动方式二*/
if (shell->read && shell->read(&data) == 0)
{
shellHandler(shell, data);
}
}
#include "stm32f4xx.h"
#include "Delay.h"
#include "ControlUart.h"
#include "ModuleConfig.h"
#include "shell_port.h"
#include "shell.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
ControlUartInit(UART0_CHANNEL,115200);
userShellInit();
while(1)
{
shellTask(&shell);
}
}
2.4.2、启动方式二
/* 自定义接口函数 */
void userShellRun(void)
{
char data = 0;
data = 0;
while (!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET))
{
}
data = USART_ReceiveData(USART1);
shellHandler(&shell,data);
//delay_ms(10);
}
#include "stm32f4xx.h"
#include "Delay.h"
#include "ControlUart.h"
#include "ModuleConfig.h"
#include "shell_port.h"
#include "shell.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
ControlUartInit(UART0_CHANNEL,115200);
userShellInit();
while(1)
{
userShellRun();
}
}
三、Letter Shell简单使用
3.1、编写自定义命令对应的执行接口
- letter shell 3.x同时支持两种形式的函数定义方式:
- Main函数形式:
func(int argc, char *agrv[])
- 普通C函数形式:
func(int i, char *str, ...)
- main函数形式
/***********************************************************************
* 函数名称: ShellTestFun0
* 功能描述: letter:/$ shelltest0 123 'a' "1234"
* 输入参数:
* 输出参数:
* 返 回 值:
* 其 它:
***********************************************************************/
int ShellTestFun0(int i, char ch, char *str)
{
printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
//最后必须要加上换行,以避免与shell内置返回打印重叠
printf("\r\n");
return 0;
}
-
普通C函数形式
普通C函数形式,shell会自动对参数进行转化处理,目前支持二进制,八进制,十进制,十六进制整形,字符,字符串/*********************************************************************** * 函数名称: ShellTestFun1 * 功能描述: letter:/$ shellest1 "hello world" * 输入参数: * 输出参数: * 返 回 值: * 其 它: ***********************************************************************/ int ShellTestFun1(int argc, char *agrv[]) { printf("%dparameter(s)\r\n", argc); for (char i = 0; i <= argc; i++) { printf("%s\r\n", agrv[i]); } //最后必须要加上换行,以避免与shell内置返回打印重叠 printf("\r\n"); return 0; }
3.2、注册命令
/***********************************************************************
* 函数名称: #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc)
* 输入参数:
_attr :命令属性
_name :命令名
_func :命令函数
_desc :命令描述
* 输出参数:
* 返 回 值:
* 其 它:
***********************************************************************/
/******************************************************************************
* 注册自定义不同形参的测试指令
******************************************************************************/
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), shelltest0, ShellTestFun0, test mode0 parameter);
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), shelltest1, ShellTestFun1, test mode1 parameter);
3.3、命令测试
#终端调用
MicroShell:/$ shelltest0 12 'a' "hello"
input int: 12, char: a, string: hello
Return: 0, 0x00000000
#终端调用
MicroShell:/$ shelltest1 "hello"
2parameter(s)
shelltest1
hello
Return: 0, 0x00000000
附录:Demo源码
https://gitee.com/jiangfengzhang/stm32-f4-letter-shell
图示:工程源码结构
shell_customd_cmd.c(自定义命令源文件)