feat: KT mBMS 펌웨어 3종(HW1/2/3) 및 통합 빌드 환경 초기 커밋 (V4.0.0.1)
This commit is contained in:
63
mBMS_APP_V3117/USMART/readme.txt
Normal file
63
mBMS_APP_V3117/USMART/readme.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
USMART V3.1
|
||||
USMART是由ALIENTEK开发的一个灵巧的串口调试互交组件,通过 它,你可以通过串口助手调用程
|
||||
序里面的任何函数,并执行.因此,你可以随意更改函数的输入参数(支持数字(10/16进制)、字符串、
|
||||
函数入口地址等作为参数),单个函数最多支持10个输入参数,并支持函数返 回值显示.V2.1新增
|
||||
hex和dec两个指令.他们可以用于设置函数参数的显示格式.也可以用于数据的进制转换.
|
||||
例如:
|
||||
输入"hex 100" 会在串口调试助手上看到 HEX 0X64.
|
||||
输入"dec 0X64" 会在串口调试助手上看到 DEC 100.
|
||||
|
||||
升级说明
|
||||
V1.4
|
||||
增加了对参数为string类型的函数的支持.适用范围大大提高.
|
||||
优化了内存占用,静态内存占用为79个字节@10个参数.动态适应数字及字符串长度
|
||||
V2.0
|
||||
1,修改了list指令,打印函数的完整表达式.
|
||||
2,增加了id指令,打印每个函数的入口地址.
|
||||
3,修改了参数匹配,支持函数参数的调用(输入入口地址).
|
||||
4,增加了函数名长度宏定义.
|
||||
V2.1 20110707
|
||||
1,增加dec,hex两个指令,用于设置参数显示进制,及执行进制转换.
|
||||
注:当dec,hex不带参数的时候,即设定显示参数进制.当后跟参数的时候,即执行进制转换.
|
||||
如:"dec 0XFF" 则会将0XFF转为255,由串口返回.
|
||||
如:"hex 100" 则会将100转为0X64,由串口返回
|
||||
2,新增usmart_get_cmdname函数,用于获取指令名字.
|
||||
V2.2 20110726
|
||||
1,修正了void类型参数的参数统计错误.
|
||||
2,修改数据显示格式默认为16进制.
|
||||
V2.3 20110815
|
||||
1,去掉了函数名后必须跟"("的限制.
|
||||
2,修正了字符串参数中不能有"("的bug.
|
||||
3,修改了函数默认显示参数格式的修改方式.
|
||||
V2.4 20110905
|
||||
1,修改了usmart_get_cmdname函数,增加最大参数长度限制.避免了输入错误参数时的死机现象.
|
||||
2,增加USMART_ENTIM2_SCAN宏定义,用于配置是否使用TIM2定时执行scan函数.
|
||||
V2.5 20110930
|
||||
1,修改usmart_init函数为void usmart_init(u8 sysclk),可以根据系统频率自动设定扫描时间.(固定100ms)
|
||||
2,去掉了usmart_init函数中的uart_init函数,串口初始化必须在外部初始化,方便用户自行管理.
|
||||
V2.6 20111009
|
||||
1,增加了read_addr和write_addr两个函数.可以利用这两个函数读写内部任意地址(必须是有效地址).更加方便调试.
|
||||
2,read_addr和write_addr两个函数可以通过设置USMART_USE_WRFUNS为来使能和关闭.
|
||||
3,修改了usmart_strcmp,使其规范化.
|
||||
V2.7 20111024
|
||||
1,修正了返回值16进制显示时不换行的bug.
|
||||
2,增加了函数是否有返回值的判断,如果没有返回值,则不会显示.有返回值时才显示其返回值.
|
||||
V2.8 20111116
|
||||
1,修正了list等不带参数的指令发送后可能导致死机的bug.
|
||||
V2.9 20120917
|
||||
1,修改了形如:void*xxx(void)类型函数不能识别的bug。
|
||||
V3.0 20130425
|
||||
1,新增了字符串参数对转义符的支持。
|
||||
V3.1 20131120
|
||||
1,增加runtime系统指令,可以用于统计函数执行时间.
|
||||
用法:
|
||||
发送:runtime 1 ,则开启函数执行时间统计功能
|
||||
发送:runtime 0 ,则关闭函数执行时间统计功能
|
||||
runtime统计功能,必须设置:USMART_ENTIMX_SCAN 为1,才可以使用!!
|
||||
|
||||
|
||||
|
||||
正点原子@ALIENTEK
|
||||
技术论坛:www.openedv.com
|
||||
修改日期:2013/11/20
|
||||
Copyright(C) ALIENTEK 2011-2021
|
||||
451
mBMS_APP_V3117/USMART/usmart.c
Normal file
451
mBMS_APP_V3117/USMART/usmart.c
Normal file
@@ -0,0 +1,451 @@
|
||||
#include "usmart.h"
|
||||
#include "usart.h"
|
||||
#include "sys.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32 development board
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Version: V3.1
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2011-2021
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//Upgrade instructions
|
||||
//V1.4
|
||||
// Added support for function of the parameter to a string type. scope greatly.
|
||||
// Optimized memory usage static memory footprint to 79 bytes @10 parameters. dynamic numbers and the length of the string
|
||||
//V2.0
|
||||
// 1, modify the list command, the print function series.
|
||||
// 2, increasing the ID command, print each function entry addresses.
|
||||
// 3, modified the parameters, supported calls for function parameters (inlet).
|
||||
// 4, increase the length of the function name macro definition.
|
||||
//V2.1 20110707
|
||||
//1,增加dec,hex两个指令,用于设置参数显示进制,及执行进制转换.
|
||||
//注:当dec,hex不带参数的时候,即设定显示参数进制.当后跟参数的时候,即执行进制转换.
|
||||
//如:"dec 0XFF" 则会将0XFF转为255,由串口返回.
|
||||
//如:"hex 100" 则会将100转为0X64,由串口返回
|
||||
//2,新增usmart_get_cmdname函数,用于获取指令名字.
|
||||
//V2.2 20110726
|
||||
//1,修正了void类型参数的参数统计错误.
|
||||
//2,修改数据显示格式默认为16进制.
|
||||
//V2.3 20110815
|
||||
//1,去掉了函数名后必须跟"("的限制.
|
||||
//2,修正了字符串参数中不能有"("的bug.
|
||||
//3,修改了函数默认显示参数格式的修改方式.
|
||||
//V2.4 20110905
|
||||
//1,修改了usmart_get_cmdname函数,增加最大参数长度限制.避免了输入错误参数时的死机现象.
|
||||
//2,增加USMART_ENTIM2_SCAN宏定义,用于配置是否使用TIM2定时执行scan函数.
|
||||
//V2.5 20110930
|
||||
//1,修改usmart_init函数为void usmart_init(u8 sysclk),可以根据系统频率自动设定扫描时间.(固定100ms)
|
||||
//2,去掉了usmart_init函数中的uart_init函数,串口初始化必须在外部初始化,方便用户自行管理.
|
||||
//V2.6 20111009
|
||||
//1,增加了read_addr和write_addr两个函数.可以利用这两个函数读写内部任意地址(必须是有效地址).更加方便调试.
|
||||
//2,read_addr和write_addr两个函数可以通过设置USMART_USE_WRFUNS为来使能和关闭.
|
||||
//3,修改了usmart_strcmp,使其规范化.
|
||||
//V2.7 20111024
|
||||
//1,修正了返回值16进制显示时不换行的bug.
|
||||
//2,增加了函数是否有返回值的判断,如果没有返回值,则不会显示.有返回值时才显示其返回值.
|
||||
//V2.8 20111116
|
||||
//1,修正了list等不带参数的指令发送后可能导致死机的bug.
|
||||
//V2.9 20120917
|
||||
//1,修改了形如:void*xxx(void)类型函数不能识别的bug。
|
||||
//V3.0 20130425
|
||||
//1,新增了字符串参数对转义符的支持。
|
||||
//V3.1 20131120
|
||||
//1,增加runtime系统指令,可以用于统计函数执行时间.
|
||||
//用法:
|
||||
//发送:runtime 1 ,则开启函数执行时间统计功能
|
||||
//发送:runtime 0 ,则关闭函数执行时间统计功能
|
||||
///runtime统计功能,必须设置:USMART_ENTIMX_SCAN 为1,才可以使用!!
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//系统命令
|
||||
u8 *sys_cmd_tab[]=
|
||||
{
|
||||
"?",
|
||||
"help",
|
||||
"list",
|
||||
"id",
|
||||
"hex",
|
||||
"dec",
|
||||
"runtime",
|
||||
};
|
||||
//处理系统指令
|
||||
//0,成功处理;其他,错误代码;
|
||||
u8 usmart_sys_cmd_exe(u8 *str)
|
||||
{
|
||||
u8 i;
|
||||
u8 sfname[MAX_FNAME_LEN];//存放本地函数名
|
||||
u8 pnum;
|
||||
u8 rval;
|
||||
u32 res;
|
||||
res=usmart_get_cmdname(str,sfname,&i,MAX_FNAME_LEN);//得到指令及指令长度
|
||||
if(res)return USMART_FUNCERR;//错误的指令
|
||||
str+=i;
|
||||
for(i=0;i<sizeof(sys_cmd_tab)/4;i++)//支持的系统指令
|
||||
{
|
||||
if(usmart_strcmp(sfname,sys_cmd_tab[i])==0)break;
|
||||
}
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
case 1://帮助指令
|
||||
printf("\r\n");
|
||||
#if USMART_USE_HELP
|
||||
printf("------------------------USMART V3.1------------------------ \r\n");
|
||||
printf(" USMART是由ALIENTEK开发的一个灵巧的串口调试互交组件,通过 \r\n");
|
||||
printf("它,你可以通过串口助手调用程序里面的任何函数,并执行.因此,你可\r\n");
|
||||
printf("以随意更改函数的输入参数(支持数字(10/16进制)、字符串、函数入\r\n");
|
||||
printf("口地址等作为参数),单个函数最多支持10个输入参数,并支持函数返 \r\n");
|
||||
printf("回值显示.新增参数显示进制设置功能,新增进制转换功能.\r\n");
|
||||
printf("技术支持:www.openedv.com\r\n");
|
||||
printf("USMART有7个系统命令:\r\n");
|
||||
printf("?: 获取帮助信息\r\n");
|
||||
printf("help: 获取帮助信息\r\n");
|
||||
printf("list: 可用的函数列表\r\n\n");
|
||||
printf("id: 可用函数的ID列表\r\n\n");
|
||||
printf("hex: 参数16进制显示,后跟空格+数字即执行进制转换\r\n\n");
|
||||
printf("dec: 参数10进制显示,后跟空格+数字即执行进制转换\r\n\n");
|
||||
printf("runtime:1,开启函数运行计时;0,关闭函数运行计时;\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");
|
||||
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,&rval);//得到本地函数名
|
||||
printf("%s id is:\r\n0X%08X\r\n",sfname,usmart_dev.funs[i].func); //显示ID
|
||||
}
|
||||
printf("\r\n");
|
||||
break;
|
||||
case 4://hex指令
|
||||
printf("\r\n");
|
||||
usmart_get_aparm(str,sfname,&i);
|
||||
if(i==0)//参数正常
|
||||
{
|
||||
i=usmart_str2num(sfname,&res); //记录该参数
|
||||
if(i==0) //进制转换功能
|
||||
{
|
||||
printf("HEX:0X%X\r\n",res); //转为16进制
|
||||
}else if(i!=4)return USMART_PARMERR;//参数错误.
|
||||
else //参数显示设定功能
|
||||
{
|
||||
printf("16进制参数显示!\r\n");
|
||||
usmart_dev.sptype=SP_TYPE_HEX;
|
||||
}
|
||||
|
||||
}else return USMART_PARMERR; //参数错误.
|
||||
printf("\r\n");
|
||||
break;
|
||||
case 5://dec指令
|
||||
printf("\r\n");
|
||||
usmart_get_aparm(str,sfname,&i);
|
||||
if(i==0)//参数正常
|
||||
{
|
||||
i=usmart_str2num(sfname,&res); //记录该参数
|
||||
if(i==0) //进制转换功能
|
||||
{
|
||||
printf("DEC:%lu\r\n",res); //转为10进制
|
||||
}else if(i!=4)return USMART_PARMERR;//参数错误.
|
||||
else //参数显示设定功能
|
||||
{
|
||||
printf("10进制参数显示!\r\n");
|
||||
usmart_dev.sptype=SP_TYPE_DEC;
|
||||
}
|
||||
|
||||
}else return USMART_PARMERR; //参数错误.
|
||||
printf("\r\n");
|
||||
break;
|
||||
case 6://runtime指令,设置是否显示函数执行时间
|
||||
printf("\r\n");
|
||||
usmart_get_aparm(str,sfname,&i);
|
||||
if(i==0)//参数正常
|
||||
{
|
||||
i=usmart_str2num(sfname,&res); //记录该参数
|
||||
if(i==0) //读取指定地址数据功能
|
||||
{
|
||||
if(USMART_ENTIMX_SCAN==0)printf("\r\nError! \r\nTo EN RunTime function,Please set USMART_ENTIMX_SCAN = 1 first!\r\n");//报错
|
||||
else
|
||||
{
|
||||
usmart_dev.runtimeflag=res;
|
||||
if(usmart_dev.runtimeflag)printf("Run Time Calculation ON\r\n");
|
||||
else printf("Run Time Calculation OFF\r\n");
|
||||
}
|
||||
}else return USMART_PARMERR; //未带参数,或者参数错误
|
||||
}else return USMART_PARMERR; //参数错误.
|
||||
printf("\r\n");
|
||||
break;
|
||||
default://非法指令
|
||||
return USMART_FUNCERR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//移植注意:本例是以stm32为例,如果要移植到其他mcu,请做相应修改.
|
||||
//usmart_reset_runtime,清除函数运行时间,连同定时器的计数寄存器以及标志位一起清零.并设置重装载值为最大,以最大限度的延长计时时间.
|
||||
//usmart_get_runtime,获取函数运行时间,通过读取CNT值获取,由于usmart是通过中断调用的函数,所以定时器中断不再有效,此时最大限度
|
||||
//只能统计2次CNT的值,也就是清零后+溢出一次,当溢出超过2次,没法处理,所以最大延时,控制在:2*计数器CNT*0.1ms.对STM32来说,是:13.1s左右
|
||||
//其他的:TIM4_IRQHandler和Timer4_Init,需要根据MCU特点自行修改.确保计数器计数频率为:10Khz即可.另外,定时器不要开启自动重装载功能!!
|
||||
|
||||
#if USMART_ENTIMX_SCAN==1
|
||||
//复位runtime
|
||||
//需要根据所移植到的MCU的定时器参数进行修改
|
||||
void usmart_reset_runtime(void)
|
||||
{
|
||||
|
||||
TIM_ClearFlag(TIM4,TIM_FLAG_Update);//清除中断标志位
|
||||
TIM_SetAutoreload(TIM4,0XFFFF);//将重装载值设置到最大
|
||||
TIM_SetCounter(TIM4,0); //清空定时器的CNT
|
||||
usmart_dev.runtime=0;
|
||||
}
|
||||
//获得runtime时间
|
||||
//返回值:执行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
|
||||
//需要根据所移植到的MCU的定时器参数进行修改
|
||||
u32 usmart_get_runtime(void)
|
||||
{
|
||||
if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update)==SET)//在运行期间,产生了定时器溢出
|
||||
{
|
||||
usmart_dev.runtime+=0XFFFF;
|
||||
}
|
||||
usmart_dev.runtime+=TIM_GetCounter(TIM4);
|
||||
return usmart_dev.runtime; //返回计数值
|
||||
}
|
||||
//下面这两个函数,非USMART函数,放到这里,仅仅方便移植.
|
||||
//定时器4中断服务程序
|
||||
void TIM4_IRQHandler(void)
|
||||
{
|
||||
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)//溢出中断
|
||||
{
|
||||
usmart_dev.scan(); //执行usmart扫描
|
||||
TIM_SetCounter(TIM4,0); //清空定时器的CNT
|
||||
TIM_SetAutoreload(TIM4,100);//恢复原来的设置
|
||||
}
|
||||
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志位
|
||||
}
|
||||
//使能定时器4,使能中断.
|
||||
void Timer4_Init(u16 arr,u16 psc)
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
|
||||
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); ///使能TIM4时钟
|
||||
|
||||
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
|
||||
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
|
||||
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动重装载值
|
||||
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
|
||||
|
||||
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化定时器4
|
||||
|
||||
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器4更新中断
|
||||
TIM_Cmd(TIM4,ENABLE); //使能定时器4
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//外部中断4
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级3
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;//子优先级3
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
|
||||
NVIC_Init(&NVIC_InitStructure);//配置NVIC
|
||||
|
||||
}
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//初始化串口控制器
|
||||
//sysclk:系统时钟(Mhz)
|
||||
void usmart_init(u8 sysclk)
|
||||
{
|
||||
#if USMART_ENTIMX_SCAN==1
|
||||
Timer4_Init(1000,(u32)sysclk*100-1);//分频,时钟为10K ,100ms中断一次,注意,计数频率必须为10Khz,以和runtime单位(0.1ms)同步.
|
||||
#endif
|
||||
usmart_dev.sptype=1; //十六进制显示参数
|
||||
}
|
||||
//从str中获取函数名,id,及参数信息
|
||||
//*str:字符串指针.
|
||||
//返回值:0,识别成功;其他,错误代码.
|
||||
u8 usmart_cmd_rec(u8*str)
|
||||
{
|
||||
u8 sta,i,rval;//状态
|
||||
u8 rpnum,spnum;
|
||||
u8 rfname[MAX_FNAME_LEN];//暂存空间,用于存放接收到的函数名
|
||||
u8 sfname[MAX_FNAME_LEN];//存放本地函数名
|
||||
sta=usmart_get_fname(str,rfname,&rpnum,&rval);//得到接收到的数据的函数名及参数个数
|
||||
if(sta)return sta;//错误
|
||||
for(i=0;i<usmart_dev.fnum;i++)
|
||||
{
|
||||
sta=usmart_get_fname((u8*)usmart_dev.funs[i].name,sfname,&spnum,&rval);//得到本地函数名及参数个数
|
||||
if(sta)return sta;//本地解析有误
|
||||
if(usmart_strcmp(sfname,rfname)==0)//相等
|
||||
{
|
||||
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,rval;
|
||||
id=usmart_dev.id;
|
||||
if(id>=usmart_dev.fnum)return;//不执行.
|
||||
usmart_get_fname((u8*)usmart_dev.funs[id].name,sfname,&pnum,&rval);//得到本地函数名,及参数个数
|
||||
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));
|
||||
if(usmart_dev.sptype==SP_TYPE_DEC)printf("%lu",temp[i]);//10进制参数显示
|
||||
else printf("0X%X",temp[i]);//16进制参数显示
|
||||
}
|
||||
if(i!=pnum-1)printf(",");
|
||||
}
|
||||
printf(")");
|
||||
usmart_reset_runtime(); //计时器清零,开始计时
|
||||
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;
|
||||
}
|
||||
usmart_get_runtime();//获取函数执行时间
|
||||
if(rval==1)//需要返回值.
|
||||
{
|
||||
if(usmart_dev.sptype==SP_TYPE_DEC)printf("=%lu;\r\n",res);//输出执行结果(10进制参数显示)
|
||||
else printf("=0X%X;\r\n",res);//输出执行结果(16进制参数显示)
|
||||
}else printf(";\r\n"); //不需要返回值,直接输出结束
|
||||
if(usmart_dev.runtimeflag) //需要显示函数执行时间
|
||||
{
|
||||
printf("Function Run Time:%d.%1dms\r\n",usmart_dev.runtime/10,usmart_dev.runtime%10);//打印函数执行时间
|
||||
}
|
||||
}
|
||||
//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
|
||||
{
|
||||
len=usmart_sys_cmd_exe(USART_RX_BUF);
|
||||
if(len!=USMART_FUNCERR)sta=len;
|
||||
if(sta)
|
||||
{
|
||||
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;//状态寄存器清空
|
||||
}
|
||||
}
|
||||
|
||||
#if USMART_USE_WRFUNS==1 //如果使能了读写操作
|
||||
//读取指定地址的值
|
||||
u32 read_addr(u32 addr)
|
||||
{
|
||||
return *(u32*)addr;//
|
||||
}
|
||||
//在指定地址写入指定的值
|
||||
void write_addr(u32 addr,u32 val)
|
||||
{
|
||||
*(u32*)addr=val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
158
mBMS_APP_V3117/USMART/usmart.h
Normal file
158
mBMS_APP_V3117/USMART/usmart.h
Normal file
@@ -0,0 +1,158 @@
|
||||
#ifndef __USMART_H
|
||||
#define __USMART_H
|
||||
#include "usmart_str.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
|
||||
//ALIENTEK STM32开发板
|
||||
//正点原子@ALIENTEK
|
||||
//技术论坛:www.openedv.com
|
||||
//版本:V3.1
|
||||
//版权所有,盗版必究。
|
||||
//Copyright(C) 正点原子 2011-2021
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//升级说明
|
||||
//V1.4
|
||||
//增加了对参数为string类型的函数的支持.适用范围大大提高.
|
||||
//优化了内存占用,静态内存占用为79个字节@10个参数.动态适应数字及字符串长度
|
||||
//V2.0
|
||||
//1,修改了list指令,打印函数的完整表达式.
|
||||
//2,增加了id指令,打印每个函数的入口地址.
|
||||
//3,修改了参数匹配,支持函数参数的调用(输入入口地址).
|
||||
//4,增加了函数名长度宏定义.
|
||||
//V2.1 20110707
|
||||
//1,增加dec,hex两个指令,用于设置参数显示进制,及执行进制转换.
|
||||
//注:当dec,hex不带参数的时候,即设定显示参数进制.当后跟参数的时候,即执行进制转换.
|
||||
//如:"dec 0XFF" 则会将0XFF转为255,由串口返回.
|
||||
//如:"hex 100" 则会将100转为0X64,由串口返回
|
||||
//2,新增usmart_get_cmdname函数,用于获取指令名字.
|
||||
//V2.2 20110726
|
||||
//1,修正了void类型参数的参数统计错误.
|
||||
//2,修改数据显示格式默认为16进制.
|
||||
//V2.3 20110815
|
||||
//1,去掉了函数名后必须跟"("的限制.
|
||||
//2,修正了字符串参数中不能有"("的bug.
|
||||
//3,修改了函数默认显示参数格式的修改方式.
|
||||
//V2.4 20110905
|
||||
//1,修改了usmart_get_cmdname函数,增加最大参数长度限制.避免了输入错误参数时的死机现象.
|
||||
//2,增加USMART_ENTIM2_SCAN宏定义,用于配置是否使用TIM2定时执行scan函数.
|
||||
//V2.5 20110930
|
||||
//1,修改usmart_init函数为void usmart_init(u8 sysclk),可以根据系统频率自动设定扫描时间.(固定100ms)
|
||||
//2,去掉了usmart_init函数中的uart_init函数,串口初始化必须在外部初始化,方便用户自行管理.
|
||||
//V2.6 20111009
|
||||
//1,增加了read_addr和write_addr两个函数.可以利用这两个函数读写内部任意地址(必须是有效地址).更加方便调试.
|
||||
//2,read_addr和write_addr两个函数可以通过设置USMART_USE_WRFUNS为来使能和关闭.
|
||||
//3,修改了usmart_strcmp,使其规范化.
|
||||
//V2.7 20111024
|
||||
//1,修正了返回值16进制显示时不换行的bug.
|
||||
//2,增加了函数是否有返回值的判断,如果没有返回值,则不会显示.有返回值时才显示其返回值.
|
||||
//V2.8 20111116
|
||||
//1,修正了list等不带参数的指令发送后可能导致死机的bug.
|
||||
//V2.9 20120917
|
||||
//1,修改了形如:void*xxx(void)类型函数不能识别的bug。
|
||||
//V3.0 20130425
|
||||
//1,新增了字符串参数对转义符的支持。
|
||||
//V3.1 20131120
|
||||
//1,增加runtime系统指令,可以用于统计函数执行时间.
|
||||
//用法:
|
||||
//发送:runtime 1 ,则开启函数执行时间统计功能
|
||||
//发送:runtime 0 ,则关闭函数执行时间统计功能
|
||||
///runtime统计功能,必须设置:USMART_ENTIMX_SCAN 为1,才可以使用!!
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//USMART资源占用情况@MDK 3.80A@2.0版本:
|
||||
//FLASH:4K~K字节(通过USMART_USE_HELP和USMART_USE_WRFUNS设置)
|
||||
//SRAM:72字节(最少的情况下)
|
||||
//SRAM计算公式: SRAM=PARM_LEN+72-4 其中PARM_LEN必须大于等于4.
|
||||
//应该保证堆栈不小于100个字节.
|
||||
////////////////////////////////////////////用户配置参数////////////////////////////////////////////////////
|
||||
#define MAX_FNAME_LEN 30 //函数名最大长度,应该设置为不小于最长函数名的长度。
|
||||
#define MAX_PARM 10 //最大为10个参数 ,修改此参数,必须修改usmart_exe与之对应.
|
||||
#define PARM_LEN 200 //所有参数之和的长度不超过PARM_LEN个字节,注意串口接收部分要与之对应(不小于PARM_LEN)
|
||||
|
||||
|
||||
#define USMART_ENTIMX_SCAN 1 //使用TIM的定时中断来扫描SCAN函数,如果设置为0,需要自己实现隔一段时间扫描一次scan函数.
|
||||
//注意:如果要用runtime统计功能,必须设置USMART_ENTIMX_SCAN为1!!!!
|
||||
|
||||
#define USMART_USE_HELP 1 //使用帮助,该值设为0,可以节省近700个字节,但是将导致无法显示帮助信息。
|
||||
#define USMART_USE_WRFUNS 1 //使用读写函数,使能这里,可以读取任何地址的值,还可以写寄存器的值.
|
||||
///////////////////////////////////////////////END///////////////////////////////////////////////////////////
|
||||
|
||||
#define USMART_OK 0 //无错误
|
||||
#define USMART_FUNCERR 1 //函数错误
|
||||
#define USMART_PARMERR 2 //参数错误
|
||||
#define USMART_PARMOVER 3 //参数溢出
|
||||
#define USMART_NOFUNCFIND 4 //未找到匹配函数
|
||||
|
||||
#define SP_TYPE_DEC 0 //10进制参数显示
|
||||
#define SP_TYPE_HEX 1 //16进制参数显示
|
||||
|
||||
|
||||
//函数名列表
|
||||
struct _m_usmart_nametab
|
||||
{
|
||||
void* func; //函数指针
|
||||
const u8* name; //函数名(查找串)
|
||||
};
|
||||
//usmart控制管理器
|
||||
struct _m_usmart_dev
|
||||
{
|
||||
struct _m_usmart_nametab *funs; //函数名指针
|
||||
|
||||
void (*init)(u8); //初始化
|
||||
u8 (*cmd_rec)(u8*str); //识别函数名及参数
|
||||
void (*exe)(void); //执行
|
||||
void (*scan)(void); //扫描
|
||||
u8 fnum; //函数数量
|
||||
u8 pnum; //参数数量
|
||||
u8 id; //函数id
|
||||
u8 sptype; //参数显示类型(非字符串参数):0,10进制;1,16进制;
|
||||
u16 parmtype; //参数的类型
|
||||
u8 plentbl[MAX_PARM]; //每个参数的长度暂存表
|
||||
u8 parm[PARM_LEN]; //函数的参数
|
||||
u8 runtimeflag; //0,不统计函数执行时间;1,统计函数执行时间,注意:此功能必须在USMART_ENTIMX_SCAN使能的时候,才有用
|
||||
u32 runtime; //运行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
|
||||
};
|
||||
extern struct _m_usmart_nametab usmart_nametab[]; //在usmart_config.c里面定义
|
||||
extern struct _m_usmart_dev usmart_dev; //在usmart_config.c里面定义
|
||||
|
||||
|
||||
void usmart_init(u8 sysclk);//初始化
|
||||
u8 usmart_cmd_rec(u8*str); //识别
|
||||
void usmart_exe(void); //执行
|
||||
void usmart_scan(void); //扫描
|
||||
u32 read_addr(u32 addr); //读取指定地址的值
|
||||
void write_addr(u32 addr,u32 val);//在指定地址写入指定的值
|
||||
u32 usmart_get_runtime(void); //获取运行时间
|
||||
void usmart_reset_runtime(void);//复位运行时间
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
86
mBMS_APP_V3117/USMART/usmart_config.c
Normal file
86
mBMS_APP_V3117/USMART/usmart_config.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "usmart.h"
|
||||
#include "usmart_str.h"
|
||||
////////////////////////////User Configuration area///////////////////////////////////////////////
|
||||
//Here you want to include the functions stated in the header file (allows you to add)
|
||||
#include "delay.h"
|
||||
#include "usart.h"
|
||||
#include "sys.h"
|
||||
#include "w25qxx.h"
|
||||
#include "fattester.h"
|
||||
|
||||
|
||||
//Function initializes the list (allows you to add)
|
||||
//Users directly in the input string to perform the function name and find
|
||||
struct _m_usmart_nametab usmart_nametab[]=
|
||||
{
|
||||
#if USMART_USE_WRFUNS==1 //If you enable the read and write operations
|
||||
(void*)read_addr ,(u8 *)"u32 read_addr(u32 addr)",
|
||||
(void*)write_addr ,(u8 *)"void write_addr(u32 addr,u32 val)",
|
||||
#endif
|
||||
(void*)delay_ms ,(u8 *)"void delay_ms(u16 nms)",
|
||||
(void*)delay_us ,(u8 *)"void delay_us(u32 nus)",
|
||||
|
||||
(void*)W25QXX_Erase_Chip,(u8 *)"void W25QXX_Erase_Chip(void)",
|
||||
(void*)mf_mount ,(u8 *)"u8 mf_mount(u8* path,u8 mt)",
|
||||
(void*)mf_open ,(u8 *)"u8 mf_open(u8*path,u8 mode)",
|
||||
(void*)mf_close ,(u8 *)"u8 mf_close(void)",
|
||||
(void*)mf_read ,(u8 *)"u8 mf_read(u16 len)",
|
||||
(void*)mf_write ,(u8 *)"u8 mf_write(u8*dat,u16 len)",
|
||||
(void*)mf_opendir ,(u8 *)"u8 mf_opendir(u8* path)",
|
||||
(void*)mf_closedir ,(u8 *)"u8 mf_closedir(void)",
|
||||
(void*)mf_readdir ,(u8 *)"u8 mf_readdir(void)",
|
||||
(void*)mf_scan_files,(u8 *)"u8 mf_scan_files(u8 * path)",
|
||||
(void*)mf_showfree ,(u8 *)"u32 mf_showfree(u8 *drv)",
|
||||
(void*)mf_lseek ,(u8 *)"u8 mf_lseek(u32 offset)",
|
||||
(void*)mf_tell ,(u8 *)"u32 mf_tell(void)",
|
||||
(void*)mf_size ,(u8 *)"u32 mf_size(void)",
|
||||
(void*)mf_mkdir ,(u8 *)"u8 mf_mkdir(u8*pname)",
|
||||
(void*)mf_fmkfs ,(u8 *)"u8 mf_fmkfs(u8* path,u8 mode,u16 au)",
|
||||
(void*)mf_unlink ,(u8 *)"u8 mf_unlink(u8 *pname)",
|
||||
(void*)mf_rename ,(u8 *)"u8 mf_rename(u8 *oldname,u8* newname)",
|
||||
(void*)mf_getlabel ,(u8 *)"void mf_getlabel(u8 *path)",
|
||||
(void*)mf_setlabel ,(u8 *)"void mf_setlabel(u8 *path)",
|
||||
(void*)mf_gets ,(u8 *)"void mf_gets(u16 size)",
|
||||
(void*)mf_putc ,(u8 *)"u8 mf_putc(u8 c)",
|
||||
(void*)mf_puts ,(u8 *)"u8 mf_puts(u8*c)",
|
||||
};
|
||||
|
||||
///////////////////////////////////END///////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//Function control manager initialize
|
||||
//Each control function name
|
||||
//Get total number of functions
|
||||
struct _m_usmart_dev usmart_dev=
|
||||
{
|
||||
usmart_nametab,
|
||||
usmart_init,
|
||||
usmart_cmd_rec,
|
||||
usmart_exe,
|
||||
usmart_scan,
|
||||
sizeof(usmart_nametab)/sizeof(struct _m_usmart_nametab),//Function number
|
||||
0, //Number of parameters
|
||||
0, //Function ID
|
||||
1, //Parameter display type, 0,10-; 1,16-
|
||||
0, //Parameter type. BITX:,0, Figure 1, the string
|
||||
0, //The length of staging tables for each parameter, you need to MAX_PARM a initialize 0
|
||||
0, //Parameter of the function, you need to PARM_LEN a initialize 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
426
mBMS_APP_V3117/USMART/usmart_str.c
Normal file
426
mBMS_APP_V3117/USMART/usmart_str.c
Normal file
@@ -0,0 +1,426 @@
|
||||
#include "usmart_str.h"
|
||||
#include "usmart.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
|
||||
//ALIENTEK STM32开发板
|
||||
//正点原子@ALIENTEK
|
||||
//技术论坛:www.openedv.com
|
||||
//版本:V3.1
|
||||
//版权所有,盗版必究。
|
||||
//Copyright(C) 正点原子 2011-2021
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//升级说明
|
||||
//V1.4
|
||||
//增加了对参数为string类型的函数的支持.适用范围大大提高.
|
||||
//优化了内存占用,静态内存占用为79个字节@10个参数.动态适应数字及字符串长度
|
||||
//V2.0
|
||||
//1,修改了list指令,打印函数的完整表达式.
|
||||
//2,增加了id指令,打印每个函数的入口地址.
|
||||
//3,修改了参数匹配,支持函数参数的调用(输入入口地址).
|
||||
//4,增加了函数名长度宏定义.
|
||||
//V2.1 20110707
|
||||
//1,增加dec,hex两个指令,用于设置参数显示进制,及执行进制转换.
|
||||
//注:当dec,hex不带参数的时候,即设定显示参数进制.当后跟参数的时候,即执行进制转换.
|
||||
//如:"dec 0XFF" 则会将0XFF转为255,由串口返回.
|
||||
//如:"hex 100" 则会将100转为0X64,由串口返回
|
||||
//2,新增usmart_get_cmdname函数,用于获取指令名字.
|
||||
//V2.2 20110726
|
||||
//1,修正了void类型参数的参数统计错误.
|
||||
//2,修改数据显示格式默认为16进制.
|
||||
//V2.3 20110815
|
||||
//1,去掉了函数名后必须跟"("的限制.
|
||||
//2,修正了字符串参数中不能有"("的bug.
|
||||
//3,修改了函数默认显示参数格式的修改方式.
|
||||
//V2.4 20110905
|
||||
//1,修改了usmart_get_cmdname函数,增加最大参数长度限制.避免了输入错误参数时的死机现象.
|
||||
//2,增加USMART_ENTIM2_SCAN宏定义,用于配置是否使用TIM2定时执行scan函数.
|
||||
//V2.5 20110930
|
||||
//1,修改usmart_init函数为void usmart_init(u8 sysclk),可以根据系统频率自动设定扫描时间.(固定100ms)
|
||||
//2,去掉了usmart_init函数中的uart_init函数,串口初始化必须在外部初始化,方便用户自行管理.
|
||||
//V2.6 20111009
|
||||
//1,增加了read_addr和write_addr两个函数.可以利用这两个函数读写内部任意地址(必须是有效地址).更加方便调试.
|
||||
//2,read_addr和write_addr两个函数可以通过设置USMART_USE_WRFUNS为来使能和关闭.
|
||||
//3,修改了usmart_strcmp,使其规范化.
|
||||
//V2.7 20111024
|
||||
//1,修正了返回值16进制显示时不换行的bug.
|
||||
//2,增加了函数是否有返回值的判断,如果没有返回值,则不会显示.有返回值时才显示其返回值.
|
||||
//V2.8 20111116
|
||||
//1,修正了list等不带参数的指令发送后可能导致死机的bug.
|
||||
//V2.9 20120917
|
||||
//1,修改了形如:void*xxx(void)类型函数不能识别的bug。
|
||||
//V3.0 20130425
|
||||
//1,新增了字符串参数对转义符的支持。
|
||||
//V3.1 20131120
|
||||
//1,增加runtime系统指令,可以用于统计函数执行时间.
|
||||
//用法:
|
||||
//发送:runtime 1 ,则开启函数执行时间统计功能
|
||||
//发送:runtime 0 ,则关闭函数执行时间统计功能
|
||||
///runtime统计功能,必须设置:USMART_ENTIMX_SCAN 为1,才可以使用!!
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//对比字符串str1和str2
|
||||
//*str1:字符串1指针
|
||||
//*str2:字符串2指针
|
||||
//返回值:0,相等;1,不相等;
|
||||
u8 usmart_strcmp(u8 *str1,u8 *str2)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
if(*str1!=*str2)return 1;//不相等
|
||||
if(*str1=='\0')break;//对比完成了.
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
return 0;//两个字符串相等
|
||||
}
|
||||
//把str1的内容copy到str2
|
||||
//*str1:字符串1指针
|
||||
//*str2:字符串2指针
|
||||
void usmart_strcopy(u8*str1,u8 *str2)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
*str2=*str1; //拷贝
|
||||
if(*str1=='\0')break;//拷贝完成了.
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
}
|
||||
//得到字符串的长度(字节)
|
||||
//*str:字符串指针
|
||||
//返回值:字符串的长度
|
||||
u8 usmart_strlen(u8*str)
|
||||
{
|
||||
u8 len=0;
|
||||
while(1)
|
||||
{
|
||||
if(*str=='\0')break;//拷贝完成了.
|
||||
len++;
|
||||
str++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
//m^n函数
|
||||
//返回值:m^n次方
|
||||
u32 usmart_pow(u8 m,u8 n)
|
||||
{
|
||||
u32 result=1;
|
||||
while(n--)result*=m;
|
||||
return result;
|
||||
}
|
||||
//把字符串转为数字
|
||||
//支持16进制转换,但是16进制字母必须是大写的,且格式为以0X开头的.
|
||||
//不支持负数
|
||||
//*str:数字字符串指针
|
||||
//*res:转换完的结果存放地址.
|
||||
//返回值:0,成功转换完成.其他,错误代码.
|
||||
//1,数据格式错误.2,16进制位数为0.3,起始格式错误.4,十进制位数为0.
|
||||
u8 usmart_str2num(u8*str,u32 *res)
|
||||
{
|
||||
u32 t;
|
||||
u8 bnum=0; //数字的位数
|
||||
u8 *p;
|
||||
u8 hexdec=10;//默认为十进制数据
|
||||
p=str;
|
||||
*res=0;//清零.
|
||||
while(1)
|
||||
{
|
||||
if((*p<='9'&&*p>='0')||(*p<='F'&&*p>='A')||(*p=='X'&&bnum==1))//参数合法
|
||||
{
|
||||
if(*p>='A')hexdec=16; //字符串中存在字母,为16进制格式.
|
||||
bnum++; //位数增加.
|
||||
}else if(*p=='\0')break; //碰到结束符,退出.
|
||||
else return 1; //不全是十进制或者16进制数据.
|
||||
p++;
|
||||
}
|
||||
p=str; //重新定位到字符串开始的地址.
|
||||
if(hexdec==16) //16进制数据
|
||||
{
|
||||
if(bnum<3)return 2; //位数小于3,直接退出.因为0X就占了2个,如果0X后面不跟数据,则该数据非法.
|
||||
if(*p=='0' && (*(p+1)=='X'))//必须以'0X'开头.
|
||||
{
|
||||
p+=2; //偏移到数据起始地址.
|
||||
bnum-=2;//减去偏移量
|
||||
}else return 3;//起始头的格式不对
|
||||
}else if(bnum==0)return 4;//位数为0,直接退出.
|
||||
while(1)
|
||||
{
|
||||
if(bnum)bnum--;
|
||||
if(*p<='9'&&*p>='0')t=*p-'0'; //得到数字的值
|
||||
else t=*p-'A'+10; //得到A~F对应的值
|
||||
*res+=t*usmart_pow(hexdec,bnum);
|
||||
p++;
|
||||
if(*p=='\0')break;//数据都查完了.
|
||||
}
|
||||
return 0;//成功转换
|
||||
}
|
||||
//得到指令名
|
||||
//*str:源字符串
|
||||
//*cmdname:指令名
|
||||
//*nlen:指令名长度
|
||||
//maxlen:最大长度(做限制,指令不可能太长的)
|
||||
//返回值:0,成功;其他,失败.
|
||||
u8 usmart_get_cmdname(u8*str,u8*cmdname,u8 *nlen,u8 maxlen)
|
||||
{
|
||||
*nlen=0;
|
||||
while(*str!=' '&&*str!='\0') //找到空格或者结束符则认为结束了
|
||||
{
|
||||
*cmdname=*str;
|
||||
str++;
|
||||
cmdname++;
|
||||
(*nlen)++;//统计命令长度
|
||||
if(*nlen>=maxlen)return 1;//错误的指令
|
||||
}
|
||||
*cmdname='\0';//加入结束符
|
||||
return 0;//正常返回
|
||||
}
|
||||
//获取下一个字符(当中间有很多空格的时候,此函数直接忽略空格,找到空格之后的第一个字符)
|
||||
//str:字符串指针
|
||||
//返回值:下一个字符
|
||||
u8 usmart_search_nextc(u8* str)
|
||||
{
|
||||
str++;
|
||||
while(*str==' '&&str!='\0')str++;
|
||||
return *str;
|
||||
}
|
||||
//从str中得到函数名
|
||||
//*str:源字符串指针
|
||||
//*fname:获取到的函数名字指针
|
||||
//*pnum:函数的参数个数
|
||||
//*rval:是否需要显示返回值(0,不需要;1,需要)
|
||||
//返回值:0,成功;其他,错误代码.
|
||||
u8 usmart_get_fname(u8*str,u8*fname,u8 *pnum,u8 *rval)
|
||||
{
|
||||
u8 res;
|
||||
u8 fover=0; //括号深度
|
||||
u8 *strtemp;
|
||||
u8 offset=0;
|
||||
u8 parmnum=0;
|
||||
u8 temp=1;
|
||||
u8 fpname[6];//void+X+'/0'
|
||||
u8 fplcnt=0; //第一个参数的长度计数器
|
||||
u8 pcnt=0; //参数计数器
|
||||
u8 nchar;
|
||||
//判断函数是否有返回值
|
||||
strtemp=str;
|
||||
while(*strtemp!='\0')//没有结束
|
||||
{
|
||||
if(*strtemp!=' '&&(pcnt&0X7F)<5)//最多记录5个字符
|
||||
{
|
||||
if(pcnt==0)pcnt|=0X80;//置位最高位,标记开始接收返回值类型
|
||||
if(((pcnt&0x7f)==4)&&(*strtemp!='*'))break;//最后一个字符,必须是*
|
||||
fpname[pcnt&0x7f]=*strtemp;//记录函数的返回值类型
|
||||
pcnt++;
|
||||
}else if(pcnt==0X85)break;
|
||||
strtemp++;
|
||||
}
|
||||
if(pcnt)//接收完了
|
||||
{
|
||||
fpname[pcnt&0x7f]='\0';//加入结束符
|
||||
if(usmart_strcmp(fpname,"void")==0)*rval=0;//不需要返回值
|
||||
else *rval=1; //需要返回值
|
||||
pcnt=0;
|
||||
}
|
||||
res=0;
|
||||
strtemp=str;
|
||||
while(*strtemp!='('&&*strtemp!='\0') //此代码找到函数名的真正起始位置
|
||||
{
|
||||
strtemp++;
|
||||
res++;
|
||||
if(*strtemp==' '||*strtemp=='*')
|
||||
{
|
||||
nchar=usmart_search_nextc(strtemp); //获取下一个字符
|
||||
if(nchar!='('&&nchar!='*')offset=res; //跳过空格和*号
|
||||
}
|
||||
}
|
||||
strtemp=str;
|
||||
if(offset)strtemp+=offset+1;//跳到函数名开始的地方
|
||||
res=0;
|
||||
nchar=0;//是否正在字符串里面的标志,0,不在字符串;1,在字符串;
|
||||
while(1)
|
||||
{
|
||||
if(*strtemp==0)
|
||||
{
|
||||
res=USMART_FUNCERR;//函数错误
|
||||
break;
|
||||
}else if(*strtemp=='('&&nchar==0)fover++;//括号深度增加一级
|
||||
else if(*strtemp==')'&&nchar==0)
|
||||
{
|
||||
if(fover)fover--;
|
||||
else res=USMART_FUNCERR;//错误结束,没收到'('
|
||||
if(fover==0)break;//到末尾了,退出
|
||||
}else if(*strtemp=='"')nchar=!nchar;
|
||||
|
||||
if(fover==0)//函数名还没接收完
|
||||
{
|
||||
if(*strtemp!=' ')//空格不属于函数名
|
||||
{
|
||||
*fname=*strtemp;//得到函数名
|
||||
fname++;
|
||||
}
|
||||
}else //已经接受完了函数名了.
|
||||
{
|
||||
if(*strtemp==',')
|
||||
{
|
||||
temp=1; //使能增加一个参数
|
||||
pcnt++;
|
||||
}else if(*strtemp!=' '&&*strtemp!='(')
|
||||
{
|
||||
if(pcnt==0&&fplcnt<5) //当第一个参数来时,为了避免统计void类型的参数,必须做判断.
|
||||
{
|
||||
fpname[fplcnt]=*strtemp;//记录参数特征.
|
||||
fplcnt++;
|
||||
}
|
||||
temp++; //得到有效参数(非空格)
|
||||
}
|
||||
if(fover==1&&temp==2)
|
||||
{
|
||||
temp++; //防止重复增加
|
||||
parmnum++; //参数增加一个
|
||||
}
|
||||
}
|
||||
strtemp++;
|
||||
}
|
||||
if(parmnum==1)//只有1个参数.
|
||||
{
|
||||
fpname[fplcnt]='\0';//加入结束符
|
||||
if(usmart_strcmp(fpname,"void")==0)parmnum=0;//参数为void,表示没有参数.
|
||||
}
|
||||
*pnum=parmnum; //记录参数个数
|
||||
*fname='\0'; //加入结束符
|
||||
return res; //返回执行结果
|
||||
}
|
||||
|
||||
|
||||
//从str中得到一个函数的参数
|
||||
//*str:源字符串指针
|
||||
//*fparm:参数字符串指针
|
||||
//*ptype:参数类型 0,数字;1,字符串;0XFF,参数错误
|
||||
//返回值:0,已经无参数了;其他,下一个参数的偏移量.
|
||||
u8 usmart_get_aparm(u8 *str,u8 *fparm,u8 *ptype)
|
||||
{
|
||||
u8 i=0;
|
||||
u8 enout=0;
|
||||
u8 type=0;//默认是数字
|
||||
u8 string=0; //标记str是否正在读
|
||||
while(1)
|
||||
{
|
||||
if(*str==','&& string==0)enout=1; //暂缓立即退出,目的是寻找下一个参数的起始地址
|
||||
if((*str==')'||*str=='\0')&&string==0)break;//立即退出标识符
|
||||
if(type==0)//默认是数字的
|
||||
{
|
||||
if((*str>='0' && *str<='9')||(*str>='a' && *str<='f')||(*str>='A' && *str<='F')||*str=='X'||*str=='x')//数字串检测
|
||||
{
|
||||
if(enout)break; //找到了下一个参数,直接退出.
|
||||
if(*str>='a')*fparm=*str-0X20; //小写转换为大写
|
||||
else *fparm=*str; //小写或者数字保持不变
|
||||
fparm++;
|
||||
}else if(*str=='"')//找到字符串的开始标志
|
||||
{
|
||||
if(enout)break;//找到,后才找到",认为结束了.
|
||||
type=1;
|
||||
string=1;//登记STRING 正在读了
|
||||
}else if(*str!=' '&&*str!=',')//发现非法字符,参数错误
|
||||
{
|
||||
type=0XFF;
|
||||
break;
|
||||
}
|
||||
}else//string类
|
||||
{
|
||||
if(*str=='"')string=0;
|
||||
if(enout)break; //找到了下一个参数,直接退出.
|
||||
if(string) //字符串正在读
|
||||
{
|
||||
if(*str=='\\') //遇到转义符(不复制转义符)
|
||||
{
|
||||
str++; //偏移到转义符后面的字符,不管什么字符,直接COPY
|
||||
i++;
|
||||
}
|
||||
*fparm=*str; //小写或者数字保持不变
|
||||
fparm++;
|
||||
}
|
||||
}
|
||||
i++;//偏移量增加
|
||||
str++;
|
||||
}
|
||||
*fparm='\0'; //加入结束符
|
||||
*ptype=type; //返回参数类型
|
||||
return i; //返回参数长度
|
||||
}
|
||||
//得到指定参数的起始地址
|
||||
//num:第num个参数,范围0~9.
|
||||
//返回值:该参数的起始地址
|
||||
u8 usmart_get_parmpos(u8 num)
|
||||
{
|
||||
u8 temp=0;
|
||||
u8 i;
|
||||
for(i=0;i<num;i++)temp+=usmart_dev.plentbl[i];
|
||||
return temp;
|
||||
}
|
||||
//从str中得到函数参数
|
||||
//str:源字符串;
|
||||
//parn:参数的多少.0表示无参数 void类型
|
||||
//返回值:0,成功;其他,错误代码.
|
||||
u8 usmart_get_fparam(u8*str,u8 *parn)
|
||||
{
|
||||
u8 i,type;
|
||||
u32 res;
|
||||
u8 n=0;
|
||||
u8 len;
|
||||
u8 tstr[PARM_LEN+1];//字节长度的缓存,最多可以存放PARM_LEN个字符的字符串
|
||||
for(i=0;i<MAX_PARM;i++)usmart_dev.plentbl[i]=0;//清空参数长度表
|
||||
while(*str!='(')//偏移到参数开始的地方
|
||||
{
|
||||
str++;
|
||||
if(*str=='\0')return USMART_FUNCERR;//遇到结束符了
|
||||
}
|
||||
str++;//偏移到"("之后的第一个字节
|
||||
while(1)
|
||||
{
|
||||
i=usmart_get_aparm(str,tstr,&type); //得到第一个参数
|
||||
str+=i; //偏移
|
||||
switch(type)
|
||||
{
|
||||
case 0: //数字
|
||||
if(tstr[0]!='\0') //接收到的参数有效
|
||||
{
|
||||
i=usmart_str2num(tstr,&res); //记录该参数
|
||||
if(i)return USMART_PARMERR; //参数错误.
|
||||
*(u32*)(usmart_dev.parm+usmart_get_parmpos(n))=res;//记录转换成功的结果.
|
||||
usmart_dev.parmtype&=~(1<<n); //标记数字
|
||||
usmart_dev.plentbl[n]=4; //该参数的长度为4
|
||||
n++; //参数增加
|
||||
if(n>MAX_PARM)return USMART_PARMOVER;//参数太多
|
||||
}
|
||||
break;
|
||||
case 1://字符串
|
||||
len=usmart_strlen(tstr)+1; //包含了结束符'\0'
|
||||
usmart_strcopy(tstr,&usmart_dev.parm[usmart_get_parmpos(n)]);//拷贝tstr数据到usmart_dev.parm[n]
|
||||
usmart_dev.parmtype|=1<<n; //标记字符串
|
||||
usmart_dev.plentbl[n]=len; //该参数的长度为len
|
||||
n++;
|
||||
if(n>MAX_PARM)return USMART_PARMOVER;//参数太多
|
||||
break;
|
||||
case 0XFF://错误
|
||||
return USMART_PARMERR;//参数错误
|
||||
}
|
||||
if(*str==')'||*str=='\0')break;//查到结束标志了.
|
||||
}
|
||||
*parn=n; //记录参数的个数
|
||||
return USMART_OK;//正确得到了参数
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
83
mBMS_APP_V3117/USMART/usmart_str.h
Normal file
83
mBMS_APP_V3117/USMART/usmart_str.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef __USMART_STR_H
|
||||
#define __USMART_STR_H
|
||||
#include "stm32f4xx.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
|
||||
//ALIENTEK STM32开发板
|
||||
//正点原子@ALIENTEK
|
||||
//技术论坛:www.openedv.com
|
||||
//版本:V3.1
|
||||
//版权所有,盗版必究。
|
||||
//Copyright(C) 正点原子 2011-2021
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//升级说明
|
||||
//V1.4
|
||||
//增加了对参数为string类型的函数的支持.适用范围大大提高.
|
||||
//优化了内存占用,静态内存占用为79个字节@10个参数.动态适应数字及字符串长度
|
||||
//V2.0
|
||||
//1,修改了list指令,打印函数的完整表达式.
|
||||
//2,增加了id指令,打印每个函数的入口地址.
|
||||
//3,修改了参数匹配,支持函数参数的调用(输入入口地址).
|
||||
//4,增加了函数名长度宏定义.
|
||||
//V2.1 20110707
|
||||
//1,增加dec,hex两个指令,用于设置参数显示进制,及执行进制转换.
|
||||
//注:当dec,hex不带参数的时候,即设定显示参数进制.当后跟参数的时候,即执行进制转换.
|
||||
//如:"dec 0XFF" 则会将0XFF转为255,由串口返回.
|
||||
//如:"hex 100" 则会将100转为0X64,由串口返回
|
||||
//2,新增usmart_get_cmdname函数,用于获取指令名字.
|
||||
//V2.2 20110726
|
||||
//1,修正了void类型参数的参数统计错误.
|
||||
//2,修改数据显示格式默认为16进制.
|
||||
//V2.3 20110815
|
||||
//1,去掉了函数名后必须跟"("的限制.
|
||||
//2,修正了字符串参数中不能有"("的bug.
|
||||
//3,修改了函数默认显示参数格式的修改方式.
|
||||
//V2.4 20110905
|
||||
//1,修改了usmart_get_cmdname函数,增加最大参数长度限制.避免了输入错误参数时的死机现象.
|
||||
//2,增加USMART_ENTIM2_SCAN宏定义,用于配置是否使用TIM2定时执行scan函数.
|
||||
//V2.5 20110930
|
||||
//1,修改usmart_init函数为void usmart_init(u8 sysclk),可以根据系统频率自动设定扫描时间.(固定100ms)
|
||||
//2,去掉了usmart_init函数中的uart_init函数,串口初始化必须在外部初始化,方便用户自行管理.
|
||||
//V2.6 20111009
|
||||
//1,增加了read_addr和write_addr两个函数.可以利用这两个函数读写内部任意地址(必须是有效地址).更加方便调试.
|
||||
//2,read_addr和write_addr两个函数可以通过设置USMART_USE_WRFUNS为来使能和关闭.
|
||||
//3,修改了usmart_strcmp,使其规范化.
|
||||
//V2.7 20111024
|
||||
//1,修正了返回值16进制显示时不换行的bug.
|
||||
//2,增加了函数是否有返回值的判断,如果没有返回值,则不会显示.有返回值时才显示其返回值.
|
||||
//V2.8 20111116
|
||||
//1,修正了list等不带参数的指令发送后可能导致死机的bug.
|
||||
//V2.9 20120917
|
||||
//1,修改了形如:void*xxx(void)类型函数不能识别的bug。
|
||||
//V3.0 20130425
|
||||
//1,新增了字符串参数对转义符的支持。
|
||||
//V3.1 20131120
|
||||
//1,增加runtime系统指令,可以用于统计函数执行时间.
|
||||
//用法:
|
||||
//发送:runtime 1 ,则开启函数执行时间统计功能
|
||||
//发送:runtime 0 ,则关闭函数执行时间统计功能
|
||||
///runtime统计功能,必须设置:USMART_ENTIMX_SCAN 为1,才可以使用!!
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
u8 usmart_get_parmpos(u8 num); //得到某个参数在参数列里面的起始位置
|
||||
u8 usmart_strcmp(u8*str1,u8 *str2); //对比两个字符串是否相等
|
||||
u32 usmart_pow(u8 m,u8 n); //M^N次方
|
||||
u8 usmart_str2num(u8*str,u32 *res); //字符串转为数字
|
||||
u8 usmart_get_cmdname(u8*str,u8*cmdname,u8 *nlen,u8 maxlen);//从str中得到指令名,并返回指令长度
|
||||
u8 usmart_get_fname(u8*str,u8*fname,u8 *pnum,u8 *rval); //从str中得到函数名
|
||||
u8 usmart_get_aparm(u8 *str,u8 *fparm,u8 *ptype); //从str中得到一个函数参数
|
||||
u8 usmart_get_fparam(u8*str,u8 *parn); //得到str中所有的函数参数.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user