1 ビットに書き込むにはどうすればよいですか? 1 または 0 の変数があり、その値を 8 ビットreg
変数の 1 ビットに書き込みたいと考えています。
私はこれが少し設定されることを知っています:
reg |= mask; // mask is (1 << pin)
そして、これは少しクリアになります:
reg &= ~mask; // mask is (1 << pin)
値が入力として高いか低いかを判断することなく、1 行のコードでこれを行う方法はありますか?
またはvalue
であると仮定します。0
1
REG = (REG & ~(1 << pin)) | (value << pin);
OPコメントで@KerrekSBが指摘したように、Cキーワードであるため、REG
代わりに使用します。register
register
ここでの考え方はREG
、指定されたビットをクリアして の値を計算し、それに応じてvalue
ビットを設定するというものです。
C の見落とされている機能の 1 つは、組み込み作業に最適なビット パッキングです。を定義して、struct
各ビットに個別にアクセスできます。
typedef struct
{
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
} T_BitArray;
は: 1
、各変数を 1 ビット長にすることのみをコンパイラに指示します。次に、変数が置かれているアドレスにアクセスし、reg
それをビット配列にキャストしてから、ビットに個別にアクセスします。
((T_BitArray *)®)->bit1 = value;
®
変数のアドレスです。((T_BitArray *)®)
は同じアドレスですが、コンパイラはそれをT_BitArray
アドレスと見なし((T_BitArray *)®)->bit1
、2 番目のビットへのアクセスを提供します。もちろん、よりわかりやすい名前を使用することをお勧めします。bit1
これに埋め込みタグを付けたので、最良の答えは次のとおりだと思います。
if (set)
reg |= mask; // mask is (1 << pin)
else
reg &= ~mask; // mask is (1 << pin)
(マクロまたはインライン関数でラップできます)。その理由は、AVR のような組み込みアーキテクチャにはビット セット命令とビット クリア命令があり、分岐のコストが他の命令に比べて高くないからです (投機的実行を行う最新の CPU のように)。GCC は、そのif
ステートメントのイディオムを識別し、適切な指示を生成できます。より複雑なバージョン (最新の x86 でテストしたときにブランチレスであっても) は、組み込みシステムで最適な命令にアセンブルされない可能性があります。
確実に知る最善の方法は、結果を逆アセンブルすることです。結果を評価するのに専門家である必要はありません (特に組み込み環境では)。
単一ビットをどのように設定、クリア、およびトグルするかの複製と、まだ誰も言及されていないSETおよびCLEARレジスタとして、私の回答も再投稿します。
これは「組み込み」とタグ付けされているので、マイクロコントローラーを使用していると仮定します。上記の提案はすべて有効で機能します (読み取り-変更-書き込み、共用体、構造体など)。
しかし、オシロスコープベースのデバッグを行っている間に、マイクロの PORTnSET / PORTnCLEAR レジスタに値を直接書き込む場合と比較して、これらの方法が CPU サイクルにかなりのオーバーヘッドがあることに驚きました。 -周波数 ISR のトグル ピン。
なじみのない人のために: 私の例では、マイクロには出力ピンを反映する一般的なピン状態レジスタ PORTn があるため、PORTn |= BIT_TO_SET を実行すると、そのレジスタへの読み取り-変更-書き込みが行われます。
ただし、PORTnSET / PORTnCLEAR レジスタは、「このビットを 1 にしてください」(SET) または「このビットを 0 にしてください」(CLEAR) を意味する「1」と、「ピンをそのままにしておく」を意味する「0」を取ります。そのため、ビットを設定するかクリアするかに応じて 2 つのポート アドレスが必要になりますが (常に便利というわけではありません)、はるかに高速な反応と小さなアセンブル コードになります。