今回はC言語でビット演算子(&、>>)を使ってデータを変化させて遊んでみようと思います。
・・・。
ビット演算子と改まって言うと変な感じがしますね。
仕事などで使う場合は、”ビットシフトする”とか”ビットマスクする”とか言うことが多い気がします。
個人的によく使う演算子は下記。
演算子 | 簡単な説明 |
& | アンド。0x81&0x80とすると、0x80となる。 |
| | オア。0x81|0x02とすると、0x83となる。 |
>> | 右シフト。0x40>>1とすると、0x20となる。 |
<< | 左シフト。0x40<<1とすると、0x80となる。 |
ちなみに、数字の先頭を0xとすると、”16進数ですよ”の意味となります。
はじめに
こちらの記事で作成したフォルダに、今回もCソースを作成しようと思いますので、参考にどうぞ。
サンプルコード
いきなりですが、サンプルコードです。
今回は、エアコンからデータを受信したと仮定し、その受信データの内容をプリントしてみようという内容です。
/* インクルードファイル */
#include <stdio.h>
/* プロトタイプ宣言 */
unsigned char Get_Recv_Data(unsigned char *);
unsigned char GetBit(unsigned char *, unsigned char);
/*
受信データ(recv_buf)の各ビットの意味を下記とする。
Bit7 = 電源状態(0=OFF,1=ON)
Bit6 = 運転モード(0=暖房,1=冷房)
Bit5 = 強さ(0=弱,1=強)
Bit4 = 首振り機能(0=OFF,1=ON)
Bit3~0= 温度(0=18℃~15=33℃)
*/
/* メイン関数 */
void main(void) {
unsigned char recv_buf;
/* 外部装置からデータ受信 */
Get_Recv_Data(&recv_buf);
/* 電源状態取得(Bit7) */
printf("電源は");
if(GetBit(&recv_buf,7)){
printf("ONです。\n");
}else{
printf("OFFです。\n");
}
/* 運転モード取得(Bit6) */
printf("運転モードは");
if(GetBit(&recv_buf,6)){
printf("冷房です。\n");
}else{
printf("暖房です。\n");
}
/* 強さ取得(Bit5) */
printf("エアコンの強さは");
if(GetBit(&recv_buf,5)){
printf("強です。\n");
}else{
printf("弱です。\n");
}
/* 首振り状態取得(Bit4) */
printf("首振り機能は");
if(GetBit(&recv_buf,4)){
printf("ONです。\n");
}else{
printf("OFFです。\n");
}
/* 設定温度取得(Bit3~0) */
printf("設定温度は%d℃です。\n",(recv_buf&0x0f)+18);
};
/* 以下、内部関数 */
/*****************************************************************/
/* 関数名:Get_Recv_Data(unsigned char *pbuf) */
/* 機能 :データ受信処理 */
/* メモ :ここでデータを受信する。 */
/* とりあえず受信するデータを直接書く。 */
/*****************************************************************/
unsigned char Get_Recv_Data(unsigned char *pbuf){
*pbuf = 0x80;/* 電源ONのみ */
}
/*****************************************************************/
/* 関数名:GetBit(unsigned char *pbuf, unsigned char bit) */
/* 機能 :ビット取得処理 */
/* メモ :第一引数のバイトデータから、第二引数のビット位置の */
/* ビットを0または1で返す。 */
/*****************************************************************/
unsigned char GetBit(unsigned char *pbuf, unsigned char bit){
unsigned char ret=0;
if(0<=bit && bit<=7){
ret = (*pbuf>>bit)&0x01;
}
return(ret);
}
要点解説
21行目にて、受信データを取得します。
Get_Recv_Dataで、引数の*pbufに対して、0x80のデータを受信したと仮定します。(61行目)
23行目~51行目は、受信データの中身を判定し、プリント出力しています。
ここで、各判定にGetBit関数を使用しています。
GetBit関数は、第1引数のデータに第2引数の分だけビットシフトし、余計なビットをマスクしています。
第2引数の数値は0相対で指定しますので注意です。
あとがき
今回は1バイトデータで色々表現しました。
たかが1バイトですが、使い方によってはビットに様々な意味・状態を含ませる事ができます。
やり方によっては高速に処理ができたりとメリットもありますが、分かりにくかったり、
構造体でビットフィールドを使用する場合は、バイトオーダを意識したりしなくてはいけない等デメリットもあります。