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

DMA USART传输,上下左右按键的问题 #157

Open
jasheri opened this issue May 18, 2023 · 3 comments
Open

DMA USART传输,上下左右按键的问题 #157

jasheri opened this issue May 18, 2023 · 3 comments

Comments

@jasheri
Copy link

jasheri commented May 18, 2023

由于DMA 串口一次传输进来的上下左右按键是3字节的数据,void shellTask(void *param)只读取了一个字符,所以无法判断出上下左右按键。
修改如下:

void shellTask(void *param)
{
Shell *shell = (Shell *)param;
char data;
#if SHELL_TASK_WHILE == 1
while(1)
{
#endif
if (shell->read && shell->read(&data, 1) != 0)
{
shellHandler(shell, data);
}
#if SHELL_TASK_WHILE == 1
}
#endif
}

我这里修改如下:
首先要修改:读取函数,要给shell.parser.keyValue赋值。

short userShellRead(char *data, unsigned short len)
{
u8 dlen = 0;
u8 dat[8]; //长度为8是为了避免溢出

if(UART_GetRxData((u8*)dat, &dlen) != 0)
{
	if(dlen > 4) return 0; //不接收超过4字符的按键
	
	short i, shft = 0;
	shell.parser.keyValue = 0;
	//把接收数据赋值给shell.parser.keyValue
	for(i = 0; i < dlen; i++)
	{
		//根据接收到的长度位移 最大不能位移超过24bit
		shft = (3-i) << 3;
		shft = shft > 24 ? 24 : shft;
		shell.parser.keyValue |= ((int)dat[i] << shft);
	}
	*data = dat[0];
	return dlen;
}
return 0;

}

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

/* 遍历ShellCommand列表,尝试进行按键键值匹配 */
ShellCommand *base = (ShellCommand *)shell->commandList.base;
for (short i = 0; i < shell->commandList.count; i++)
{
    /* 判断是否是按键定义并验证权限 */
    if (base[i].attr.attrs.type == SHELL_TYPE_KEY
        && shellCheckPermission(shell, &(base[i])) == 0)
    {
        /* 对输入的字节同按键键值进行匹配 */
        if ((base[i].data.key.value ) == shell->parser.keyValue )
        {
                            data = 0x00;
			if (base[i].data.key.function)
			{
				base[i].data.key.function(shell);
			}
			shell->parser.keyValue = 0x00000000;
			break;
        }
    }
}

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

if (SHELL_GET_TICK())
{
    shell->info.activeTime = SHELL_GET_TICK();
}
SHELL_UNLOCK(shell);

}

经过修改,可以正常实现上下左右按键识别。

@NevermindZZT
Copy link
Owner

这个还是要从串口驱动上去解决,方向按键是包含三个字节数据的,按照目前 shell 的设计,应该是一个字节一个字节传入,使用 DMA 出现问题,应该是接收到的数据没有做缓冲,导致在数据处理的时候,串口的数据被丢掉

@jasheri
Copy link
Author

jasheri commented May 19, 2023

嗯,我这个是1ms调用一次shellHandler, 所以一次接收到了3个字符,如果用一个FIFO作为DMA串口驱动的缓冲应该可以解决这个问题。明白了。

@jasheri
Copy link
Author

jasheri commented May 31, 2023

长按左右按键快速滑动光标时会出现光标越界的问题,这里提供一种解决办法:
if (data != 0x00 && ((shell->parser.keyValue & 0xFFFFFF00) == 0)) //判断真实的按键值
{
shell->parser.keyValue = 0x00000000;
shellNormalInput(shell, data);
}
如上修改之后,测试不会再出现光标越界的问题。
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants