你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 1866|回复: 0

【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第十九章 USMART调试组件实验

[复制链接]

50

主题

7

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2013-1-27 18:44:32 | 显示全部楼层 |阅读模式
第十九章 USMART调试组件实验

本章,我们将向大家介绍一个十分重要的辅助调试工具:USMART调试组件。该组件由ALIENTEK 开发提供,功能类似linuxshellRTTfinsh也属于此类)。USMART最主要的功能就是通过串口调用单片机里面的函数,并执行,对我们调试代码是很有帮助的。本章分为如下几个部分:
19.1 USMART调试组件简介
19.2 硬件设计
19.3 软件设计
19.4 下载验证
19.1 USMART调试组件简介

USMART是由ALIENTEK开发的一个灵巧的串口调试互交组件,通过它你可以通过串口助手调用程序里面的任何函数,并执行。因此,你可以随意更改函数的输入参数(支持数字(10/16进制)、字符串、函数入口地址等作为参数),单个函数最多支持10个输入参数,并支持函数返回值显示,目前最新版本为V2.9
USMART的特点如下:
1,  可以调用绝大部分用户直接编写的函数。
2,  资源占用极少(最少情况:FLASH:4KSRAM:72B)。
3,  支持参数类型多(数字(包含10/16进制)、字符串、函数指针等)。
4,  支持函数返回值显示。
5,  支持参数及返回值格式设置。
6,  使用方便。
有了USMART,你可以轻易的修改函数参数、查看函数运行结果,从而快速解决问题。比如你调试一个摄像头模块,需要修改其中的几个参数来得到最佳的效果,普通的做法:写函数->修改参数->下载->看结果->不满意->修改参数->下载->看结果->不满意….不停的循环,直到满意为止。这样做很麻烦不说,单片机也是有寿命的啊,老这样不停的刷,很折寿的。而利用USMART,则只需要在串口调试助手里面输入函数及参数,然后直接串口发送给单片机,就执行了一次参数调整,不满意的话,你在串口调试助手修改参数在发送就可以了,直到你满意为止。这样,修改参数十分方便,不需要编译、不需要下载、不会让单片机折寿。
USMART支持的参数类型基本满足任何调试了,支持的类型有:10或者16进制数字、字符串指针(如果该参数是用作参数返回的话,可能会有问题!)、函数指针等。因此绝大部分函数,可以直接被USMART调用,对于不能直接调用的,你只需要重写一个函数,把影响调用的参数去掉即可,这个重写后的函数,即可以被USMART调用了。
USMART的实现流程简单概括就是:第一步,添加需要调用的函数(在usmart_config.c里面的usmart_nametab数组里面添加);第二步,初始化串口;第三步,初始化USMART(通过usmart_init函数实现);第四步,轮询usmart_scan函数,处理串口数据。
 经过以上简单介绍,我们对USMART有了个大概了解,接下来我们来简单介绍下USMART组件的移植。
USMART组件总共包含6文件如图19.1.1所示:
 



 
 
19.1.1 USMART组件代码

       其中redeme.txt是一个说明文件,不参与编译。其他五个文件,usmart.c负责与外部互交等。usmat_str.c主要负责命令和参数解析。usmart_config.c主要由用户添加需要由usmart管理的函数。
usmart.husmart_str.h是两个头文件,其中usmart.h里面含有几个用户配置宏定义,可以用来配置usmart的功能及总参数长度(直接和SRAM占用挂钩)、是否使能定时器扫描、是否使用读写函数等。
       USMART的移植,只需要实现3个函数。其中两个函数都在usmart.c里面,另外一个是串口接收函数,必须由用户自己实现,用于接收串口发送过来的数据。
第一个函数,串口接收函数。该函数,我们是通过SYSTEM文件夹默认的串口接收来实现的,该函数在5.3.1节有介绍过,我们这里就不列出来了。SYSTEM文件夹里面的串口接收函数,最大可以一次接收200字节,用于从串口接收函数名和参数等。大家如果在其他平台移植,请参考SYSTEM文件夹串口接收的实现方式进行移植。
第二个是void usmart_init(void)函数,该函数的实现代码如下:
//初始化串口控制器
//sysclk:系统时钟(Mhz
void usmart_init(u8 sysclk)
{
#if USMART_ENTIMX_SCAN==1
       Timer2_Init(1000,(u32)sysclk*100-1);//分频,时钟为10K ,100ms中断一次
#endif
       usmart_dev.sptype=1;    //十六进制显示参数
}
该函数有一个参数sysclk,就是用于定时器初始化。另外USMART_ENTIMX_SCAN是在usmart.h里面定义的一个是否使能定时器中断扫描的宏定义。如果为1,就初始化定时器中断,并在中断里面调用usmart_scan函数。如果为0,那么需要用户需要自行间隔一定时间(100ms左右为宜)调用一次usmart_scan函数,以实现串口数据处理。
最后一个是usmart_scan函数,该函数用于执行usmart扫描,该函数需要得到两个参量,第一个是从串口接收到的数组(USART_RX_BUF),第二个是串口接收状态(USART_RX_STA)。接收状态包括接收到的数组大小,以及接收是否完成。该函数代码如下:
//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
              { 
                     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;//状态寄存器清空         
       }
}
该函数的执行过程:先判断串口接收是否完成(USART_RX_STA的最高位是否为1),如果完成,则取得串口接收到的数据长度(USART_RX_STA的低14位),并在末尾增加结束符,再执行解析,解析完之后清空接收标记(USART_RX_STA置零)。如果没执行完成,则直接跳过,不进行任何处理。
       完成这三个函数的移植,你就可以使用USMART了。不过,需要注意的是,usmart同外部的互交,一般是通过usmart_dev结构体实现,所以usmart_initusmart_scan的调用分别是通过:usmart_dev.initusmart_dev.scan实现的。
       下面,我们将在第十八章实验的基础上,移植USMART,并通过USMART调用一些TFTLCD的内部函数,让大家初步了解USMART的使用。
      
19.2 硬件设计

本实验用到的硬件资源有:
1)  指示灯DS0DS1
2)  串口
3)  TFTLCD模块
这三个硬件在前面章节均有介绍,本章不再介绍。
19.3 软件设计

打开上一章的工程,复制USMART文件夹(该文件夹可以在光盘的本章实验例程里面找到)到本工程文件夹下面,如图19.3.1所示:
 

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

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

 
 
19.3.2 添加USMART组件代码

由于USMART默认提供了STM32TIM2中断初始化设置代码,我们只需要在usmart.h里面设置USMART_ENTIMX_SCAN1,即可完成TIM2的设置,通过TIM2的中断服务函数,调用usmart_dev.scan()(就是usmart_scan函数),实现usmart的扫描。此部分代码我们就不列出来了,请参考usmart.c
      此时,我们就可以使用USMART了,不过在主程序里面还得执行usmart的初始化,另外还需要针对你自己想要被USMART调用的函数在usmart_config.c里面进行添加。下面先介绍如何添加自己想要被USMART调用的函数,打开usmart_config.c,如图19.3.3所示:
 

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

这里的添加函数很简单,只要把函数所在头文件添加进来,并把函数名按上图所示的方式增加即可,默认我们添加了两个函数:delay_msdelay_us。另外,read_addrwrite_addr属于usmart自带的函数,用于读写指定地址的数据,通过配置USMART_USE_WRFUNS,可以使能或者禁止这两个函数。
这里我们根据自己的需要按上图的格式添加其他函数,添加完之后如图19.3.4所示:
 

 
 
19.3.4 添加函数后

上图中,我们添加了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里面也是可以被调用的。
在添加完函数之后,我们修改main函数,如下:
int main(void)
{                     
      Stm32_Clock_Init(9);    //系统时钟设置
       delay_init(72);                     //延时初始化
       uart_init(72,9600);      //串口1初始化为9600
       LED_Init();                         //初始化与LED连接的硬件接口
      LCD_Init();                         //初始化LCD
       usmart_dev.init(72);     //初始化USMART                          
       POINT_COLOR=RED;
       LCD_ShowString(30,50,200,16,16,"WarShip STM32 ^_^");    
       LCD_ShowString(30,70,200,16,16,"USMART TEST");    
       LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
       LCD_ShowString(30,110,200,16,16,"2012/9/7");         
      while(1)
       {                   
              LED0=!LED0;                                  
              delay_ms(500);     
       }                                                                              
}    
此代码显示简单的信息后,就是在死循环等待串口数据。
至此,整个usmart的移植就完成了。编译成功后,就可以下载程序到开发板,开始USMART的体验。
19.4 下载验证

将程序下载到战舰STM32后,可以看到DS0不停的闪烁,提示程序已经在运行了。同时,屏幕上显示了一些字符(就是主函数里面要显示的字符)。
我们打开串口调试助手,选择正确的串口号,并选择发送新行(即发送回车键)选项。如下图所示(点击扩展->隐藏,显示扩展界面):
 


 
 
19.4.1 驱动串口调试助手

       上图中listid、?、helphexdec都属于usmart自带的系统命令。下面我们简单介绍下这几个命令:
list,该命令用于打印所有usmart可调用函数。发送该命令后,串口将受到所有能被usmart调用得到函数如图19.4.2所示:
 

 
 
19.4.2 list指令执行结果

       id,该指令用于获取各个函数的入口地址。比如前面写的test_fun函数,就有一个函数参数,我们需要先通过id指令,获取ledset函数的id(即入口地址),然后将这个id作为函数参数,传递给test_fun
       ?和help,这两个指令的功能是一样的。发送该指令后,串口将打印usmart使用的帮助信息。
hexdec,这两个指令可以带参数,也可以不带参数。当不带参数的时候,hexdec分别用于设置串口显示数据格式为16进制/10进制。当带参数的时候,hexdec就执行进制转换,比如输入:hex 1234,串口将打印:HEX:0X4D2,也就是将1234转换为16进制打印出来。又比如输入:dec 0X1234,串口将打印:DEC:4660,就是将0X1234转换为10进制打印出来。 
大家可以亲自体验下这几个系统指令,不过要注意,所有的指令都是大小写敏感的,不要写错哦。
       接下来,我们将介绍如何调用list所打印的这些函数,先来看一个简单的delay_ms的调用,我们分别输入delay_ms(1000)delay_ms(0x3E8),如图19.4.3所示:
 


 
 
19.4.3 串口delay_ms函数

       从上图可以看出,delay_ms(1000)delay_ms(0x3E8)的调用结果是一样的,都是延时1000ms,因为usmart默认设置的是hex显示,所以看到串口打印的参数都是16进制格式的,大家可以通过发送dec指令切换为十进制显示。另外,由于usmart对调用函数的参数大小写不敏感,所以参数写成:0X3E8或者0x3e8都是正确的。
       我们再看另外一个函数,LCD_ShowString函数,该函数用于显示字符串,我们通过串口输入:LCD_ShowString(20,200,200,100,16,"This is a test for usmart!!"),如图19.4.4所示:
 


 
 
19.4.4 串口调用LCD_ShowString函数

该函数用于在指定区域,显示指定字符串,发送给开发板后,我们可以看到LCD在我们指定的地方显示了:This is a test for usmart!! 这个字符串。
其他函数的调用,也都是一样的方法,这里我们就不多介绍了,最后说一下带有函数参数的函数的调用。我们将led_set函数作为 test_fun的参数,通过在test_fun里面调用led_set函数,实现对DS1(LED1)的控制。前面说过,我们要调用带有函数参数的函数,就必须先得到函数参数的入口地址(id),通过输入id指令,我们可以得到led_set的函数入口地址是:0X08000281,所以,我们在串口输入:test_fun(0X08000281,0),就可以控制DS1亮了。如图19.4.5所示:
 


 
 
19.4.5 串口调用test_fun函数

在开发板上,我们可以看到,收到串口发送的test_fun(0X08000281,0)后,开发板的DS1亮了,然后大家可以通过发送test_fun(0X08000281,1),来关闭DS1。说明我们成功的通过test_fun函数调用led_set,实现了对DS1的控制。也就验证了USMART对函数参数的支持。
USMART调试组件的使用,就为大家介绍到这里。USMART是一个非常不错的调试组件,希望大家能学会使用,可以达到事半功倍的效果。

《STM32开发指南》第十九章 USMART调试组件实验.rar

下载

975.78 KB, 下载次数: 19, 下载积分: ST金币 -1

实验14 USMART调试实验.rar

下载

96.28 KB, 下载次数: 28, 下载积分: ST金币 -1

回复

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版