EDN首页   博客首页

3

关于投票
继续关于C++在WINAVR上的位控及优化问题
/*-------------------------------------------------------------------
优化示例:
  DDRB &= ~((1 << SCL) | (1 << SDA)); //SCL设置为输入方式,SCL信号由主机提供
上句将比下两句代码多编译2个字节
  DDRB &= ~(1 << SCL); //SCL设置为输入方式,SCL信号由主机提供
  DDRB &= ~(1 << SDA); //SDA设置为输入方式
--------------------------------------------------------------------*/
在MCU中,对'位'的控制都格外关心,都担心C的效率问题.但gccavr在这方面解决的很出色.
 
有时可能需要位的同时控制,则必须像:
DDRB |= ((1 << SCL) | (1 << SDA));
DDRB &= ~((1 << SCL) | (1 << SDA));
PORTB |= ((1 << SCL) | (1 << SDA));
PORTB &= ~((1 << SCL) | (1 << SDA));
 
但在小容量的芯片或和次序无关时,采用 :
DDRB &= ~(1 << SCL);
DDRB &= ~(1 << SDA);
PORTB |= (1 << SCL);
PORTB |= (1 << SDA));
可能效率更高,也符合"位控"的目的.
 
好些人一直纠缠51的"位控"方式: P1_0 = 1;P0_0 = 0;
认为是真正的"位控"方式.
 
实际是习惯问题. 因为在更多的环境下,C的通用"位控"方式则更具有普遍性.
即|=;&=~;^=的这几种常用书写方式.
 
说实话,MCU与PC的最大不同就是对硬件的操作,MCU实际最后和最直接的目的
就是用位控来达到控制的目的.
可以说几乎见不到没有位控的MCU系统.
系统分类: 单片机
用户分类: 程序优化
标签: 无标签
来源: 原创
发表评论 阅读全文(867) | 回复(0)

1

关于投票
关于C++在WINAVR上的优化问题
inline//不加inline将增大空间6个字节 
void UsiObj::CommandExec(void)
{
...............
}

//inline//加inline将增大空间40个字节 
void UsiObj::Exec(void)
{
....................
}

class AdcObj {
private:
  unsigned char AdcNum;//加volatile将增大空间72个字节
  unsigned char AdcCount;//加volatile将增大空间4个字节
  volatile unsigned int AdcSum[8];//不改变
  unsigned int AdcMax[8];//加volatile将增大空间4个字节
  volatile unsigned int AdcMin[8];//不改变
..............................
};

/*-------------------------------------------------------------------
优化示例:
  while (PINB & (1 << SCL));//等待SCL=0主机处理结束
上句将比下句代码多编译16个字节
  while ((unsigned char)tmp = (PINB & (1 << SCL)));//等待SCL=0主机处理结束
--------------------------------------------------------------------*/

/*-------------------------------------------------------------------
优化示例:
          USIDR = TxBuffer[Count];//发送8位数据1个字节
        Count ++;
以上2句将比下句代码多编译26个字节
          USIDR = TxBuffer[Count++];//发送8位数据1个字节
--------------------------------------------------------------------*/

/*-------------------------------------------------------------------
优化示例:
        if (((USIDR << 4) ^ USIDR) >= 0xf0) {//Command高低4位相反
上句将比下几句代码多编译14个字节
//        tmp = USIDR;
//      tmp <<= 4;
//        tmp ^= USIDR;
//        if (tmp >= 0xf0) {//Command高低4位相反
--------------------------------------------------------------------*/

/*-------------------------------------------------------------------
优化示例(此前Status=4):
        Status ++;
上句将比下句代码多编译2个字节
        Status = 5;
--------------------------------------------------------------------*/

/*-------------------------------------------------------------------
优化示例(此前Status=5):
        Status --;
上句将比下句代码多编译6个字节(这个有些不定,至少在2字节以上)
        Status = 4;
--------------------------------------------------------------------*/

/*-------------------------------------------------------------------
优化示例:
  for(i = 31; i >= 13; i --) {
上句将比下句代码多编译2~4个字节
  for(i = 13; i <= 31; i ++) {
--------------------------------------------------------------------*/
系统分类: 单片机
用户分类: 程序优化
标签: 无标签
来源: 原创
发表评论 阅读全文(822) | 回复(0)

0

关于投票
拜托放弃位域效率低下的习惯吧~~~
hotpower 发表于 2006-7-2 23:35 DSP 技术 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

拜托放弃位域效率低下的习惯吧~~~

研究了C28X的头文件后,有点失望~~~看来TI也陶醉与51位的流毒~~~

51的位只能适合自己,虽然PIC也是满身的位,AVR的PORT位.

但随着16位/32位 ARM/DSP的发展,"位"已淡化,且以另一种新的构思代替,即

IOSET,IOCLR代替,且2812还有IOTOGGLE.

由于控制更加复杂,模块已不能用几个寄存器就能表述...

他们一般都是地址连续或能遵循一定排列规律的变量,故一般都声明为结构(指针)而使表述更为简洁.

例:
struct GPIO_DATA_REGS {
   union  GPADAT_REG    GPADAT;
   union  GPASET_REG    GPASET;
   union  GPACLEAR_REG  GPACLEAR;
   union  GPATOGGLE_REG GPATOGGLE;
//..............
};
//...............
union GPFTOGGLE_REG {
   Uint16                all;
   struct GPFTOGGLE_BITS bit;
};

虽然位域的设置清除很方便,但是对编译器的优化带来的难题~~~

下图是经过3级优化后的编译代码,确实不好.

所以,可以保留TI的头文件,再加上"位宏",就能提高代码的效率....
(连续操作相同变量的位域不是个好习惯,除非硬件需要)

   SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;
   SysCtrlRegs.PCLKCR.bit.EVBENCLK=1;
   SysCtrlRegs.PCLKCR.bit.SCIAENCLK=1;
   SysCtrlRegs.PCLKCR.bit.SCIBENCLK=1;
   SysCtrlRegs.PCLKCR.bit.MCBSPENCLK=1;
   SysCtrlRegs.PCLKCR.bit.SPIENCLK=1;
   SysCtrlRegs.PCLKCR.bit.ECANENCLK=1;
   SysCtrlRegs.PCLKCR.bit.ADCENCLK=1;
写成以下形式肯定代码简洁
SysCtrlRegs.PCLKCR.all |= (1 << ...) | (1 << ...);

所以不如放弃union直接用:
SysCtrlRegs.PCLKCR |= (1 << ...) | (1 << ...);

当然偷懒就只不要滥用xxx.bit....而在只控制1个位时使用,超过2个就用xxx.all.

哈哈,菜农拜托各位晕友放弃位域效率低下的不良习惯吧~~~

点击看大图

系统分类: DSP
用户分类: 程序优化
标签: 无标签
来源: 原创
发表评论 阅读全文(928) | 回复(0)
总共 , 当前 /