micro:bit / マイコンの内部レジスタを操作する / 何かを書き込む / 2 つの端子から同じタイミングで反転パルスを出力する

今度は、反転したパルスを 2 つの端子から同時に出力してみる。
 
OUTSET レジスタと OUTCLR レジスタとを使えば、複数のビットを同時に H にすること、複数のビットを同時に L にすることができるが、複数のビットの一部だけを H に、一部だけを L に同時に設定することはできない。
 
OUT レジスタを使えば 32 ビットの全部を個別に H にも L にも設定できる。目的のビットだけを設定してそれ以外は変化させたくないときは、目的のビットだけ 1 にしたデータと OUT レジスタ との XOR を取ればよい。

int main(void){
    unsigned int BaseAddress = 0x50000000UL; // GPIO の各種レジスタのベースアドレス
    
    // OUT は全ビットの H 出力、L 出力を全部一度に設定するレジスタ
    // OUTSET は指定のビットだけを H に設定するレジスタ (指定していないビットは変化しない)
    // OUTCLR は指定のビットだけを L に設定するレジスタ (指定していないビットは変化しない)
    // DIRSET は指定のビットだけを出力に設定するレジスタ (指定していないビットは変化しない)
    volatile unsigned int *OUT    = (unsigned int *)(BaseAddress + 0x504);
    volatile unsigned int *OUTSET = (unsigned int *)(BaseAddress + 0x508);
    volatile unsigned int *OUTCLR = (unsigned int *)(BaseAddress + 0x50C);
    volatile unsigned int *DIRSET = (unsigned int *)(BaseAddress + 0x518);
    
    // エッジコネクターの P0 (GPIO_P03) と P1 (GPIO_P02) とを出力に設定する。
    unsigned int EdgeP0 = 1 << 3;
    unsigned int EdgeP1 = 1 << 2;
    unsigned int whichBits = EdgeP0 | EdgeP1;
    *DIRSET = whichBits;
    
    // 最初に P0 と P1 とのロジックを逆にしておく。
    *OUTSET = EdgeP0;
    *OUTCLR = EdgeP1;
    
    while(1){
        // ループを繰り返すたびに、OUT レジスタの特定のビット (エッジコネクターの P0、P1) だけを反転する。
        *OUT ^= whichBits;
    }
    return 0;
}

実行結果:
f:id:ti-nspire:20180522143608p:plain:w400
反転したパルスがまったく同じタイミングで出力されている。
この方法だと、1 回のループで 1 回だけオン、オフが切り換わるのでデューティーは 50% になる。
――――――――――――――――――――――――――――――――――――――――――――
f:id:ti-nspire:20180522150245p:plain:w500