2

我正在使用 C 和 ASM 混合编写 AVR 微控制器,但遇到了一些麻烦。

我的 C 代码中有以下代码:

uint8_t amplitudes32[32] = {.. constant values ..};
uint8_t amplitudes64[64] = {.. constant values ..}
uint8_t* amplitudes;

(amplitudes32/64 基本上是查表)

有时我希望幅度等于幅度 32,有时希望它等于幅度 64。

我正在这样做

amplitudes = amplitudes32;在我的 c 代码中。

然后,在我的 ASM 中断例程中,我想像这样读取数组的地址:

ldi r30, lo8(amplitudes)    
ldi r31, hi8(amplitudes)  

然后我做一些更多的指令来将某个索引处的数组值传到一个特定的端口。但是,当我检查输出时,它不能正常工作并且我得到了一些我没想到的东西。无论数组由什么组成,我都会得到相同的结果。即使amplitudes指向全零数组也是一样的。

如果我将汇编代码更改为

ldi r30, lo8(amplitudes64)      
ldi r31, hi8(amplitudes64) 

然后它按预期工作。但是就像我说的那样,我需要在不同的时间有一个不同的查找表,并且由于速度问题,我无法在中断例程中做出这个决定,所以如果我能有一个数组“变量”就好了可以在我的 C 代码中更改,然后中断使用。

我究竟做错了什么?

4

1 回答 1

4

我对 AVR 组装并不十分熟悉。但是,我相信 lo8 和 hi8 宏正在返回所提供变量的低/高地址——在传入幅度 64 的情况下,你将用你的 64 条目表的地址填写 r30/r31——正是你想要什么。但是,如果您传入幅度,您将获取指针的地址,这可能不是您想要的。(幅度变量需要取消引用才能返回到原始表。)

由于在微控制器中取消引用变量通常相对较慢(尤其是在时间敏感的中断中),我强烈建议您重新组织代码以在两个表之间选择一个布尔标志。例如:

if (UseTable64)
 ldi r30, lo8(amplitudes64)      
 ldi r31, hi8(amplitudes64) 
else
 ldi r30, lo8(amplitudes32)      
 ldi r31, hi8(amplitudes32) 
end if

这样做的最终结果应该只是一个额外的分支指令——可能比取消引用幅度指针的额外时间要快。或者,您可以尝试将两个查找表合并到一个 96 字节表中,并相应地调整您的索引。和以前一样,您仍然可以在中断之外执行耗时的决定(通过修改 C 代码中的标志),以使中断保持快速和高效。

于 2011-05-08T01:36:16.123 回答