OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4931|回复: 2

USMART测试函数的调用执行有些困惑,求高手解答

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2019-8-5
在线时间
7 小时
发表于 2020-1-4 11:23:02 | 显示全部楼层 |阅读模式
//函数名列表         
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
};


//函数控制管理器初始化
//得到各个受控函数的名字
//得到函数总数量
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初始化
};

//函数名列表初始化(用户自己添加)
//用户直接在这里输入要执行的函数名及其查找串
struct _m_usmart_nametab usmart_nametab[]=
{
#if USMART_USE_WRFUNS==1         //如果使能了读写操作
        (void*)read_addr,"u32 read_addr(u32 addr)",
        (void*)write_addr,"void write_addr(u32 addr,u32 val)",         
#endif
        (void*)delay_ms,"void delay_ms(u16 nms)",
        (void*)delay_us,"void delay_us(u32 nus)",         
        (void*)LCD_Clear,"void LCD_Clear(u16 Color)",
        (void*)LCD_Fill,"void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)",
        (void*)LCD_DrawLine,"void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)",
        (void*)LCD_DrawRectangle,"void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)",
        (void*)Draw_Circle,"void Draw_Circle(u16 x0,u16 y0,u8 r)",
        (void*)LCD_ShowNum,"void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)",
        (void*)LCD_ShowString,"void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)",
        (void*)runtimeTest,"void runtimeTest(u8 sta)",
        (void*)test_fun,"void test_fun(void(*ledset)(u8),u8 sta)",                                              
        (void*)LCD_ReadPoint,"u16 LCD_ReadPoint(u16 x,u16 y)",
                                                                                         
};       
case 1://有1个参数
                        res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
                        break;
原子哥的USMART 执行测试函数的时候(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);里面的(*(u32(*)())  怎么理解?  (*(u32(*)())usmart_dev.funs[id].func)(temp[0]);整体怎么理解?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2020-4-7
在线时间
7 小时
发表于 2020-4-17 23:20:25 | 显示全部楼层
请问大佬,你理解了吗?我也对这个不明白,谢谢指导一下。
回复 支持 反对

使用道具 举报

0

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2020-5-9
在线时间
18 小时
发表于 2020-5-14 22:48:23 | 显示全部楼层
你代码里的 (*(u32(*)())usmart_dev.funs[id].func)(temp[0]) 表达是不是有错误?
简化一下上述表达,实际上 *(u32(*)()) 部分是对  usmart_dev.funs[id].func 进行类型强制转换。

我努力检查了你贴出来的代码声明和代码实现,实在无法将它们结合到一起。所以,我还是改换一下回答方法吧:

1)首先让我们来看一个简单的函数指针的声明:
typedef
  unsigned int (*func)(unsigned int);
这样我们就声明了一个类似如下形式的函数的指针类型 func:
unsigned int read(unsigned int x)
{
    return 0;
}
如何使用呢?在具体的代码里,我们可以声明一个 func 类型的变量,并将函数 read 赋值给它,并最后调用它:
unsigned int test()
{
    unsigned int x = 0;
    func f = read;
   return f(x);
}
我们看到最后 f(x),完成了函数调用。

2)上面这样声明、定义、实现,编译器肯定是可以通过的。但如果我们不是这样亦步亦趋,而是直接使用泛指针会怎么样?比如:
unsigned int test()
{
    unsigned int x = 0;
    void* f;          // 用 void* ,就像本楼主贴那样声明泛指针变量
    return f(x);
}
使用泛指针没有问题,但直接这样调用肯定编译通不过,因为编译器不知道该如何调用这个 f 。
所以,我们必须给 f 一个编译器明白的类型,也就是强制类型转换,如下:
unsigned int test()
{
    unsigned int x = 0;
    void* f;
    return (*(unsigned int(*)(unsigned int x))f)(x);
}
再编译就肯定能通过了,因为我们给了这个 void * f 一个明确的函数类型 *(unsigned int(*)(unsigned int x )。

3)因为上面我们只是讲解例子,很明显我们没有给 f 赋值,下面是完整的写法:
unsigned int test()
{
    unsigned int x = 0;
    void* f = read;
    return (*(unsigned int(*)(unsigned int x))f)(x);
}
式中,我们将上面的 read 函数赋值给了 f。


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 19:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表