打印

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

[复制链接]
1017|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stly|  楼主 | 2021-4-1 21:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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个系统指令周期,让人崩溃。

使用特权

评论回复
沙发
spark周| | 2021-4-1 21:15 | 只看该作者
楼主详细说说怎么回事啊,这么说太笼统了

使用特权

评论回复
板凳
xxmmi| | 2021-4-1 21:16 | 只看该作者
看看面向对象的方法,容易理解了就......

使用特权

评论回复
地板
stly|  楼主 | 2021-4-1 21:19 | 只看该作者
编译器是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;
}

使用特权

评论回复
5
jlyuan| | 2021-4-1 21:21 | 只看该作者
你那数据不适合8位机操作,能给你结果就不错了。如果这样的数据过多还有速度要求,说明你的芯片选错了。8位机的优势不在这里

使用特权

评论回复
6
langgq| | 2021-4-1 21:23 | 只看该作者
指针不适合于普通的PIC单片机

使用特权

评论回复
7
stly|  楼主 | 2021-4-1 21:25 | 只看该作者
8位机就是价格有优势,没其他了

使用特权

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

使用特权

评论回复
9
bqyj| | 2021-4-1 21:30 | 只看该作者
看指令就知道了,指针这种操作最适合ARM内核

使用特权

评论回复
10
zwll| | 2021-4-1 21:35 | 只看该作者

pic的指令系统确实不太适合用指针,还是尽量用简单的语句吧。

使用特权

评论回复
11
llljh| | 2021-4-1 21:37 | 只看该作者
另外编译器也不够智能,否则应该也可以少用几条指令。

使用特权

评论回复
12
stly|  楼主 | 2021-4-1 21:40 | 只看该作者

嗯,预料中的结果,多谢大家啦

使用特权

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

本版积分规则

433

主题

7058

帖子

0

粉丝