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を渡す場合は、r30/r31に64エントリテーブルのアドレスを正確に入力します。あなたが欲しいもの。ただし、振幅を渡す場合は、ポインタのアドレスを取得していることになります。これは、必要なアドレスではない可能性があります。(元のテーブルに戻すには、振幅変数を逆参照する必要があります。)

マイクロコントローラーでは変数の逆参照が比較的遅いことが多いため(特に時間に敏感な割り込み内)、2つのテーブルから選択する単一のブールフラグを持つようにコードを再編成することを強くお勧めします。例えば:

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

これの最終結果は、たった1つの追加の分岐命令になるはずです。おそらく、振幅ポインタを逆参照するための追加の時間よりも高速です。または、両方のルックアップテーブルを1つの96バイトテーブルにマージして、それに応じてインデックスを調整することもできます。以前と同様に、割り込みの外部で使用するテーブルの時間のかかる決定を実行して(Cコード内のフラグを変更することにより)、割り込みを高速かつ効率的に保つことができます。

于 2011-05-08T01:36:16.123 に答える