原创 调试利器----USMART 2.0正式发布!

2011-6-15 11:11 7135 15 10 分类: MCU/ 嵌入式

USMART V2.0使用说明

USMART是由ALIENTEK开发的一个灵巧的串口调试互交组件,通过它你可以通过串口助手调用程序里面的任何函数,并执行。因此,你可以随意更改函数的输入参数(支持数字(10/16进制)、字符串、函数入口地址等作为参数),单个函数最多支持10个输入参数,并支持函数返回值显示。

USMART的特点如下:

1,  可以调用绝大部分用户直接编写的函数。

2,  资源占用极少(最少情况:FLASH:2.5KSRAM:72B)。

3,  支持参数类型多(数字(包含10/16进制)、字符串、函数指针等)。

4,  支持函数返回值显示。

5,  使用方便。

 

有了USMART,你可以轻易的修改函数参数、查看函数运行结果,从而快速解决问题。比如你调试一个摄像头模块,需要修改其中的几个参数来得到最佳的效果,普通的做法:写函数->修改参数->下载->看结果->不满意->修改参数->下载->看结果->不满意….不停的循环,直到满意为止。这样做很麻烦不说,单片机也是有寿命的啊,老这样不停的刷,很折寿的。而利用USMART,则只需要在串口调试助手里面输入函数及参数,然后直接串口发送给单片机,就执行了一次参数调整,不满意的话,你在串口调试助手修改参数在发送就可以了,直到你满意为止。这样,修改参数十分方便,不需要编译、不需要下载、不会让单片机折寿。

USMART支持的参数类型基本满足任何调试了,支持的类型有:10或者16进制数字、字符串指针(如果该参数是用作参数返回的话,可能会有问题!)、函数指针等。因此绝大部分函数,可以直接被USMART调用,对于不能直接调用的,你只需要重写一个函数,把影响调用的参数去掉即可,这个重写后的函数,即可以被USMART调用了。

 经过以上简单介绍,接下来我们来看看USMART的移植和使用。

 


一、USMART移植

USMART组件总共包含6文件如下图所示:

20110615110125001.jpg

1.1 USMART组件

         其中redeme.txt是一个说明文件,不参与编译。其他五个文件,usmart.c负责与外部互交等。usmat_str主要负责命令和参数解析。usmart_config.c主要由用户添加需要由usmart管理的函数。

usmart.husmart_str.h是两个头文件,其中usmart.h里面含有几个用户配置宏定义,可以用来配置usmart的功能及总参数长度(直接和SRAM占用挂钩)

         USMART的移植,只需要实现两个函数。两个函数都在usmart.c里面,第一个是void usmart_init(void)函数,该函数主要实现串口初始化,如果用中断执行usmart的扫描,则可以把中断的初始化代码,也放到这个函数里面。

ALIENTEK STM32开发板上该函数的实现代码如下:

//初始化串口控制器

void usmart_init(void)

{

         //必须使能串口中断接收

         uart_init(72,9600);                  /串口1初始化

         Timer2_Init(1000,7199);         //7200分频,时钟为10K ,100ms中断一次

}       

         上述代码,我们初始化串口波特率为9600,并开启了定时器2,每隔100ms执行一次usmart的扫描。

         这里uart_init设置还包括开启串口中断接收,并实现利用回车键判别接收是否完成,具体的说明,请参考《STM32不完全手册V2.02.7.3节或《例说STM325.3节。不过我们这里提供的源码usart.c文件已经被更新,为1.4版本了。主要修改了USART_RX_STA这个自定义寄存器,将其由u8变为u16,这样我们的串口一次可以接收的字节数,最大可以是214次方,主要为了增加对长函数名及函数参数的支持。

         Timer2的中断函数如下:

//定时器2中断服务程序  

void TIM2_IRQHandler(void)

{                                                                    

         if(TIM2->SR&0X0001)//溢出中断

         {

                   usmart_dev.scan();//执行usmart扫描                                                                         

         }                                      

         TIM2->SR&=~(1<<0);//清除中断标志位        

}

         这里主要就是调用了usmart_dev.scan();这个函数,用于及时处理从串口接收到的数据,即上文所说的usmart扫描。这里采用的是中断扫描方式(推荐),你也可以使用死循环里面调用的方式,只要保证usmart_dev.scan();函数每隔一定时间(建议不超过200ms)被调用一次即可。

         第二个要实现的函数就是void usmart_scan(void)。该函数用于执行usmart扫描,该函数需要得到两个参量,第一个是从串口接收到的数组(USART_RX_BUF),第二个是串口接收状态(USART_RX_STA)。接收状态包括接收到的数组大小,以及接收是否完成。

         该函数的执行过程:先判断串口接收是否完成(USART_RX_STA的最高位是否为1),如果完成,则取得串口接收到的数据长度(USART_RX_STA的低14位),并在末尾增加结束符,再执行解析,解析完之后清空接收标记(USART_RX_STA置零)。如果没执行完成,则直接跳过,不进行任何处理。

ALIENTEK STM32开发板上该函数实现代码如下:

//usmart扫描函数

//通过调用该函数,实现usmart的各个控制.该函数需要每隔一定时间被调用一次

//以及时执行从串口发过来的各个函数.

//本函数可以在中断里面调用,从而实现自动管理.

//如果非ALIENTEK用户,USART_RX_STAUSART_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; //状态寄存器清空   

         }

}                

         完成这两个函数的移植,你就可以使用USMART了。


二、USMART使用

USMART的使用很简单,下面结合ALIENTEK MINISTM32 实验10 TFTLCD显示实验为例介绍一下USMART的使用(移植好的例程为: ALIENTEK MINISTM32 扩展实验9 USMART应用)。首先打开实验10的工程,然后将usart.hEN_USART1_RX设置为1,使能串口中断接收。如下图所示(注意,这里我们用的是V1.4版本的串口驱动代码,如果你的还是旧版本的,请将usmart实验源码的usart文件夹覆盖你的usart文件夹):

20110615110127002.jpg

2.1 修改EN_USART1_RX1

然后,我们复制USMART文件夹到工程文件夹下面,如下图所示:

20110615110128003.jpg

2.2 复制USMART文件夹到工程文件夹下

         接着,我们在工程里面添加USMART组件代码,并把USMART文件夹添加到头文件包含路径,在主函数里面加入includeusmart.h”如下图所示:

20110615110129004.jpg

2.3 添加USMART组件代码

由于我们采用定时器中断2用来执行USMART扫描,所以需要在timer.c里面增加如下代码:

////////////////////////////////定时器2,用于支持USMART中断调用////////////////////

//定时器2中断服务程序  

void TIM2_IRQHandler(void)

{                                                                    

         if(TIM2->SR&0X0001)//溢出中断

         {

                   usmart_dev.scan();//执行usmart扫描                                                                                                                           

         }                                      

         TIM2->SR&=~(1<<0);//清除中断标志位        

}

//使能定时器2,使能中断.

void Timer2_Init(u16 arr,u16 psc)

{

         RCC->APB1ENR|=1<<0;//TIM2时钟使能   

        TIM2->ARR=arr;  //设定计数器自动重装值 

         TIM2->PSC=psc;  //预分频器7200,得到10Khz的计数时钟

         //这两个东东要同时设置才可以使用中断

         TIM2->DIER|=1<<0;   //允许更新中断                                

         TIM2->DIER|=1<<6;   //允许触发中断

                                                                                      

         TIM2->CR1|=0x01;    //使能定时器2

       MY_NVIC_Init(3,3,TIM2_IRQChannel,2);//抢占3,子优先级3,组2(2中优先级最低的)                                                                             

}

         此时,我们就可以使用USMART了,不过在主程序里面还得执行usmart的初始化,另外还需要针对你自己想要被USMART调用的函数在usmart_config.c里面进行添加。下面先介绍如何添加自己想要被USMART调用的函数,打开usmart_config.c,如下图所示:

20110615110131005.jpg

         2.4 添加需要被USMART调用的函数

         这里的添加函数很简单,只要把函数所在头文件添加进来,并把函数名按上图所示的方式增加即可,默认我们添加了两个函数:delay_msdelay_us。这里我们根据自己的需要按上图的格式添加其他函数,添加完之后如下图所示:

20110615110133006.jpg

         2.5 添加需要被USMART调用的函数

         上图中,我们添加了lcd.h,并添加了很多LCD函数,最后我们还添加了led_settest_fun两个函数,这两个函数在test.c里面实现,代码如下:

//LED状态设置函数

void led_set(u8 sta)

{

         LED1=sta;

}

//函数参数调用测试函数

void test_fun(void(*ledset)(u8),u8 sta)

{

         ledset(sta);

}

         led_set函数,用于设置LED1的状态,而第二个函数test_fun则是测试USMART对函数参数的支持的,test_fun的第一个参数是函数,在USMART里面也是可以被调用的。

         在添加完函数之后,我们修改主函数,如下:

//Mini STM32开发板扩展实验

//USMART测试 实验

//正点原子@ALIENTEK

//技术论坛:www.openedv.com          

int main(void)

{                            

       Stm32_Clock_Init(9);//系统时钟设置

         delay_init(72);                   //延时初始化

         uart_init(72,9600); //串口1初始化 

         LED_Init();

        LCD_Init();

         usmart_dev.init();  //初始化USMART                                           

         POINT_COLOR=RED;

         LCD_ShowString(30,50,"Mini STM32 ^_^");

         LCD_ShowString(30,70,"USMART TEST");   

         LCD_ShowString(30,90,"ATOM@ALIENTEK");

         LCD_ShowString(30,110,"2011/6/18");    

       while(1)

         {                          

                   LED0=!LED0;                                        

                   delay_ms(500);       

         }                                                                                                        

}       

编译之后,我们下下载代码到ALIENTEK MiniSTM32开发板上,就可以通过串口来调用我们在图2.5中所添加的函数了。下面简单介绍一下,下载完代码,我们可以看到DS0不停闪烁,然后屏幕上显示了一些字符(就是主函数里面要显示的字符)。

我们打开串口调试助手(由于我写的助手在WIN7上有兼容问题,这里使用丁丁的助手),选择正确的串口号,并选择发送新行(即发送回车键)选项。如下图所示(点击扩展->隐藏):

20110615110135007.jpg

         2.6 启动串口助手

此时我们在右边的栏里面输入各种指令或者函数,就可以得到执行结果如下图:

20110615110137008.jpg

2.7 输入“?/help”指令

20110615110139009.jpg

2.8 输入“list”指令

通过“list”指令,我们可以获得当前USMART所管理的全部函数。

20110615110141010.jpg

2.9 执行:delay_ms(1000)函数

通过输入delay_ms(1000)函数,观察板子上的DS0,可以看到会停1秒钟之后再闪烁。该函数没有返回值,所以输出的返回值1000对我们来说没有意义,忽略之,下同。

20110615110143011.jpg

2.10 执行:delay_us(0x1B7740)函数

         这里,我们修改输入参数为16进制,调用delay_us函数延时(注意delay_us同样有延时范围哦!)0x1b7740=1800000us=1800ms=1.8s,可以看到DS0的闪烁会停的更久一些。这里输入参数0x1b7740,其大小写是自动转换的,你可以输入0X1b7740也可以输入0x1B7740都是一样的。

20110615110145012.jpg

2.11 执行:LCD_Clear(0X7d7C)函数

         可以看到整个LCD颜色变为了浅蓝色。

20110615110148013.jpg

2.12 执行:LCD_Fill(10,10,230,310,0x07E0)函数

         可以看到LCD内出现一个绿色的正方形。

20110615110149014.jpg

2.13 执行:LCD_DrawLine(10,10,230,310)函数

         可以看到绿色正方形内出现一条红色的对角线。

20110615110151015.jpg

2.14 执行:LCD_DrawRectangle(10,10,230,310)函数

         可以看到绿色正方形边框变为红色的了。

20110615110153016.jpg

2.15 执行:Draw_Circle(120,160,55)函数

         可以看到绿色正方形内出现了一个红色的圆圈。

 

 

20110615110155017.jpg

2.16 执行:LCD_ShowNum(10,10,0x45abCdEf,10,16)函数

         可以看到在LCD的绿色区域内显示了1168887279(与0X45ABCDEF相等)。

20110615110159018.jpg

2.17 执行:LCD_ShowString(10,40,"ALIENTEK STM32 Dev Kit USMART Test!")函数

         可以看到在LCD的屏幕对应位置显示了ALIENTEK STM32 Dev Kit USMART Test!字样。

20110615110201019.jpg

2.18 执行:led_set(0)函数

         可以看到DS1点亮了。

         最后一个函数,其参数为函数指针,需要我们先获得函数的地址,这里通过id指令获得,发送id指令,得到所有函数的id,如下图:

20110615110203020.jpg

2.19执行“id”指令

         由于test_fun的函数指针我们设计的时候考虑的是led_set函数,所以,我们从上面的列表中选择led_setID,为0x0800021d。再作为test_fun的函数参数输入,发送给ALIENTEK MiniSTM32开发板,得到如下结果:

 20110615110205021.jpg

2.20 执行:test_fun(0x0800021d,1)函数

         此时可以看到DS1灯灭了。说明我们确实通过test_fun调用了led_set,并设置了LED1=1;这里注意函数参数ID一定不能错,如果错了,可能导致程序崩溃!

 

至此整个USMART的使用就介绍完了。通过以上实例,我们可以看出USMART的使用时非常简单的,我相信如果你真的学会了usmart的使用,一定会给你的学习/工作带来很大的方便。

 

 


三、USMART注意事项

         1USMART的函数在函数名与’(’之间不要留空格,否则导致无法匹配。比如delay_ms(1000),不要弄成delay_ms (1000)

         2,在参数为函数指针的时候,其函数ID一定不要搞错,否则可能导致程序崩溃。

         3usmart.h里面,PARM_LEN的值最少应该为4,他是用来设定保存函数参数的数组大小的。PARM_LEN的值将直接影响到USMART组件的SRAM占用率。计算公式为:sram=PARM_LEN+72-4。当PARM_LEN设置为4的时候,组件只占用72个字节。但此时的参数长度则限制在4个字节。PARM_LEN的值,大家自己根据需要修改。

 

rar.gif丁丁串口调试助手.rar
rar.gifALIENTEK MINISTM32 扩展实验9 USMART应用.rar
pdf.gifUSMART V2.0使用说明.pdf

 

 

 

 

 

                                                                                    正点原子@ALIENTEK

2011-6-14

20110615110206022.png

PARTNER CONTENT

文章评论7条评论)

登录后参与讨论

用户1565170 2012-1-15 19:40

很好,顶!

用户212008 2011-10-11 16:35

好东西,谢谢。

liujun6037_345432000 2011-6-26 21:35

mplab,这个没用过.你试试吧.

dwwzl 2011-6-24 08:31

哦,我用的是mplab ide 8.66不知可以吗?

用户1570367 2011-6-21 12:59

顶楼主一个

liujun6037_345432000 2011-6-16 18:18

看编译器吧.如果是KEIL的编译器,应该是可以的.你可以移植一下.

用户1610024 2011-6-16 17:30

可以支持51和430吗?希望楼主回答。特别是51,每次调试都要连一大堆的线。而且仿真器真的好麻烦。
相关推荐阅读
正点原子 2013-05-17 23:47
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十一章 战舰STM32开发板综合实验(标准例程终结篇)
   第六十一章 战舰STM32开发板综合实验        前面已经给大家讲了55个实例了,本章将设计一个综合实例,作为本指南的最后一个实验 ,该实验向大家展示了STM...
正点原子 2013-05-03 23:02
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十章 UCOSII实验3-消息队列、信号量集和软件定时器
   第六十章 UCOSII实验3-消息队列、信号量集和软件定时器   上一章,我们学习了UCOSII的信号量和邮箱的使用,本章,我们将学习消息队列、信号量集和软件定时器...
正点原子 2013-05-03 20:42
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
第五十七章 ENC28J60网络实验   本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块...
正点原子 2013-05-01 23:00
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十九章 UCOSII实验2-信号量和邮箱
第五十九章 UCOSII实验2-信号量和邮箱      上一章,我们学习了如何使用UCOSII,学习了UCOSII的任务调度,但是并没有用到任务间的同步与通信,本章我们将学习两个最基本的...
正点原子 2013-04-30 10:55
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十八章 UCOSII实验1-任务调度
  第五十八章 UCOSII实验1-任务调度      前面我们所有的例程都是跑的裸机程序(裸奔),从本章开始,我们将分3个章节向大家介绍UCOSII(实时多任务操作系...
正点原子 2013-04-26 23:16
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
 第五十七章 ENC28J60网络实验  本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块和uIP 1...
EE直播间
更多
我要评论
7
15
关闭 站长推荐上一条 /1 下一条