打印
[PIC®/AVR®/dsPIC®产品]

一条取结构体数组元素的指令要花费几十个系统指令周期

[复制链接]
978|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ailingg|  楼主 | 2017-12-18 11:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ailingg 于 2017-12-18 11:34 编辑
typedef void (*PFV1)(UINT8 *pBuf);

typedef struct
{
    UINT16 LongTime;           /* 长按键生效时间,0表示非长按键  */
    UINT8  ReentryTime;        /* 长按键重复生效时间,0表示键值不重复生效  */
    UINT8  FiltTime;           /* 去抖滤波时间      */
    PFV1   keyFuncDown;        /* 按键按下,所调用函数的指针  */
    PFV1   keyFuncUp;          /* 按键弹起,所调用函数的指针  */
    PFV1   keyFuncLong;        /* 按键长按,所调用函数的指针  */
   
}KeyElem_TypeDef;

// 按键元素表
KeyElem_TypeDef const sKeyElemTbl[KEY_QTY] = {
{    600,    0,      4,     KEY_0_FUNC_DOWN,   KEY_0_FUNC_UP,    KEY_0_FUNC_LONG  }, // KEY_0
{    150,    20,      4,     KEY_1_FUNC_DOWN,   KEY_1_FUNC_UP,    KEY_1_FUNC_LONG  }, // KEY_1
{    0,        0,      4,     KEY_2_FUNC_DOWN,   KEY_2_FUNC_UP,    KEY_2_FUNC_LONG  }, // KEY_2
{    150,    20,      4,     KEY_3_FUNC_DOWN,   KEY_3_FUNC_UP,    KEY_3_FUNC_LONG  }, // KEY_3
{    0,        0,      4,     KEY_4_FUNC_DOWN,   KEY_4_FUNC_UP,    KEY_4_FUNC_LONG  }, // KEY_4
{    0,        0,      4,     KEY_5_FUNC_DOWN,   KEY_5_FUNC_UP,    KEY_5_FUNC_LONG  }, // KEY_5
{    150,    20,      4,    KEY_6_FUNC_DOWN,   KEY_6_FUNC_UP,    KEY_6_FUNC_LONG  }, // KEY_6, KEY_0和KEY_1组合
{    150,    20,      4,    KEY_7_FUNC_DOWN,   KEY_7_FUNC_UP,    KEY_7_FUNC_LONG     }  // KEY_7, KEY_0和KEY_3组合

};

if( pKeyElem->LongTime > 0 )

就这么一条指令,要开销33个系统指令周期,让人崩溃。
沙发
ailingg|  楼主 | 2017-12-18 11:38 | 只看该作者
本帖最后由 ailingg 于 2017-12-18 11:46 编辑

编译器是XC8,一条取结构体数组元素的指令居然要调用函数库乘法子程序,巨耗时间。

KeysState |= sKeyVar[keyID].KeyState;

这条指令要调用下面的乘法子程序

// 8 x 8 bit multiplication with 8 bit result

unsigned char
__bmul(unsigned char multiplier, unsigned char multiplicand)
{
    unsigned char product = 0;

#if defined(__OPTIMIZE_SPEED__)

    if(multiplier & 0x01)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x02)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x04)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x08)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x10)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x20)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x40)
        product = (product + multiplicand) & 0xff;
    multiplicand <<= 1;

    if(multiplier & 0x80)
        product = (product + multiplicand) & 0xff;

#else
    do {
        if(multiplier & 1)
            product += multiplicand;
        multiplicand <<= 1;
        multiplier >>= 1;
    } while(multiplier != 0);

#endif
    return product;
}

使用特权

评论回复
板凳
kingkits| | 2017-12-19 11:09 | 只看该作者
你那数据不适合8位机操作,能给你结果就不错了。如果这样的数据过多还有速度要求,说明你的芯片选错了。8位机的优势不在这里

使用特权

评论回复
地板
ayb_ice| | 2017-12-19 11:39 | 只看该作者
指针不适合于普通的PIC单片机

使用特权

评论回复
5
ailingg|  楼主 | 2017-12-19 21:30 | 只看该作者
kingkits 发表于 2017-12-19 11:09
你那数据不适合8位机操作,能给你结果就不错了。如果这样的数据过多还有速度要求,说明你的芯片选错了。8位 ...

8位机就是价格有优势,没其他了

使用特权

评论回复
6
ailingg|  楼主 | 2017-12-19 21:53 | 只看该作者
ayb_ice 发表于 2017-12-19 11:39
指针不适合于普通的PIC单片机

用结构体是为了让程序清晰一些,即使不用函数指针数组,但参数这样的数组还是必须的,问题是一条取数组元素的指令也要十几个系统指令周期,PIC 8位中、低档伤不起。近些年出的高频版本如16F15xx,时钟到16M,一般的应用就不太要考虑如结构体引用开销大这样的问题,但早期的16F73这样的8位MCU真是没办法。

使用特权

评论回复
7
ayb_ice| | 2017-12-20 08:34 | 只看该作者
ailingg 发表于 2017-12-19 21:53
用结构体是为了让程序清晰一些,即使不用函数指针数组,但参数这样的数组还是必须的,问题是一条取数组元 ...

看指令就知道了,指针这种操作最适合ARM内核

使用特权

评论回复
8
lanyong| | 2017-12-20 11:35 | 只看该作者
pic的指令系统确实不太适合用指针,还是尽量用简单的语句吧。

另外编译器也不够智能,否则应该也可以少用几条指令。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

18

主题

167

帖子

2

粉丝