4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ビットシフトしたくないオジサンは今日も共用体を使う

Last updated at Posted at 2025-06-25

前置き

組込みマイコンでの話になります。 当方STM32F4(1ワードが32bit)を使った環境です。

注意事項

マイコン(コンパイラ)の種類に応じて、バイトオーダーでのエンディアンの違いとかあるので、ここで紹介しているコード参考にしたけど、結果が一致しないとかするとかは注意してください。

union(共用体)使わない場合

「32bitのデータをSPI通信で転送するときに16bitを2回に分けて送信する」なんてことは組込み業界ではよくある話ですが、チャットGPTでも初手で出してくるコードはこんな感じでしょう。

void SetSpiData32(uint32_t val) {
    FPGA_SPI_Write(BaseAddress + 0x00, (uint16_t)(val & 0xFFFF)); // Set lower 16 bits
    FPGA_SPI_Write(BaseAddress + 0x01, (uint16_t)((val >> 16) & 0xFFFF)); // Set upper 16 bits
}

ビットシフトとマスク処理が入っていますので、処理サイクル数はかさんでしまいます。
最近のコンパイラは賢いので最適化してビットシフトしないようなコードに変換しているかもしれませんが。。。

union(共用体)使うといいぞ

#ifndef	_TYPEDEF_H_
#define	_TYPEDEF_H_

#include <stdint.h>

// 32bitを16bitと8bitのでアクセスするための共用体
union uint32_u {
    uint32_t UI32;
    struct {
        uint16_t LO;
        uint16_t HI;
    } UI16;
    struct {
        uint8_t LL;
        uint8_t LH;
        uint8_t HL;
        uint8_t HH;
    } UI8;
};

// 16bitを8bitのでアクセスするための共用体
union uint16_u {
    uint16_t UI16;
    struct {
        uint8_t LO;
        uint8_t HI;
    } UI8;
};


#endif	/* _TYPEDEF_H_ */

こんな感じの共用体を定義しますと、32bitの領域を16bitの上位下位、8bitで4分割してアクセスできるようになります。
image.png

確認方法

注意事項に書きましたとおり、環境依存がありますので真偽を確認します。
コードはこのような感じで、32bitで入力して、16bit,8bitで読み出します。

  printf("--------------------------------\r\n");
  printf("Progrum Start\r\n");
  printf("--------------------------------\r\n");
  uint32_u val;
  val.UI32 = 0x12345678;
  printf("UI8.HH : 0x%02X\r\n", val.UI8.HH);
  printf("UI8.HL : 0x%02X\r\n", val.UI8.HL);
  printf("UI8.LH : 0x%02X\r\n", val.UI8.LH);
  printf("UI8.LL : 0x%02X\r\n", val.UI8.LL);
  printf("UI16.HI: 0x%04X\r\n", val.UI16.HI);
  printf("UI16.LO: 0x%04X\r\n", val.UI16.LO);
  printf("UI32   : 0x%08X\r\n", val.UI32);

結果はこの通りになります。
image.png

さよならビットシフト

ということで共用体を利用した場合、このようなコードで書けますのでビットシフトも無くなり、上位下位どっちにアクセスしているのか見やすくなりますので、「私のことは嫌いになっても共用体のことは嫌いにならないでください」✋

void SetSpiData32(uint32_u val) {
    FPGA_SPI_Write(BaseAddress + 0x00, val.UI16.LO); // Set lower 16 bits
    FPGA_SPI_Write(BaseAddress + 0x01, val.UI16.HI); // Set upper 16 bits
}
4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?