電子工作@shukukei
現在 5 人がオンライン
総合: 1508
今日: 1 ,昨日: 2
管理人に連絡する

利用規約はトップページに記述

電子回路

  • モータードライバ基板
  • 電源回路基板
  • 信号制御基板
    1. プレステコン基板


Suzuka-OS



小ネタプログラム



その他




開発記録(メモ書き)



開発環境

  • パソコン
    1. MacBook
  • ライター
    1. AKI-PIC2
  • マイコン
    1. PIC12F683
    2. PIC16F88
    3. PIC16F887
  • ソフトウェア
    1. EAGLE
    2. HI-TECH C Compiler

開発記録->独自シリアル通信->3回読み取って平均を取る

開発記録->独自シリアル通信->3回読み取って平均を取る




  • 外乱の影響を少しでも軽減するため、三回読み取って平均を取ることとする。

実際の処理は以下の二通り。
three_read_bit = (D1 + D2 + D3) >> 1;
three_read_byte = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
になることを説明する。




一回目(D1):1110
二回目(D2):0110
三回目(D3):1101

結果(Ans):1110とする。

手法としては、
D1の0bit目 + D2の0bit目 + D3の0bit目の結果が0〜1ならば0、2〜3ならば1となる。

つまり、

0 + 0 + 0 = 0 → 0
0 + 0 + 1 = 1 → 0
0 + 1 + 0 = 0 → 0
0 + 1 + 1 = 2 → 1
1 + 0 + 0 = 1 → 0
1 + 0 + 1 = 2 → 1
1 + 1 + 0 = 2 → 1
1 + 1 + 1 = 3 → 1

となることより明らかである。
(入力に1が二回あれば1、0が二回あれば0だから)

これをC言語で表現してみる。

unsigned char ans;
switch ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) {
case 0:
case 1:
ans &= 0xE; // B'1110'
break;
case 2:
case 3:
ans |= 0x1; // B'0001'
break;
default:
}

switch ( ((D1>>1)&1) + ((D2>>1)&1) + ((D3>>1)&1) ) {
case 0:
case 1:
ans &= 0xD; // B'1101'
break;
case 2:
case 3:
ans |= 0x2; // B'0010'
break;
default:
}

switch ( ((D1>>2)&1) + ((D2>>2)&1) + ((D3>>2)&1) ) {
case 0:
case 1:
ans &= 0xB; // B'1011'
break;
case 2:
case 3:
ans |= 0x4; // B'0100'
break;
default:
}

switch ( ((D1>>3)&1) + ((D2>>3)&1) + ((D3>>3)&1) ) {
case 0:
case 1:
ans &= 0x7; // B'0111'
break;
case 2:
case 3:
ans |= 0x8; // B'1000'
break;
default:
}

これをちょっとだけ最適化してみる。


(D1の0bit目 + D2の0bit目 + D3の0bit目) / 2 = Ansの0bit目

となる。

これは、
0 / 2 = 0
1 / 2 = 0.5
2 / 2 = 1
3 / 2 = 1.5
となるが、整数型であるので、小数点は切り捨てられるため、
0 / 2 = 0
1 / 2 = 0
2 / 2 = 1
3 / 2 = 1
となることより明らかである。

unsigned char ans;
if ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) / 2 == 1){
ans |= 0x1;
}


ここで、÷2の動作を「1bit右シフト」に置き換える。

unsigned char ans;
if ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) >> 1 == 1){
ans |= 0x1;
}

ただし、この手法は1bitずつしか出来ないので8bit分実行すると遅くなってしまう。

一気に8bit分を実現する方法は。

まず、三回分の入力信号を次の様に仮定する

D1:1110
D2:0110
D3:1101

これで、一回目と二回目を比較してみると。
2bit目〜0bit目は一致している。
つまり、2/3を獲得しているので、これは確定。

3bit目だけが不定となる。

つまりD1とD2を比較した結果、
ANS:x110
であることが確定する。

ここで、xは不確定、つまり1と0がそれぞれ一回ずつ存在しているので。
三回目が1ならば1であるし、0ならば0になる。

と、言う事は。

三回目の結果の3bit目で上書きすれば良い。


ANDとORとXORを使って説明すると。

D1:1110
D2:0110
D3:1101

ANS:1110

D1とD2の差異を抽出→XORする

1110 XOR 0110 = 1000

論理を反転→NOTする→XORする

1000 XOR 1111 = 0111

D1とD2で一致していなかった部分を0にする→さきほどの結果とANDする

1110 AND 0111 = 0110

これで、x110が得られた(x=0にする)ことになる。

D3からD1とD2で未確定だった部分を抽出する→最初の結果とANDする

1101 AND 1000 = 1000

最後に、抽出した結果で3bit目を上書きする→ORする

0110 OR 1000 = 1110

というわけで、ANS:1110と一致しました。
この演算を式に纏めると。

X = D1 XOR D2
X = X XOR 0xFF (Xをビット反転する)
Y = D1 AND X
Z = X AND D3
ANS = Y IOR Z

となります。

ここで、D1,D2,D3,ANSの真理値表を作成すると。
真理値表
D1 D2 D3 ANS
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1

となるので。

次に、
f = (Aバー)・B・C + A・(Bバー)・C + A・B・(Cバー) + A・B・C
※D1=A、D2=B、D3=C、ANS=fとした。
を元に、カルノー図を書いて最適化すると。

カルノー図
A/BC 00 01 11 10
0 1
1 1 1 1

よって、
f = A・B・C + A・B + A・C

となることより、
ANS = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
が導かれる。

また、
ANS = (D2 & D3) | (D1 & D2) | (D1 & D3);
でも実現可能である。