?? usmart.c
字號:
#include "usmart.h"
#include "usart.h"
#include "timer.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學習使用,未經作者許可,不得用于其它任何用途
//ALIENTEK STM32開發板
//正點原子@ALIENTEK
//技術論壇:www.openedv.com
//修改日期:2011/6/13
//版本:V2.0
//版權所有,盜版必究。
//Copyright(C) 正點原子 2011-2021
//All rights reserved
//********************************************************************************
//升級說明
//V1.4
//增加了對參數為string類型的函數的支持.適用范圍大大提高.
//優化了內存占用,靜態內存占用為79個字節@10個參數.動態適應數字及字符串長度
//V2.0,
//1,修改了list指令,打印函數的完整表達式.
//2,增加了id指令,打印每個函數的入口地址.
//3,修改了參數匹配,支持函數參數的調用(輸入入口地址).
//4,增加了函數名長度宏定義.
/////////////////////////////////////////////////////////////////////////////////////
//系統命令
u8 *sys_cmd_tab[]=
{
"?",
"help",
"list",
"id",
};
//處理系統指令
//0,成功處理;其他,錯誤代碼;
u8 usmart_sys_cmd_exe(u8 *str)
{
u8 i;
u8 sfname[MAX_FNAME_LEN];//存放本地函數名
u8 pnum;
for(i=0;i<4;i++)//支持4個系統指令
{
if(usmart_strcmp(str,sys_cmd_tab[i]))break;
}
switch(i)
{
case 0:
case 1://幫助指令
printf("\r\n");
#if USMART_USE_HELP
printf("------------------------USMART V2.0------------------------ \r\n");
printf(" USMART是由ALIENTEK開發的一個靈巧的串口調試互交組件,通過 \r\n");
printf("它,你可以通過串口助手調用程序里面的任何函數,并執行.因此,你可\r\n");
printf("以隨意更改函數的輸入參數(支持數字(10/16進制)、字符串、函數入\r\n");
printf("口地址等作為參數),單個函數最多支持10個輸入參數,并支持函數返 \r\n");
printf("回值顯示. 技術支持:www.openedv.com\r\n");
printf("USMART有4個系統命令:\r\n");
printf("?: 獲取幫助信息\r\n");
printf("help: 獲取幫助信息\r\n");
printf("list: 可用的函數列表\r\n\n");
printf("id: 可用函數的ID列表\r\n\n");
printf("請按照程序編寫格式輸入函數名及參數并以回車鍵結束.\r\n");
printf("--------------------------ALIENTEK------------------------- \r\n");
#else
printf("指令失效\r\n");
#endif
break;
case 2://查詢指令
printf("\r\n");
printf("-------------------------函數清單--------------------------- \r\n");
for(i=0;i<usmart_dev.fnum;i++)printf("%s\r\n",usmart_dev.funs[i].name);
printf("\r\n\n");
break;
case 3://查詢ID
printf("\r\n");
printf("-------------------------函數 ID --------------------------- \r\n");
for(i=0;i<usmart_dev.fnum;i++)
{
usmart_get_fname((u8*)usmart_dev.funs[i].name,sfname,&pnum);//得到本地函數名
printf("%s id is:\r\n0x%08x\r\n",sfname,usmart_dev.funs[i].func); //顯示ID
}
printf("\r\n\n");
break;
default://非法指令
return 1;
}
return 0;
}
//初始化串口控制器
void usmart_init(void)
{
//必須使能串口中斷接收
uart_init(72,9600); //串口1初始化
Timer2_Init(1000,7199); //7200分頻,時鐘為10K ,100ms中斷一次
}
//從str中獲取函數名,id,及參數信息
//*str:字符串指針.
//返回值:0,識別成功;其他,錯誤代碼.
u8 usmart_cmd_rec(u8*str)
{
u8 sta,i;//狀態
u8 rpnum,spnum;
u8 rfname[MAX_FNAME_LEN];//暫存空間,用于存放接收到的函數名
u8 sfname[MAX_FNAME_LEN];//存放本地函數名
sta=usmart_get_fname(str,rfname,&rpnum);//得到接收到的數據的函數名及參數個數
if(sta)return sta;//錯誤
for(i=0;i<usmart_dev.fnum;i++)
{
sta=usmart_get_fname((u8*)usmart_dev.funs[i].name,sfname,&spnum);//得到本地函數名及參數個數
if(sta)return sta;//本地解析有誤
if(usmart_strcmp(sfname,rfname))//相等
{
if(spnum>rpnum)return USMART_PARMERR;//參數錯誤(輸入參數比源函數參數少)
usmart_dev.id=i;//記錄函數ID.
break;//跳出.
}
}
if(i==usmart_dev.fnum)return USMART_NOFUNCFIND; //未找到匹配的函數
sta=usmart_get_fparam(str,&i); //得到函數參數個數
if(sta)return sta; //返回錯誤
usmart_dev.pnum=i; //參數個數記錄
return USMART_OK;
}
//usamrt執行函數
//該函數用于最終執行從串口收到的有效函數.
//最多支持10個參數的函數,更多的參數支持也很容易實現.不過用的很少.一般5個左右的參數的函數已經很少見了.
//該函數會在串口打印執行情況.以:"函數名(參數1,參數2...參數N)=返回值".的形式打印.
//當所執行的函數沒有返回值的時候,所打印的返回值是一個無意義的數據.
void usmart_exe(void)
{
u8 id,i;
u32 res;
u32 temp[MAX_PARM];//參數轉換,使之支持了字符串
u8 sfname[MAX_FNAME_LEN];//存放本地函數名
u8 pnum;
id=usmart_dev.id;
if(id>=usmart_dev.fnum)return;//不執行.
usmart_get_fname((u8*)usmart_dev.funs[id].name,sfname,&pnum);//得到本地函數名,及參數個數
printf("\r\n%s(",sfname);//輸出正要執行的函數名
for(i=0;i<pnum;i++)//輸出參數
{
if(usmart_dev.parmtype&(1<<i))//參數是字符串
{
printf("%c",'"');
printf("%s",usmart_dev.parm+usmart_get_parmpos(i));
printf("%c",'"');
temp[i]=(u32)&(usmart_dev.parm[usmart_get_parmpos(i)]);
}else //參數是數字
{
temp[i]=*(u32*)(usmart_dev.parm+usmart_get_parmpos(i));
printf("%d",temp[i]);
}
if(i!=pnum-1)printf(",");
}
printf(")");
switch(usmart_dev.pnum)
{
case 0://無參數(void類型)
res=(*(u32(*)())usmart_dev.funs[id].func)();
break;
case 1://有1個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
break;
case 2://有2個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1]);
break;
case 3://有3個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2]);
break;
case 4://有4個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3]);
break;
case 5://有5個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4]);
break;
case 6://有6個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
temp[5]);
break;
case 7://有7個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
temp[5],temp[6]);
break;
case 8://有8個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
temp[5],temp[6],temp[7]);
break;
case 9://有9個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
temp[5],temp[6],temp[7],temp[8]);
break;
case 10://有10個參數
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
temp[5],temp[6],temp[7],temp[8],temp[9]);
break;
}
printf("=%d;\r\n",res);//輸出執行結果.
}
//usmart掃描函數
//通過調用該函數,實現usmart的各個控制.該函數需要每隔一定時間被調用一次
//以及時執行從串口發過來的各個函數.
//本函數可以在中斷里面調用,從而實現自動管理.
//如果非ALIENTEK用戶,則USART_RX_STA和USART_RX_BUF[]需要用戶自己實現
void usmart_scan(void)
{
u8 sta,len;
if(USART_RX_STA&0x8000)//串口接收完成?
{
len=USART_RX_STA&0x3fff; //得到此次接收到的數據長度
USART_RX_BUF[len]='\0'; //在末尾加入結束符.
sta=usmart_dev.cmd_rec(USART_RX_BUF);//得到函數各個信息
if(sta==0)usmart_dev.exe();//執行函數
else if(usmart_sys_cmd_exe(USART_RX_BUF))
{
switch(sta)
{
case USMART_FUNCERR:
printf("函數錯誤!\r\n");
break;
case USMART_PARMERR:
printf("參數錯誤!\r\n");
break;
case USMART_PARMOVER:
printf("參數太多!\r\n");
break;
case USMART_NOFUNCFIND:
printf("未找到匹配的函數!\r\n");
break;
}
}
USART_RX_STA=0;//狀態寄存器清空
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -