2017-02-19 5 views
2

マイクロコントローラ用のライブラリをいくつか書いています。そのために、私はマクロのような機能を使います。例えば、I2Cモジュールを有効にするマクロのような機能が定義されているとして:_xモジュール番号であるを使ったマクロ定数の連結##

#define I2C_MODULE_ENABLE(_x) \ 
    I2C##_x##CONLbits.I2CEN = 1 

(例えば、1又は2私の場合)。

ユーザーがI2C_MODULE_ENABLE(1)というマクロのような関数を呼び出すと、プリプロセッサーによってI2C1CONLbits. I2CEN = 1に展開されます。しかし

、ユーザは、(例えば、マクロ定数が#define MY_I2C 1のように定義される)MY_I2Cは私i2c.hライブラリに含まれるユーザ定義config.hファイルで定義されたマクロ定数であるI2C_MODULE_ENABLE(MY_I2C)、このマクロのような関数を呼び出す場合マクロ的な機能はI2CMY_I2CCONLbits. I2CEN = 1として拡張されます。

は私が何とか連結前MY_I2Cマクロ定数を評価する必要があることを知っている、と私は別のマクロレベル追加していることを行うことができます。

#define __I2CxCONLbits(_x) I2C##_x##CONLbits 
#define I2C_MODULE_ENABLE(_x) \ 
    __I2CxCONLbits.I2CEN = 1 

私の質問は次のとおりです。をよりエレガントな解決策はこれにあり私がCONLbitsレジスタのような複数のレジスタを持っているので、問題。このアプローチを使用すると、すべてのレジスタに特別な__I2CxREGISTER(_x)マクロを定義する必要があります。

私はこのような何かしようとした:

#define __I2Cx(_x) I2C##_x 
#define I2C_MODULE_ENABLE(_x) \ 
    __I2Cx(_x)##CONLbits.I2CEN = 1 

をそれは、このような出力を生成します:I2C1 CONLbits .I2CEN = 1、そして私のコンパイラはI2C1CONLbitsトークンの間に空白文句を言っています。

答えて

5

マクロレベルを正しく追加していません。表示されています。通常のイディオムは、引数を転送するだけで何もしないラッパーを定義することです。引数がマクロそのものであればその方法は、それがラップされているマクロに渡される前に展開されます。

#define I2C_MODULE_ENABLE__(x_) \ 
    I2C##x_##CONLbits.I2CEN = 1 

#define I2C_MODULE_ENABLE(x_) \ 
    I2C_MODULE_ENABLE__(x_) 

先頭のアンダースコアを持つ識別子は次のように定義されているので、私は、あなたのマクロのパラメータの名前を変更するの自由を取りました実装のために予約されて、私はそれが残念よりも安全であることをお勧めします。必ずそれが正しく展開だ作るために、私は間接のことわざのレベルで行く、そして正しい接頭トークンを生成するために、マクロのような機能を使用し、二つのレベルに沿って、それを渡したいスペースのあなたの問題を解決するために


#define I2Cx__(x_) I2C##x_ 
#define I2C_MODULE_ENABLE__(IC_) \ 
    IC_##CONLbits.I2CEN = 1 
#define I2C_MODULE_ENABLE_(IC_) \ 
    I2C_MODULE_ENABLE__(IC_) 
#define I2C_MODULE_ENABLE(x_) \ 
    I2C_MODULE_ENABLE_(I2Cx__(x_)) 

はライブhere

全体shtickは確かプリプロセッサが見て、各ステップで有効なトークンを生成することです、それを参照してください。どちらが少し面倒なことができます。

+0

これは実際に問題を解決していない/質問に答えます。 – melpomene

+0

@melpomene - 私は結局そこに着いた。私のお気に入りのクラウドコンパイラでコードサンプルを確認するのに問題があった:) – StoryTeller

+0

それはまだ 'CONLbits'を使うためにハードコードされています。 – melpomene

関連する問題