/********主程序(程序示例1)*******/
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "usmart.h"
void led_set(u8 sta)
{
LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
ledset(sta);
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
usmart_dev.init(84); //初始化USMART
LED_Init(); //初始化LED
LCD_Init(); //初始化LCD
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
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,"2014/5/5");
while(1)
{
LED0=!LED0;
delay_ms(500);
}
}
/******usmart_dev结构体变量定义(程序示例2)*******/
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),//函数数量
0, //参数数量
0, //函数ID
1, //参数显示类型,0,10进制;1,16进制
0, //参数类型.bitx:,0,数字;1,字符串
0, //每个参数的长度暂存表,需要MAX_PARM个0初始化
0, //函数的参数,需要PARM_LEN个0初始化
};
/********结构体成员函数usmart_dev.init()的实现(程序示例3)*********/
//初始化串口控制器
//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; //十六进制显示参数
}
/***********结构体的定义(程序示例4)********/
//函数名列表
struct _m_usmart_nametab
{
void* func; //函数指针
const u8* name; //函数名(查找串)
};
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
};
今天刚看完正点原子开发的基于stm32的USMART源码,个人觉得比较有意思。首先介绍下我们的主角吧:USMART,USMART是基于USART(Universal Synchronous/Asynchronous Receiver/Transmitter)的一个辅助程序调试的一个程序。我用的板子是正点原子stm32F407的一款板子,程序是基于该板子和固件库的。为啥他们要管这个程序叫"USMART"呢?本人以为可能有两方面的原因吧,一方面该程序是基于USART的,另一方面是将USMART拆分成 U+SMART(你很机智)。当然,我没有并没有去问他们的设计人员,只是我的个人臆想。
先说一下这个程序的移植吧,这个程序包括五个主要文件(usmart.c、usmart.h、usmart_str.c、usmart_str.h和usmart_config.c),关于这个工程的其他文件在此就不赘述了。
主程序程序示例1(main.c文件)里边主要说一下void test_fun(void(*ledset)(u8),u8 sta)这个函数吧,这个函数的特别之处在于它的第一个参数是一个函数指针。这就是USMART得以实现的关键。第二个看一下usmart_dev.init(84)这个函数,这个函数的特别之处在于这是一个结构体成员函数。我们找到usmart_dev这个成员变量定义程序--程序示例2(usmart_config.c文件),等号后边是对该结构体变量的赋值。举个例子,usmart_init是函数名赋值,看定义我们就能找到该函数的实现,看程序示例3(usmart.c文件)。刚才只是说了结构体变量——usmart_dev——的定义,然后我们接着顺藤摸瓜看下关于该结构体的定义(程序示例4)。这个程序重点看下函数名列表这个结构体,这个结构体变量会与usmart_config.c中的struct _m_usmart_nametab usmart_nametab[]={}结构体数组进行比。对至此我们大概就了解了将串口发送的数据与相应的函数进行匹配。
这个过程还需要定时器的配合,定时器的作用是在定时中断里实现对USMART的扫描来获取串口数据,从而调用相关函数。