我正在使用C和ASM的混合编程AVR微控制器,但我遇到了一些麻烦。
我的C代码中有以下代码:
uint8_t amplitudes32[32] = {.. constant values ..};
uint8_t amplitudes64[64] = {.. constant values ..}
uint8_t* amplitudes;
(幅度32/64基本上都是查表)
有时我希望幅度等于幅度32,有时希望它等于幅度64.
我这样做是为了
我的c代码中的 amplitudes = amplitudes32;
。
然后,在我的ASM中断例程中,我想读取数组的地址,如下所示:
ldi r30, lo8(amplitudes)
ldi r31, hi8(amplitudes)
然后,我再做一些指令,将数组的值在特定的索引处获取到特定的端口。但是,当我检查输出时它没有正常工作,我得到了一些我没想到的东西。无论数组是由什么构成的,我都会得到同样的东西..即使amplitudes
指向全零的数组也是如此。
如果我将汇编代码更改为
ldi r30, lo8(amplitudes64)
ldi r31, hi8(amplitudes64)
然后按预期工作。但就像我说的,我需要在不同的时间有一个不同的查找表,并且由于速度问题我无法在中断例程中做出决定所以如果我有一个数组'变量'我会很好可能会改变中断然后使用的C代码。
我做错了什么?
答案 0 :(得分:4)
我对AVR组装并不熟悉。但是,我相信lo8和hi8宏正在返回所提供变量的低/高地址 - 在传入幅度64的情况下,你将用 64条目表的地址 - 正是您想要的。但是,如果传入幅度,则表示您正在使用指针的地址,这可能不是您想要的。 (需要取消引用幅度变量才能返回原始表格。)
由于解除引用变量在微控制器中通常比较慢(特别是在时间敏感的中断中),我强烈建议您重新组织代码,以便在两个表之间选择一个布尔标志。例如:
if (UseTable64)
ldi r30, lo8(amplitudes64)
ldi r31, hi8(amplitudes64)
else
ldi r30, lo8(amplitudes32)
ldi r31, hi8(amplitudes32)
end if
这样的最终结果应该只是一个额外的分支指令 - 可能比取消引用振幅指针的额外时间更快。或者,您可以尝试将两个查找表合并为一个96字节表,并相应地调整索引。和以前一样,您仍然可以执行耗时的决定,使用哪个表来使用在中断之外(通过修改C代码中的标志),以便中断保持快速和高效。