Youtubeでも掻動䞭

チャンネル登録しおくれたら喜びたす。
リンクはフリヌです。共有・拡散は倧歓迎

このボタンで簡単にチャンネル登録
PR

【ビット操䜜】Arduinoで䜿うビット挔算をマスタヌする。

arduino-bit-calc-eyecatch

今回はArduinoでも䜿うビット挔算子に぀いおのご玹介です。

Arduinoを䜿っおいおビット挔算が必芁になるタむミングずいえば、

なにかのICを䜿うずきに、レゞスタをいじるずきくらいでしょうか

ただ、以前からArduinoをAVRのマむコンずしお䜿甚しおいる蚘事を曞いおいたす。

そこでは頻繁にマむコン自䜓のレゞスタを曞き換える関係䞊、

どうしおもビット挔算が必芁になりたす。

たあ、毎回0b00000001のように8bit党お指定しおもできたすが…

ちょっずかっこ悪いずいうのず、他の機胜を叞るbitたで䞍甚意に倉曎するのは

バグの原因ずなりたすから、基本的には必芁なずころを必芁なだけ倉曎したほうがいいです。

ただでさえ既にむベントで出力するようずしおピンが予玄されおいるこずもありたすので、

そのピンを䞍甚意にいじっおしたうのは危ないですよね

ずいうこずで今回はビット挔算に぀いおご玹介しおいきたす。

この蚘事を読むこずでわかるこず

自己玹介

サラリヌマンしおたす。

䞻に工堎(生産珟堎)で䜿甚する怜査装眮のアプリケヌション開発しおたす。

ヒトの䜜業を自動化しお簡略化するアプリケヌションを日々開発䞭。

2022幎5月に転職。珟圹バリバリの技術者です。
珟圚は超倧手䌁業の新芏事業分野で装眮の研究・開発をしおいたす。

Youtubeチャンネルにさたざたな動画を䞊げおいたす。

↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓

泚意

本ブログはアフィリ゚むトを甚いた広告を掲茉しおいたす。

  1. どんなずきにビット挔算が必芁か
    1. IC(シフトレゞスタだったりIO゚キスパンダだったり)を制埡する堎合。
    2. Arduinoの本䜓ずもいうべきマむコン本䜓を制埡する堎合。
  2. ビット挔算ずは具䜓的に䜕をする
    1. bitのなかの、指定した桁数のbitのみを反転させる。
    2. 指定した桁のbitを匷制的に1たたは0にする。
    3. 取埗したレゞスタの状態から、目的の桁数のビットが立っおいるかどうか確認する。
  3. ビット挔算を実䟋ず合わせお玹介する。
    1. bitのなかの、指定した桁数のbitのみを反転させる。
    2. 指定した桁のbitを匷制的に1たたは0にする。
      1. 匷制的に狙ったbitを1にする堎合。
      2. 匷制的に狙ったbitを0にする堎合。
    3. 取埗したレゞスタの状態から、目的の桁数のビットが立っおいるかどうか確認する。
  4. 今回のたずめ。

どんなずきにビット挔算が必芁か

それではどんな時にビット挔算が必芁か䟋を挙げおいきたしょう。

䟋えばこの2぀は本ブログでも玹介しおいる内容です。

  • IC(シフトレゞスタだったりIO゚キスパンダだったり)を制埡する堎合。
  • Arduinoの本䜓ずもいうべきマむコン本䜓を制埡する堎合。

どちらも以前から玹介しおいる内容なので軜く觊れおいきたしょう。

IC(シフトレゞスタだったりIO゚キスパンダだったり)を制埡する堎合。

IC関係を制埡するずきはそのICのレゞスタに通信する必芁がありたす。

その際、そのICのデヌタシヌトに曞かれおいるレゞスタ(いわゆる番地)

にビットを立おたり萜ずしたりするこずで、ICを意図通りに動かしたす。

具䜓的には、この蚘事で玹介したmcp23017ずいう

IO゚キスパンダヌなんかがいい䟋です。

これがIO゚キスパンダヌ

↓↓↓

MCP23017
IO゚キスパンダヌ MCP23017
ビット挔算を䜿う堎面(ICの制埡)

このIO゚キスパンダヌで䜿甚するピンを蚭定したり、

実際に出力させるずきに0b00000011のように2進数で該圓箇所にビットを

立おた状態で送信するず、IC偎でその通りの動きをしたす。

単玔な制埡の堎合はすべお8bitなら8bit䞞ごず入力しおしたっおも問題ないこずが倚いです。

Arduinoの本䜓ずもいうべきマむコン本䜓を制埡する堎合。

先ほどの䟋だず、8bitなら8bit䞞ごず入力しおしたえばいいず蚀いたしたが、

このArduinoに茉っおいるマむコンの制埡の堎合、

そうはいきたせん。

ずいうのも、Arduinoの堎合、すでにどこかに぀ながっお、

動䜜させるのに重芁なビットたで萜ずしおしたうず、

正垞な動䜜にならないためです。

䟋えば、PortAの0~7たですべおLOWに萜ずす。

ずいった指什を出した堎合に、他の機胜ずバッティングしお、

PORTAの○○番ピンをLOWに萜ずすず䞍具合が…なんおこずが発生する可胜性があるためです。

ビット挔算ずは具䜓的に䜕をする

ビット挔算でやるこずず蚀えば、次の3぀くらいだず認識しおいたす。

  • bitのなかの、指定した桁数のbitのみを反転させる。
  • 指定した桁のbitを匷制的に1たたは0にする。
  • 取埗したレゞスタの状態から、目的の桁数のビットが立っおいるかどうか確認する。

具䜓的にどういうずきにその挔算が必芁なのかご玹介したす。

bitのなかの、指定した桁数のbitのみを反転させる。

これは、入出力関係のレゞスタをいじるずきに発生したす。

今たで出力しおいた5番pinを今床はLOWにしお出力を止めたい。

なんおずきですね。

その時、3番pinや4番pinはそのたたHIGHのたたで制埡したい。

ずいう堎合、なにも考えずにすべおのbitを萜ずすず、

3番pinず4番pinにも圱響を及がすわけです。

ですから、狙った桁のビットを反転させる必芁があるわけです。

指定した桁のbitを匷制的に1たたは0にする。

これは初期化の時なんかによく䜿いたす。

今珟圚のレゞスタの状態は無芖しお、指定した状態にしたいずきですね。

先ほども曞きたしたが、初期化の時はこのように匷制的にビットの操䜜を行いたす。

取埗したレゞスタの状態から、目的の桁数のビットが立っおいるかどうか確認する。

レゞスタの状態は確認する機䌚もあるはずです。

そんな時、8bitならば、8桁の01の数字の矅列が返っおくるはずです。

その矅列を芋お、○○桁目だから….ずやるずちょっずダサいですよね。

ですから、あらかじめ○○桁だけを芋るように工倫するわけです。

ビット挔算を実䟋ず合わせお玹介する。

それでは実䟋ず合わせお今回のビット挔算の内容をご玹介しおいきたしょう。

たず、䜿うのはC++

8bitのレゞスタを操䜜するこずを前提ずしたす。

C++ずしたのは、Arduinoの蚀語がC++の掟生だからです。

この通りやっおもらうず、Arduinoでも䜿えたすので詊しおみおください。

前提条件
  • 䜿甚蚀語はC++
  • 8bitのレゞスタを操䜜する。

ではやっおいきたしょう。

bitのなかの、指定した桁数のbitのみを反転させる。

指定した桁のずころだけbitを反転させる堎合をご玹介したす。

䟋えば、0b00100100ずいう状態になっおいたずしたしょう。

ここで、3bit目の1のみを0にしたしょう。

぀たり、3bit目を反転するわけです。そのほかのbitには圱響が出おはいけたせん。

たずは悪い䟋です。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test = 0b000;//ここで0にしおいるが、6bit目たで0になっおしたう。
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果0

たしかに0b000ずすれば、0bit目から3bit目たで0にするこずはできたしたが、

6bit目の1たで0になっおしたっおいたす。

しかも反転ず蚀っおいるのに、匷制的に0にしおいるので、反転ずも蚀えないですね。

それではどうすればいいのか。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test ^= 0b100;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
} // 実行結果32(0b00100000)

こうするこずによっお、6bit目に圱響が出ないようになっおいたす。

具䜓的にはここの行ですね。

test ^= 0b100;// ここで反転させおいる。

ここで䜕をしおいるかずいうず、

^=はXORです。

このXORは、䞡方のbitを確認しお、どちらか䞀方でも1になっおいたら1。

どちらも1になっおいたら0にするずいう論理挔算子です。

぀たりXORを䜿うこずで、

3bit目が1になっおいたら0になるし、

3bit目が0だった堎合は1になる。぀たり反転するずいうこずですね。

詊しにこのように2行にするず、元に戻るこずが確認できたす。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test ^= 0b100;
    test ^= 0b100;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果36(0b00100100)

圓然ですが、耇数のbitを同時に反転させるこずも可胜です。

それでは、1~4bit目を反転させたしょう。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test ^= 0b1111;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}//実行結果43(0b00101011)

ちゃんず1~4bit目たで反転しおいるこずがわかりたすね。

指定した桁のbitを匷制的に1たたは0にする。

次に指定した桁のbitを匷制的に1たたは0にしおみたしょう。

ひず぀前の章では、反転でしたから、珟圚のbitの状態によっお倉化させおいたした。

今回は匷制的に狙ったbitだけ0か1にしたいので、XOR挔算子は䜿甚できたせん。

では䜕を䜿うかずいうず、1にしたい堎合はOR、0にしたい堎合はANDずNOTです。

具䜓的にコヌドをお芋せしたす。

1にしたい堎合。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test |= 0b1111;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果47(0b00101111)

0にしたい堎合。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test &= ~0b1111;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果32(00100000)

匷制的に狙ったbitを1にする堎合。

匷制的に1にする堎合は、ORを䜿甚したす。

ORは|この蚘号を䜿甚したす。

ORの圹割は、䞡方のbitを比范しお、どちらか䞀方でもbitに1が入っおいる堎合は1にする。

ずいう論理挔算子です。

ですから、狙ったbitに1を立おたいなら、ORで1をぶ぀けおやれば、

たずえ元のbitが0でも1でも匷制的に1になる。ずいう原理です。

匷制的に狙ったbitを0にする堎合。

匷制的に0にする堎合は、ANDずNOTを䜿甚したす。

ANDの圹割は、䞡方のbitを比范しお、どちらも1になっおいなければ0で、

どちらも1になっおいれば1になりたす。

NOTは吊定の論理挔算子です。今回の堎合は、

~0b1111ずなっおいるので、0b0000ず同じ意味です。

では今回の堎合はどうなっおいるかずいうず、

1bit目から4bit目たで0b0000ずANDをずるずいうこずになりたす。

0ずANDをずる⇒必ず0になる。

こういった原理をうたく利甚しおいるずいうこずです。

取埗したレゞスタの状態から、目的の桁数のビットが立っおいるかどうか確認する。

今床は取埗したレゞスタの䞭から、必芁な桁数のビットを確認する方法です。

具䜓的には、先ほどから䜿甚しおいる䟋を匕き続き䜿甚したす。

䟋えば、test = 0b00100100ずなっおいお、このtestの状態を読んだずしたす。

そしお、5bit目が0なのか1なのかを確認したいずしたす。

もちろん人間はこの数字の矅列を目で確認しお、右から5番目は0なのか1なのか

ず確認するこずが可胜です。もちろん0ですね

ただ、プログラム䞊でそこだけ必芁な堎合どうしたらいいでしょうか

そのbitだけ䜿っおif文で分岐したいな…なんおずきに結構面倒なはずです。

それではその面倒な問題を解決したしょう。

問題のキヌずなるのは、ビットシフトずいうツヌルです。

たずはコヌドをお芋せしたす。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test = (test>>4 & 0b01);
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果0

たったこれだけで5bit目の状態がわかりたす。

ビットシフトは>>で衚珟されたす。ビットシフトずは、

単玔に説明するず、数字の矅列をそのたたごっそり移動させる手法です。

test>>1ずするず、1぀右にずれたす。

぀たりtest=0b0010010ずなりたす。

さらに続けおtest>>1ずするず、

test=0b001001ずなりたす。

今回の䟋では5bit目の状態が知りたいので、4぀右にずらすこずで、

5bit目の数倀が1bit目に来たす。

さらにそこたで来たら、0b01ずANDをずっおあげれば、

5bit目よりも䞊のbitは無芖しお0なのか1なのかがわかるずいう原理です。

ビットシフトしただけだず、5bit目以降の倀も䞀緒に出おきおしたうので、

&0b01は必ず必芁になるのを忘れないように気を぀けたしょう。

ためしに&0b01を忘れるずこんな感じになりたす。

#include <iostream>
#include <string>
using namespace std;

int main() {
    int test = 0b00100100;
    test = test>>4;
    string testS = std::to_string(test);
    printf(testS.c_str());
    return 0;
}// 実行結果2(0b10)

今回のたずめ。

今回はビット挔算に぀いおご玹介したした。

私自身、Arduinoに茉っおいるatmega4809のレゞスタを盎接いじっおいる時に、

あれ、ビット挔算子っおこれ䜕の意味だっけ

なんお思い出しながらやっおいた郚分もあったので、

今回の蚘事は自分の備忘録的な意味合いもありたす。

レゞスタをいじったりマむコン関係で制埡する人には圓たり前の話かもしれないですが、

初心者でこれからビット挔算どんどんやっおいくぞずいう

堎合には有甚です。ぜひマスタヌしおみおください。

コメント

タむトルずURLをコピヌしたした