开发环境:Window 10 64bit
开发工具:IAR Embedded Workbench
硬件:stm32f103c8t6
RT-Thread Nano 版本包含了 FinSH 组件,我们可以在reconfig.h配置使用它,使用之后我们可以在电脑上通过串口终端输入命令调试系统。这功能用于调试或查看系统信息,在实际开发中可以带来很多的方便,。效果如下图:
1.我使用的芯片是stm32f103c8t6,基于IAR移植RT-Thread Nano,点击下载RT-Thread Nano源码 。如果你没有IAR,而是使用KEIL,点击查看参考链接。
2.下载源码后,在rt-thread-3.1.3\bsp\stm32f103-msh路径下,打开iar工作空间文件Project.eww,打开后是这样子的:
Project->Options,General Optons->配置成自己使用的芯片、Debugger->配置调试工具:
3.配置rtconfig.h文件,在该文件里加入一下宏:
#define RT_USING_FINSH
#define FINSH_USING_HISTORY
开启后可对 FinSH 组件相关的参数进行配置修改(在rtconfig.h文件结尾的地方):
#if defined (RT_USING_FINSH) // 开关 FinSH 组件
#define FINSH_USING_MSH // 使用 FinSH 组件 MSH 模式
#define FINSH_USING_MSH_ONLY // 仅使用 MSH 模式
#define __FINSH_THREAD_PRIORITY 5 // 设置 FinSH 组件优先级,配置该值后通过下面的公式进行计算
#define FINSH_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 8 * __FINSH_THREAD_PRIORITY + 1)
#define FINSH_THREAD_STACK_SIZE 1024 // 设置 FinSH 线程栈大小,范围 1-4096
#define FINSH_HISTORY_LINES 5 // 设置 FinSH 组件记录历史命令个数,值范围 1-32
#define FINSH_USING_SYMTAB // 使用符号表,需要打开,默认打开
#endif
4.在shell.c文件里面找到rt_hw_console_getchar函数:
//修改点:函数返回值,增加清除RXNE标志,去掉delay
int rt_hw_console_getchar(void)
{
int ch = -1;
if (__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_RXNE) != RESET)
{
ch = UartHandle.Instance->DR & 0xff;
__HAL_UART_CLEAR_FLAG(&UartHandle, UART_FLAG_RXNE);
}
else
{
//rt_thread_mdelay(10);
}
return ch;
}
5.在shell.c文件里面找到finsh_thread_entry 函数,注释掉两个回显:
/*.........*/
else if (ch == 0x44) /* left key */
{
if (shell->line_curpos)
{
//rt_kprintf("\b");
shell->line_curpos --;
}
continue;
}
else if (ch == 0x43) /* right key */
{
if (shell->line_curpos < shell->line_position)
{
//rt_kprintf("%c", shell->line[shell->line_curpos]);
shell->line_curpos ++;
}
continue;
}
/*.........*/
1.点击下载源码
2.我使用的qt版本是Qt Creator 5.14,如果下载我的源码由于版本冲突,不能使用的话可以自己新建一个工程,把代码复制过去;或者去qt官网下载该版本。
3.效果图:
4.关键代码:
重写键盘释放事件函数,通过ev->text()可以获取键盘输入的字符(包括回退键,确认键),此外我们还需要获取方向键,方向键的使用类似Linux终端,可通过按上键来翻阅之前的命令记录,命令是在MCU里记录,当按了上键时,MCU就会返回上一次输入的命令,命令记录的条数最大值设置是在在rtconfig.h文件中的宏FINSH_HISTORY_LINES。
方向键需要发送的键值是不能直接通过ev->text()获取到的,所以先通过ev->key(),不同的按键发送对应的控制码,比如“上”键,发送的是:0x1b 0x5b 0x41即可。
void MainWindow::keyReleaseEvent(QKeyEvent *ev)
{
int code = 0xFF;
unsigned char controlkey[5]={0x1b,0x5b,0x00};
//unsigned int key = ev->key();
//qDebug("键值:0x%x",ev->key());
if(!ui->textEdit->hasFocus()){//判断光标是否在textEdit控件上
return;
}
/*
* handle control key
* up key : 0x1b 0x5b 0x41
* down key: 0x1b 0x5b 0x42
* right key:0x1b 0x5b 0x43
* left key: 0x1b 0x5b 0x44
*/
controlkey[2] = 0x00;
switch (ev->key()) {
case Qt::Key_Left:
controlkey[2] = 0x44;
ui->textEdit->moveCursor(QTextCursor::Left);
break;
case Qt::Key_Right:
controlkey[2] = 0x43;
ui->textEdit->moveCursor(QTextCursor::Right);
break;
case Qt::Key_Up:
controlkey[2] = 0x41;
break;
case Qt::Key_Down:
controlkey[2] = 0x42;
break;
default:
QString text = ev->text();
if(text.size() > 0){
code = text.at(0).toLatin1();
if((code >= 0) && (code <= 0x7e)){//ASCII
if(code == '\n'||code == '\r'){//回车按键按下时,将光标移动到末尾
ui->textEdit->moveCursor(QTextCursor::End);
}
if(port != NULL && port->isOpen()){//发送字符到串口
port->write((const char*)&code,1);
}
}
}
break;
}
if(controlkey[2] != 0x00){
port->write((const char*)&controlkey[0],3);
}
//qDebug("0x%x %c",(char)code,(char)code);
//QWidget::keyPressEvent(ev);
}
窗口接收函数,当PC端串口接收到数据就会进入下面的函数,接受到的数据会先保存到MainSerialRecvData数组里,然后再一个一个的追加到显示输入控件textEdit上,这里我同了temp数组来过度,如果有更好的办法可以优化一下;当CP端按下了“backspace”键时,MCU会往PC回发‘/b’,那么当PC端接收到‘/b’就要删除关标后一个字符。
void MainWindow::SerialRecvMsgEvent()
{
QByteArray MainSerialRecvData;
char temp[10]={0};
if(port->bytesAvailable()>0)
{
MainSerialRecvData = port->readAll();
//qDebug("rec data");
int count = MainSerialRecvData.count();
for(int i = 0;i= 0) && (temp[0] <= 0x7e)){//ASCII
if(temp[0] == 0x08){// '/b':backspace键
ui->textEdit->textCursor().deletePreviousChar();//删除光标后面一个字符
}else{
ui->textEdit->textCursor().insertText(temp);//把字符显示到textedit里
}
//移动滚动条到底部
QScrollBar *scrollbar = ui->textEdit->verticalScrollBar();
if (scrollbar)
{
scrollbar->setSliderPosition(scrollbar->maximum());
}
}
}
}
}
把qt的源码下载解压,就可以直接编译运行,选择串口,设置波特率,输入命令是记得把输入法切换到英文,否则输入无效的。
《路漫漫其修远兮,吾将上下而求索。———屈原》