哪种方法可以更快地初始化微控制器中的寄存器?

Blo*_*ger 5 c embedded microcontroller

在为PIC微控制器编写固件时想到了这个问题。

我知道有两种方法可以初始化微控制器中的寄存器。举例来说,如果我们将端口初始化为输出,则一种方法是编写如下命令,并将其分配1给TRISx寄存器中的每个位

方法1

TRISX = 0xFF;
Run Code Online (Sandbox Code Playgroud)

可以通过单独分配位来完成同一件事。

方法2

_TRISX0 = 1;
_TRISX1 = 1;
_TRISX2 = 1;
...
_TRISX7 = 1;
Run Code Online (Sandbox Code Playgroud)

我的问题是,编译器会否将其视为相同,并且完成这两个操作所花费的时间是相同的?还是方法1占用一个时钟周期,而方法2占用8个时钟周期(我的意思是慢8倍)?

我尝试阅读X16编译器指南,但找不到任何提示。

Lun*_*din 11

硬件寄存器始终是volatile合格的,并且不允许编译器优化包含volatile访问权限的代码。因此,如果您给他们写8次信,那么您将获得8次写信。当然,这比1次写入要慢得多。

另外,将寄存器连续写入多次就像将其作为RAM中的临时变量一样,是非常不好的做法。硬件寄存器往往具有各种微妙的副作用。它们可以具有“一次写入”属性,或仅接受某些模式下的写入。通过分几步写给他们,您就会养成习惯,以创建由错误的寄存器设置引起的各种疯狂的,细微的问题。

正确的做法是一次或多次写入寄存器。

例如,您可能认为示例中的数据方向寄存器是一个非常愚蠢的没有副作用的寄存器。但通常GPIO硬件需要一些时间来切换端口电路,从您写入数据方向寄存器的点到访问I / O端口的点。因此,几次写入可能会不必要地使端口停顿。

假设REGISTER是内存映射的volatile合格硬件寄存器的名称,然后...

不要这样做:

MASK1 = calculation();
REGISTER |= MASK1;
MASK2 = calculation();
REGISTER |= MASK2;
Run Code Online (Sandbox Code Playgroud)

做这个:

uintx_t reg_val=0; // temp variable in RAM
MASK1 = calculation();
reg_val |= MASK1;
MASK2 = calculation();
reg_val |= MASK2;
REGISTER = reg_val; // single write to the actual register
Run Code Online (Sandbox Code Playgroud)


Dav*_*ins 7

这将取决于处理器指令集和编译器。例如,对于PIC18F45K20,sdcc编译器将编译以下内容

TRISDbits.TRISD0 = 1;
Run Code Online (Sandbox Code Playgroud)

BSF _TRISDbits, 0
Run Code Online (Sandbox Code Playgroud)

在编译时

BSF _TRISDbits, 0
Run Code Online (Sandbox Code Playgroud)

MOVLW   0xff
MOVWF   _TRISD
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,设置单个位会更快,因为它不涉及在工作寄存器中放置临时值。

BSF但是,并非所有指令集都包含一条指令,并且某些架构不需要为后一项任务使用工作寄存器。

PS上面的示例基于sdcc编译器的输出,但是我认为xc8xc16编译器会产生相似的结果。

PPS在检查生成的程序集时,请记住,某些指令比其他指令消耗更多的处理器周期。有关详细信息,请参见数据表。