<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
https://static.assets-stash.eet-china.com/album/old-resources/2010/3/12/179aec15-2659-4ff5-b53a-5795c2e5e2ff.rar这是可以支持参数的命令shell。
一、移植目的
1、结合命令界面的改进,实现文件系统与命令界面的结合使用。
2、在命令界面中实现以下文件系统操作命令:flist-列出当前目录下的文件;fmkdir-在当前目录下创建目录;fchgdir-改变当前目录;fread-读取文件内容;fwrite-新建文件并写入。
二、移植条件
1、可以识别参数的串口命令界面。
2、FatFS007e版本。
三、对命令界面所实现功能的描述
1、超级终端设置。
首先打开串口终端,设置波特率115200,8位数据,无奇偶校验,无流控,终端仿真选择ANSIW,asicc码设置为以换行符结尾(以前设置的,原因已经忘了),反正这样设置了能够正常工作。
开发板复位后,终端显示:**********nthq2004 编写的简单命令接口!*********
Sh> 然后可以在这里输入命令执行。比如现在支持的命令包括:"help","cls","ledon","ledoff","time","temp","i2cwr","i2crd","sdrd","sdwr",共10个命令。比如输入help me命令,则会显示命令界面当前支持的所有命令,并显示当前所有输入的命令参数。所以命令执行过程的分析以help me为例,help是命令,me是参数。
2、串口终端命令输入过程
在串口终端输入一个字符时,其工作工程为:
void USART1_IRQHandler(void){ //该函数在文件stm<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />32f10x_it.c中
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL();
OSIntNesting++; //中断嵌套计数
OS_EXIT_CRITICAL();
if ( USART_GetITStatus ( USART1, USART_IT_RXNE )!= RESET )
{ Uart_ReceiveChar(); //串口接收字符 }
OSIntExit(); //这里可以触发任务切换软中断
}
串口接收到字符引起终端、然后调用函数Uart_ReceiveChar()获取字符并放入串口消息队列,
void Uart_ReceiveChar (void) { //该函数在文件uart.c中
u32 RecChar;
RecChar = (u32)(USART1->DR & 0xFF);
OSQPost ( UartMsgOSQ, ( void* )RecChar ); //将字符指针化放入消息队列,这里接用了周慈航教授书中的方法。}
在task_uartcmd.c文件创建的串口界面任务中,
case UartStateInput: //如果出于输入状态
{ UartCharIn=Uart_GetChar(); //读取输入按键
UartCharIn &= 0x7F;
该函数从消息队列中取得从串口接收到的字符,然后放入到串口命令缓冲数组。
UartCmdBuf[UartCharCount]=UartCharIn; //将字符存入缓冲区当前位置
UartCharCount +=1;
Uart_PutChar( UartCharIn );//将有效字符输出。这是在用户电脑的超级终端上进行回显。}
如果用户在超级终端上按下了回车键:
if(UartCharIn=='\n') // 如果按下了Enter键,它是触发软件状态机从输入态
{ // 进入命令解释执行态的关键。
UartCmdBuf[UartCharCount]='\0'; //命令缓冲区以0结束
Uart_PutString( "\r\n" ); //显示器上回显换行
UartCmdState=UartStateExe; //如果输入过字符,进入命令解释态
UartCharCount=0;
}
3、串口命令执行过程
进入命令执行态后,首先进行命令缓冲字符串的解析,从中分析出命令和参数:
case UartStateExe: //如果处于命令执行态
{
UartParseCmdBuf(UartCmdBuf,&CmdArg); //命令缓冲字符串的解析
解析后得到一个结构数组,指明参数的个数和一个指向参数指针数组的指针:
该数组的第一个指针指向命令字符串,第二个开始指向参数。
UartCmdStr=CmdArg.Argv[0]; //解析命令缓冲区,得到命令结构信息,我这里还只支持简单命令
//所以处理很简单,直接获得命令字符串,以后可以扩展。 for(UartCmdIndex=0; UartCmdIndex<UartCmdMaxCount; UartCmdIndex++ )
{ // 在命令表里搜索对应命令字符串
UartCompResult=strcmp((char*)UartCmdStr, (char*)(UartCmdStrTable[UartCmdIndex]) );
//命令字符串比较的结果
if (UartCompResult==0) //如果在字符串表里找到。返回0.
break; //此时CmdIndex对应的值为命令在命令表里的索引。 }
if ( UartCmdIndex<UartCmdMaxCount)
{ //找到对应命令,调用相应函数处理
argc=CmdArg.Argc;
for ( j="0"; j<argc; j++ )
{ argv[j]=(void*)CmdArg.Argv[j];
}
UartCmdTable[UartCmdIndex].UartCmdFunc(argc,argv);//利用
}
实际上输入命令help me,此时调用的函数就是:
UartCmdTable[0].UartCmdFunc=UartCmdHelp;
该函数的源代码在文件uartcmd.c文件中:
void UartCmdHelp(u8 argc,void **argv){
u8 i;
Uart_PutString("You entered the parameter: ");
for ( i="1"; i<argc; i++ )
{
Uart_PutString( argv ); /这是将后面的参数一一列出来。
Uart_PutString( " " );
}
Uart_PutString( "\r\n" ); /这是将命令界面支持的命令列举出来。
Uart_PutString("cls ");
Uart_PutString("ledon ");
Uart_PutString("ledoff ");
Uart_PutString("time ");
Uart_PutString("temp ");
Uart_PutString("i2cwr ");
Uart_PutString("i2crd \r\n");
Uart_PutString("sdrd ");
Uart_PutString("sdwr \r\n");
}
用户1010563 2014-6-17 09:49