Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

按键拦截操作优化,并添加 STM32 HAL 库移植参考 #191

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions demo/stm32-hal/shell_port.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @file shell_port.c
* @author Shellever ([email protected])
* @brief
* @version 0.1
* @date 2024-06-20
*
* @copyright (c) 2019 Letter
*
*/

#include "main.h"
#include "usart.h"

#include "shell.h"
#include "shell_port.h"


Shell shell;
char shellBuffer[512];


/**
* @brief 用户shell写
*
* @param data 数据
* @param len 数据长度
*
* @return short 实际写入的数据长度
*/
short userShellWrite(char *data, unsigned short len)
{
HAL_UART_Transmit(&huart1, (uint8_t *)data, len, 200); // 太小的话会导致超时,只有前面部分显示,显示不全

return len;
}


/**
* @brief 用户shell读
*
* @param data 数据
* @param len 数据长度
*
* @return short 实际读取到
*/
short userShellRead(char *data, unsigned short len)
{
if (HAL_UART_Receive(&huart1, (uint8_t *)data, len, 200) == HAL_OK) {
return len;
}

return 0;
}


/**
* @brief 用户shell初始化
*
*/
void userShellInit(void)
{
shell.write = userShellWrite;
shell.read = userShellRead;

shellInit(&shell, shellBuffer, sizeof(shellBuffer));
}


21 changes: 21 additions & 0 deletions demo/stm32-hal/shell_port.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @file shell_port.h
* @author Shellever ([email protected])
* @brief
* @version 0.1
* @date 2024-06-20
*
* @copyright (c) 2019 Letter
*
*/

#ifndef __SHELL_PORT_H__
#define __SHELL_PORT_H__


#include "shell.h"

extern Shell shell;

void userShellInit(void);
#endif
114 changes: 70 additions & 44 deletions src/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ ShellCommand* shellSeekCommand(Shell *shell,
ShellCommand *base,
unsigned short compareLength);
static void shellWriteCommandHelp(Shell *shell, char *cmd);
static char shellInterceptKey(Shell *shell, char data);

/**
* @brief shell 初始化
Expand Down Expand Up @@ -1759,48 +1760,40 @@ SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RE
help, shellHelp, show command info\r\nhelp [cmd]);

/**
* @brief shell 输入处理
*
* @param shell shell对象
* @param data 输入数据
* @brief shell 按键拦截
* parser.keyValue 保存上一次已经匹配的数值位
* keyFilter 保存之前匹配过的掩码值
* keyByteOffset 当前需要匹配的字节偏移位置
* keyName keyValue parser.keyValue keyByteOffset keyFilter
* backspace 0x08000000 0x00000000 24 0x00000000
* CRLF 0x0D0A0000 0x0D000000 16 0xFF000000
* up 0x1B5B4100 0x1B5B0000 8 0xFFFF0000
* delete 0x1B5B337E 0x1B5B3300 0 0xFFFFFF00
*
* @param shell shell 对象
* @param data 输入字符
*/
void shellHandler(Shell *shell, char data)
static char shellInterceptKey(Shell *shell, char data)
{
SHELL_ASSERT(data, return);
SHELL_LOCK(shell);
char keyByteOffset;
int keyFilter;
char keyHit = 0; // 按键匹配标志

#if SHELL_LOCK_TIMEOUT > 0
if (shell->info.user->data.user.password
&& strlen(shell->info.user->data.user.password) != 0
&& SHELL_GET_TICK())
{
if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT)
{
shell->status.isChecked = 0;
}
}
#endif

/* 根据记录的按键键值计算当前字节在按键键值中的偏移 */
char keyByteOffset = 24;
int keyFilter = 0x00000000;
if ((shell->parser.keyValue & 0x0000FF00) != 0x00000000)
{
keyByteOffset = 0;
keyFilter = 0xFFFFFF00;
}
else if ((shell->parser.keyValue & 0x00FF0000) != 0x00000000)
{
keyByteOffset = 8;
keyFilter = 0xFFFF0000;
}
else if ((shell->parser.keyValue & 0xFF000000) != 0x00000000)
char *pkey = (char *)&shell->parser.keyValue;
char i = sizeof(shell->parser.keyValue);

while(pkey[--i] != 0)
{
keyByteOffset = 16;
keyFilter = 0xFF000000;
;
}

/* 遍历ShellCommand列表,尝试进行按键键值匹配 */
keyFilter = 0xFFFFFFFF << ((i + 1) * 8);
keyByteOffset = i * 8;


/* 遍历 ShellCommand 列表,尝试进行按键键值匹配 */
ShellCommand *base = (ShellCommand *)shell->commandList.base;
for (short i = 0; i < shell->commandList.count; i++)
{
Expand All @@ -1810,29 +1803,62 @@ void shellHandler(Shell *shell, char data)
{
/* 对输入的字节同按键键值进行匹配 */
if ((base[i].data.key.value & keyFilter) == shell->parser.keyValue
&& (base[i].data.key.value & (0xFF << keyByteOffset))
== (data << keyByteOffset))
&& ((base[i].data.key.value >> keyByteOffset) & 0xFF) == data)
{
shell->parser.keyValue |= data << keyByteOffset;
data = 0x00;
if (keyByteOffset == 0
|| (base[i].data.key.value & (0xFF << (keyByteOffset - 8)))
== 0x00000000)
keyHit = 1;

/* 测试按键键值匹配位置的后一个字节是否为 0x00,用于表示匹配是否完成 */
if (keyByteOffset == 0
|| ((base[i].data.key.value >> (keyByteOffset - 8)) & 0xFF) == 0x00)
{
if (base[i].data.key.function)
{
base[i].data.key.function(shell);
}
shell->parser.keyValue = 0x00000000;
shell->parser.keyValue = 0;
break;
}
else
{
shell->parser.keyValue |= data << keyByteOffset;
}
}
}
}

if (data != 0x00)
if (!keyHit)
{
shell->parser.keyValue = 0;
}

return keyHit;
}

/**
* @brief shell 输入处理
*
* @param shell shell对象
* @param data 输入数据
*/
void shellHandler(Shell *shell, char data)
{
SHELL_ASSERT(data, return);
SHELL_LOCK(shell);

#if SHELL_LOCK_TIMEOUT > 0
if (shell->info.user->data.user.password
&& strlen(shell->info.user->data.user.password) != 0
&& SHELL_GET_TICK())
{
if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT)
{
shell->status.isChecked = 0;
}
}
#endif

if (!shellInterceptKey(shell, data))
{
shell->parser.keyValue = 0x00000000;
shellNormalInput(shell, data);
}

Expand Down