DCDCコン開発(52) バグ解析について

プログラムのバグは、直ってしまえばそれでハッピーなのだが、バグによる現象を解析しておくと、次回に似たような現象に出会ったときにその原因の特定に役立つというメリットがある。余裕のあるときには、きちんと検証しておくと、スキルアップにつながるはず。

ということで、連休で、しかも台風直撃でどこにも出かけられないので、解析してみよう。

//****************************************
// TMR1×4(262ms毎)処理
// LED表示切替(262ms毎) 4秒サイクル
// MPPTターゲット電圧再設定(2分毎:262ms×16×28)
// 正常状態:●●●●○○○○・・・・(後半はモードを表す)
// 異常状態:●○●○●○●○・・・・(後半はモードを表す)
// 特殊状態:●●○○●●○○・・・・(後半はモードを表す)
void disp_and_mppt_reset( void ){
      static unsigned char led_count;                                        // LED表示切替カウンタ
      WPUA3 = (led_led>>led_count)&&(0b01);                     // led_count番目のビットが1:点灯、0:消灯
      led_count++;                                                                  // カウントインクリメント
      if(!(led_count-LED_DISP_CYCLE)) {                             // 約4sサイクル
           led_count = 0;                                                           // カウンタクリア
      }
}
上記で、led_ledという変数には、例えば”0101010101010101″という2進数が設定されているとする。それぞれのビットが1のところでLEDが点灯、0のと頃でLEDが消灯するように動作させたい。

led_countは、この関数が呼ばれる毎に+1ずつされる。これは、led_ledのビットを選択する働きをもつ。

led_count の値は、led_led のビット位置を以下のように指し示す。
led_count     15  14 13 12  11 10    9    8    7    6    5    4    3    2    1    0
led_led           0    1    0    1    0    1    0    1    0    1    0    1    0    1    0    1

例えば、led_count=4の場合は、led_ledの右端から5番目のビットを指し示す。

これが、”0″か”1″かを判断する。

正しい文 (led_led>>led_count)&(0b01) の動作は、以下のようになる。

led_led を led_count分右にシフトする。シフトとは、1ビットずつ右にずらして、左からは0で埋めることである。led_count=3だと、以下のようになる
0101010101010101        右シフト3ビット      00000101010101010
                                                                     ^^^ この部分が左から埋められた

これを1とビット演算「&」(アンド)する。同じ位置のビットがともに”1″の場合は”1″、どちらかが”0″の場合は”0″となる。例の場合は、以下のようになり、結果は”1″となる。
led_led             0000101010101010
0b01                 0000000000000001
                                                    ^ 片方が”0″なので「&」の結果は”0“となる。

こうして、led_ledのビットを一つずつ右にずらしながら1、0を確認し、一番左まで来たら、次は一番右に戻り、繰返す。

さて、これが、「&&」の場合はどういう動作になるか。

「&&」は、論理和といって、二つの変数(ビットではなく、全体)がともに”0″以外のときに”1″となり、その他は”0″となる。上記の場合は、以下のようになる。
led_led             0000101010101010      0でない
0b01                 0000000000000001      0でない
                                                         よって「&&」の結果は”1“となる。

「&」と「&&」では、異なった結果となる。

今回のおかしな現象としては、本来はチカチカと点滅して欲しいのに、ずっと点灯しっぱなしというもの。上記の結果を考えれば、ほとんどの場合で、”1″となり、点灯する事になるという現象が理解できる。

でも、たまに、消灯する場合もあった。

led_led の値は、以下のようにいくつかのパタンがあった。
STOP                                  0000001100001111                          // 入力電圧不足休止中(duty=0)
STANDBY                          0101010100001111                          // 電力供給可能(負荷がない状態)(duty=0)
MPPT                                  0001000100001111                          // PV最大電力点追従モード
RECOVERY_WAIT             0000111100001111                          // PWM停止後に出力電圧低下待
CALIBRATION                   0011001100110011                          // キャリブレーション
ERR_VIN_OVER                0001001101010101                         // 入力電圧上限オーバー(緊急停止)
ERR_VCTL_OVER             0010001101010101                         // 制御電圧上限オーバー(緊急停止)
ERR_VOUT_DANGER       0100001101010101                         // 出力電圧上限オーバー(緊急停止)
ERR_INVALID_INT            0101010101010101                         // 割込み異常

この中で、例えば以下のように、左側に”0″が複数連続している場合、10ビットシフトした以降は”0″となるため、「&&」の結果”0″となる。
0000001100001111

10ビット分シフトするまでは点灯、11~15ビット分は消灯という動作となる。

なるほど。まさに、現象に現れたとおりとなる。当り前なんだけど。

ということで、今回のバグにより現れた現象が、このミスによるものであることが特定できた。

T.Yさん、M.Sさん、N.Uさん、他4人が「いいね!」と言っています。

<前へ>                   <次へ>

タイトルとURLをコピーしました