本帖最后由 煮饺子水洗脚 于 2018-7-22 16:09 编辑
USMART 是由 ALIENTEK 开发的一个灵巧的串口调试互交组件,通过它你可以通过串口助手调用程序里面的任何函数,并执行。因此,你可以随意更改函数的输入参数(支持数字 ( 10/16进制, 支持负数)、字符串、函数入口地址等作为参数),单个函数最多支持 10 个输入参数,并支持函数返回值显示。
USMART 的功能类似 linux 的shell( RTT的finsh 也属于此类)。它最主要的功能就是通过串口调用单片机里面的函数,并执行,可以帮助我们调试代码。对其进行简易改动,也可以设计成单片机系统的指令系统。
USMART主要功能有:
l 可以调用绝大部分用户直接编写的函数。
l 支持参数类型多(数字(包含10/16进制)、字符串、函数指针等)。
l 支持函数返回值显示。
l 支持参数及返回值格式设置。
l 支持函数执行时间计算。
USMART 的特点如下:
1, 可以调用绝大部分用户直接编写的函数。对于不能直接调用的,你只需要重写一个函数,把影响调用的参数去掉即可,这个重写后的函数,即可以被USMART调用了。
2, 资源占用极少(最少情况: FLASH:4K; SRAM:72B)。
3, 支持参数类型多(数字(包含 10或16 进制,支持负数)、字符串指针(如果该参数用作参数返回的话可能会有问题!)、函数指针等)。
4, 支持函数返回值显示。
5, 支持参数及返回值格式设置。
6, 支持函数执行时间计算( V3.1 版本新特性)。
USMART组件主要包括五部分:一是输入和输出接口,主要是串口进行交互和信息转存;二是信息的解析,在转存信息提炼出函数和参数,并按格式贮存;三是函数执行,即执行输入的函数;四是控制USMART运行的机制;五是单片机内的函数列表信息,作为比对使用。
USMART运行的机制实现1.何时获得信息;2.获得必要信息;3,何时按信息执行,如何转到信息执行的函数中去。
何时获取信息:使用定时扫描的方式,使用一个定时器,在定时中断时扫描缓存空间;
获得必要信息:在串口接收中,将上位机输入的信息存到缓存空间,此时得到原始信息;在定时扫描时,将缓存空间中原始信息解析成需要的具体信息;
何时按信息执行:在解析完成后,将具体信息与函数列表信息进行比对,得到需要执行的函数及参数,采用函数指针调用的方式调用相应的执行函数。
根据功能要求,要实现USMART控制管理,需要设计一个结构来控制usmart的执行。其变量包含信息应包括:
(1) 组件执行的必要函数,如组件初始化、信息解析、信息比对、函数执行等;
(2) 调试函数的名称、参数数量、参数类型;
(3) 其他辅助变量;
(4) 附加功能,如运行时间统计等。
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
};复制代码
单片机内的作为比对函数列表信息的贮存,设计一个列表。每项包括两个要素,一是函数的指针变量,指向函数的执行;一是函数名,用来与信息进行比对。
struct_m_usmart_nametab
{
void* func; //函数指针
const u8* name; //函数名(查找串)
};复制代码
在结构数组里将需要调试的函数的两类信息。
struct_m_usmart_nametab usmart_nametab[];复制代码
数组中初始化如:
struct_m_usmart_nametab usmart_nametab[]=
{
…………….
(void*)LCD_Clear,"voidLCD_Clear(u16 Color)",
…………….
};复制代码
USMART的实现流程简单概括就是:
第一步,添加需要调用的函数(在 usmart_config.c里面的usmart_nametab数组里面添加);
QQ截图20180722154604.jpg (172.54 KB, 下载次数: 20)
2018-7-22 15:46 上传
第二步,初始化串口;
QQ截图20180722154706.jpg (5.18 KB, 下载次数: 22)
2018-7-22 15:47 上传
第三步,初始化 USMART(通过usmart_init函数实现);
QQ截图20180722154726.jpg (5.7 KB, 下载次数: 15)
2018-7-22 15:47 上传
第四步,轮询 usmart_scan 函数,处理串口数据。
QQ截图20180722154849.jpg (72.04 KB, 下载次数: 21)
2018-7-22 15:48 上传
USMART组件的移植:
redeme.txt是一个说明文件,不参与编译。
其他五个文件:
usmart.c负责与外部交互等;
usmat_str.c主要负责命令和参数解析;
usmart_config.c主要由用户添加需要由usmart管理的函数。
usmart.h 和 usmart_str.h 是两个头文件,usmart.h里面含有几个用户配置宏定义,可以用来配置usmart的功能及总参数长度(直接和SRAM占用挂钩)、是否使能定时器扫描、是否使用读写函数等;
USMART的移植,只需要实现5个函数。其中4个函数都在usmart.c里面,另外一个是串口接收函数,必须由用户自己实现,用于接收串口发送过来的数据。
第一个函数:串口接收函数
通过SYSTERM文件夹默认的串口接受来实现的。SYSTERM文件夹里面的串口接收函数最大可以一次接收200字节,用于从串口接收函数名和参数等。(如果在其他平台移植请参考SYSTERM文件夹串口接收的实现方式)
第二个是 void usmart_init(void)函数
初始化串口控制器,该函数有一个参数sysclk,就是用于定时器初始化。另外USMART_ENTIMX_SCAN是在usmart.h里面定义的一个是否使能定时器中断扫描的宏定义。如果为1,就初始化定时器中断,并在中断里面调用usmart_scan函数。如果为0,那么需要用户需要自行间隔一定时间(100ms左右为宜)调用一次usmart_scan 函数,以实现串口数据处理。注意:如果要使用函数执行时间统计功能(runtime 1), 则必须设置USMART_ENTIMX_SCAN为1。 另外,为了让统计时间精确到0.1ms,定时器的计数时钟频率必须设置为10Khz,否则时间就不是 0.1ms了
第三和第四个函数仅用于服务USMART的函数执行时间统计功能(串口指令:runtime 1),分别是:usmart_reset_runtime和usmart_get_runtime
usmart_reset_runtime: 复位runtime(需要根据所移植的MCU的定时器参数进行修改), 在每次USMART调用函数之前执行,清除计数器,然后在函数执行完之后,调用usmart_get_runtime获取整个函数的运行时间。
usmart_get_runtime: 获得runtime时间, 单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms (需要根据所移植的MCU的定时器参数进行修改). 由于usmart调用的函数,都是在中断里面执行的,所以我们不太方便再用定时器的中断功能来实现定时器溢出统计,因此,USMART的函数执行时间统计功能,最多可以统计定时器溢出1次的时间,对STM32F4的定时器4,该定时器是16位的,最大计数是65535,而由于我们定时器设置的是0.1ms一个计时周期(10Khz),所以最长计时时间是:65535*2*0.1ms=13.1秒。也就是说,如果函数执行时间超过13.1秒,那么计时将不准确。
第五个函数:usmart_scan 函数
该函数用于执行 usmart 扫描,该函数需要得到两个参量,第一个是从串口接收到的数组( USART_RX_BUF),第二个是串口接收状态(USART_RX_STA)。接收状态包括接收到的数组大小,以及接收是否完成。通过调用该函数,实现usmart的各个控制.该函数需要每隔一定时间被调用一次以及时执行从串口发过来的各个函数.
系统命令
QQ截图20180722154942.jpg (8.25 KB, 下载次数: 18)
2018-7-22 15:49 上传
发送"?"或者“”help“” 获取帮助信息
QQ截图20180722155105.jpg (161.37 KB, 下载次数: 20)
2018-7-22 15:51 上传
函数id
QQ截图20180722155105.jpg (161.37 KB, 下载次数: 20)
2018-7-22 15:53 上传
下面测试下 通过usmart 控制lcd显示的功能,当然这些也是可以自定义函数接口的
QQ截图20180722155432.jpg (154.48 KB, 下载次数: 23)
2018-7-22 15:54 上传
用 函数 Draw_Circle(u16 x0,u16 y0,u8 r) 花了一系列同心圆
QQ截图20180722155655.jpg (100.99 KB, 下载次数: 20)
2018-7-22 15:57 上传
IMG_20180722_155806.jpg (4.88 MB, 下载次数: 23)
2018-7-22 15:59 上传
显示字符串
QQ截图20180722160505.jpg (63.24 KB, 下载次数: 17)
2018-7-22 16:05 上传
IMG_20180722_160553.jpg (1.27 MB, 下载次数: 20)
2018-7-22 16:06 上传
设置lcd颜色
QQ截图20180722160821.jpg (45.73 KB, 下载次数: 17)
2018-7-22 16:08 上传
IMG_20180722_160909.jpg (2.39 MB, 下载次数: 21)
2018-7-22 16:09 上传