本着“停課不停學”的原則,在家也不能閒着,最近在進一步探索μC/OS時發現了μC/Shell,果斷決定嘗試一下。
Silicon Labs收購Micrium後,將其產品開源了,GitHub上可以下載代碼。https://github.com/SiliconLabs
下面先介紹μC/Shell的文件結構,再介紹移植方法和實際應用。
μC/Shell文件結構
\Cfg\Template\shell_cfg.h
μC/Shell的配置文件,設置指令表大小、指令參數格式、最大指令長度等參數。
\Cmd\General\sh_shell.c, sh_shell.h
我沒看明白這兩個文件是幹什麼的,移植時也沒用上。
\Source\shell.c
μC/Shell的所有函數接口都在這個文件裏,包括Shell初始化、添加指令、刪除指令、執行指令等函數接口。
\Source\shell.h
μC/Shell的頭文件,包括一些函數、函數指針、結構體、變量的聲明和宏定義。
\Terminal\ 終端文件夾,提供的接口方便單片機與PC終端交互。
\Terminal\Cfg\Template\terminal_cfg.h
終端的配置文件。
\Terminal\Mode\VT100\terminal_mode.c
包括讀寫終端指令的函數。
\Terminal\OS\uCOS-III\terminal_os.c
配合uCOS-III使用的文件,創建終端任務。還有一個可以用於uCOS-II的文件。
\Terminal\Serial\Template\terminal_serial.c
輸入輸出接口文件,移植時需要修改文件裏的函數以配合單片機硬件接口。
\Terminal\Source\terminal.c, terminal.h
包括終端初始化、終端任務函數等。
μC/Shell移植
集成開發環境:keil5。單片機:STM32F405,事先已移植好μC/OS-III操作系統。
1、在工程目錄下創建UCShell文件夾,將μC/Shell的文件複製到UCShell文件夾內,文件結構可以自己調整一下。
2、在Keil中建立UCShell和UCShell_terminal分組,將相應文件添加入工程,我用的uCOS-III的terminal_os.c文件,沒有添加\Cmd\General\下的文件。配置頭文件路徑。
3、修改terminal_serial.c文件。因爲我自己寫的外設配置文件是用C++寫的,爲了方便調用C++函數接口,我將terminal_serial.c改爲了terminal_serial.cpp,在terminal.h文件里加extern "C"。
/*
TerminalSerial_Init 函數用於配置單片機串口,我在其他文件裏配置了串口。
*/
CPU_BOOLEAN TerminalSerial_Init (void)
{
return (DEF_OK);//原版文件裏是DEF_FAIL,一定要改成DEF_OK。
}
/*
TerminalSerial_Exit 關閉串口函數,沒必要改。
*/
void TerminalSerial_Exit (void)
{
}
/*
TerminalSerial_Wr 串口發送字符串,添加串口發送函數。
*/
CPU_INT16S TerminalSerial_Wr (void *pbuf,
CPU_SIZE_T buf_len)
{
board.USART6Send((unsigned char*)pbuf,buf_len);//USART6發送字符串。
return (-1);
}
/*
TerminalSerial_RdByte 從串口讀取一字節。
我是從緩衝隊列中取字節,緩衝隊列中的字節是在串口中斷時送入。
當緩衝隊列空時,返回值一要是0x00。
*/
CPU_INT08U TerminalSerial_RdByte (void)
{
unsigned char byte = 0x00;
if(!shell_rx_queue.EmptyCheck())
{
byte = shell_rx_queue.GetData();
}
return byte;
}
/*
TerminalSerial_WrByte 串口發送一字節,添加串口發送函數。
*/
void TerminalSerial_WrByte (CPU_INT08U c)
{
board.USART6Send((unsigned char*)&c,1);
}
至此,μC/Shell移植完成,接下來需要用實踐檢驗移植是否成功。
μC/Shell應用
新建myshell.cpp和myshell.h文件,寫一個命令行控制LED亮滅的代碼驗證移植是否成功。
//myshell.c
#include "myshell.h"
#include "shell.h"
#include "terminal.h"
#include "stm32f4xx.h"
//函數原型,函數的參數必須是這種形式,否則不能正常使用。
CPU_INT16S LedCmd(CPU_INT16U argc,
CPU_CHAR *argv[],
SHELL_OUT_FNCT out_fnct,
SHELL_CMD_PARAM *pcmd_param);
//指令表,"LED"是指令,LedCmd是指令回調函數。
static SHELL_CMD ShellCmdTbl[] =
{
{"LED", LedCmd},
{0, 0}
};
//Shell初始化,在μC/OS系統啓動任務中調用。
void ShellInit(void)
{
SHELL_ERR err;
Shell_Init(); //初始化Shell
Terminal_Init(); //初始化終端
Shell_CmdTblAdd((CPU_CHAR*)"LED",ShellCmdTbl,&err);//添加一項指令
}
/****************************************************
//LED指令回調函數,參數必須是這種形式。
//argc 記錄參數個數,只有指令沒有參數時爲1;
//argv 字符串指針數組,記錄指令及參數,argv[0]是指令LED,argv[1]是參數ON或OFF,如果參數更多,參數會存在argv[2]...
//out_fnct 函數指針,函數響應時指向terminal.c中的Terminal_OutFnct函數;
//pcmd_param 目前還不知道這個參數幹什麼用的。
*****************************************************/
CPU_INT16S LedCmd(CPU_INT16U argc,
CPU_CHAR *argv[],
SHELL_OUT_FNCT out_fnct,
SHELL_CMD_PARAM *pcmd_param)
{
CPU_INT16S output;
CPU_INT16S ret_val;
if(argc == 2)
{
if(!Str_Cmp(argv[1],"ON"))
{
GPIOB->BSRRL = GPIO_Pin_15;//亮燈
}
else if(!Str_Cmp(argv[1],"OFF"))
{
GPIOB->BSRRH = GPIO_Pin_15;//關燈
}
output = out_fnct((CPU_CHAR*)"OK",(CPU_INT16U)Str_Len("OK"),pcmd_param->pout_opt);
}
else if(argc > 2)
{
output = out_fnct((CPU_CHAR*)"error: too many arguments",(CPU_INT16U)Str_Len("error: too many arguments"),pcmd_param->pout_opt);
}
else
{
output = out_fnct((CPU_CHAR*)"error: missing argument",(CPU_INT16U)Str_Len("error: missing argument"),pcmd_param->pout_opt);
}
ret_val = output;
return ret_val;
}
代碼寫好後可以試一下,在SecureCRT上輸入幾條指令看一下現象。(LED亮滅我就不拍照了)
實踐證明,移植成功,μC/Shell可以正常使用。
μC/Shell的詳細說明請看μC/Shell官方文檔 。
μC/Shell模板下載:https://download.csdn.net/download/QDchenxr/12262695