ジョイスティックから得られるアナログ電圧をAD変換によりPICで取り扱うことのできることを基礎編で確認してもらいました.では,一連の動作をするプログラムを作成してみましょう.まず,今回作成するプログラムを動作させた様子を下の動画でご覧ください.ジョイスティックが動くたびにドットマトリクスディスプレイの表示が変わることを確認していただけると思います.

  1. 事前準備

    今回,ドットマトリクスディスプレイ付き距離センサボードを,メインマイコンボードが本来接続されるピンヘッダに接続します.まず電源を切った上で足が曲がらないことに留意しつつ,メインマイコンボードを取り外してください.一方向だけからしか力を入れないで取り外そうとすると,ピンヘッダが曲がってしまいます.次に,ドットマトリクスディスプレイ付き距離センサボードを下図の位置に取り付けてください.
    JoyStick03

    下図のようにコネクタが正しく刺さっていることを確認しましょう.
    JoyStick04

    次に,ジョイスティックをドットマトリクスディスプレイ付き距離センサボードで取り扱えるようにするため,ジャンパを変えます.下図のように「DIG」側に接続するようにしてください.なお,「ANA」に接続するのは,メインマイコンでジョイスティックを扱うときです.
    JoyStick05
  2. ADConverter.c


    ADConverter.cでは,ジョイスティックが接続されているAD変換器に関するプログラムを書きます.
    1. ADConverter_initialize関数

      この関数ではAD変換器を初期化します.下図に処理の流れを示します.
      ADConverter initialize
      最初に端子を入力端子にし,さらにアナログ入力端子にします.次に,変換時間を1[us]にするため,ADCSレジスタを変更します.ADCSはADCS0~ADSC2まであり,これらを使ってFosc/2~Fosc/64までの速度のクロックをADコンバータに供給します.その結果,変換時間を決められます.ここでは,ADCS2=1,ADCS1=0,ADCS0=0とすることで,1[us]の変換時間にすることができます.次に,AD変換器の電圧の最大および最小を設定します.PIC16F1936に備わるAD変換器には,変換するアナログ信号の上限をマイコンの動作電圧,下限をGND以外に設定することができるようになっています.ただし今回は,上限をマイコンの動作電圧,下限をGNDに設定することとします.最後に,変換結果が格納される位置を設定します.PIC16F1936のAD変換器の分解能は10ビットであり,1個のレジスタには変換結果が納まりきりません.このため,2個のレジスタ(ADRESHとADRESL)に結果が納められるようになっています.この格納の方法が2種類あり,ひとつは左詰,もうひとつが右詰です.下図に示すように,ADFMが0の場合には左詰となり,ADRESHの全部とADRESLの上位2ビットに結果が納められ,ADFMが1の場合には右詰となり,ADRESLの全部とADRESHの下位2ビットに結果が納められます.なお,灰色で示した箇所は不定値となります.
    2. ADConvertResult

    3. ADConverter_getDigitalValue関数

      この関数では,デジタル値に変換した結果を返します.まずは下図をご覧ください.
      ADConverter getDigitalValue
    4. 引数としてchannelが渡されますので,これをCHSレジスタに入れることで変換するチャネルを設定することができます.次にAD変換器を動作させるため,ADONレジスタを変更し,さらにAD変換を開始させるためGOレジスタを変更します.GOレジスタは変換が終了するとクリアされますので,それまで待ち続けます.最後にデジタル値のうち上位8ビットのみ返します.このようにすることで,下位の値は誤差として扱うこととし,下位2ビットは無視することにします.

  3. Joystick.c


    このファイルには,ジョイスティックに関する処理が書かれています.
    1. スタティックな変数および定数

      まずはじめに,水平および垂直方向の動きによる電圧変化を読み取るチャネルを_HORIZONTAL_CHANNELと_VERTICAL_CHANNELとして定義します.水平方向はチャネル2,垂直方向はチャネル3のAD変換器と接続されていますので,次のように定義しましょう.
      /* 水平方向の動きによる電圧変化を読み取るチャネル番号 */
      #define _HORIZONTAL_CHANNEL (2)
      
      /* 垂直方向の動きによる電圧変化を読み取るチャネル番号 */
      #define _VERTICAL_CHANNEL (3)
      


      スタティックな変数として,水平方向および垂直方向の値を保持する_horizontalと_verticalを宣言します.

      /* 水平方向の値 */
      static uint8_t _horizontal;
      /* 垂直方向の値 */
      static uint8_t _vertical;
    2. Joystick_initialize関数

      この関数では,ジョイスティックの初期化を行います.下図をご覧ください.
      Joystick initialize
      まず,ADコンバータの初期化を行うため,ADConverter_initialize関数を呼び出します.そして,水平および垂直方向の値を初期化しておきます.

    3. Joystick_getHorizontalValue関数

      この関数は,_horizontal変数をJoystick.c外から参照することができるようにするために設けられています._horizontal変数はスタティックであるため,Joystick.c外からは直接参照できません.もちろん,externにしてしまえばどこからでもアクセスできることは知っていますが,あえてこのような作りにしているのです.なぜなら,こうすることで_horizontalを書き換えたり参照したりするスコープを減らすことができ,プログラムの管理が容易になるからです.
      Joystick getHorizontalValue

    4. Joystick_getVerticalValue関数

      この関数は,Joystick_getHorizontalValue関数と同様に,_vertical変数をJoystick.c外から参照することができるようにするために設けられています.
      Joystick getVerticalValue

    5. Joystick_measure関数

      この関数では,AD変換器を使って得られるジョイスティックの位置を_horizontalと_verticalに入れます.下図のように,各チャネル番号は_HORIZONTAL_CHANNELと_VERTICAL_CHANNELとになっておりますので,これをADConverter_getDigitalValue関数に渡してデジタル値を得て,_horizontalおよび_verticalに代入してください.
      Joystick measure

  4. Main.c

    メイン関数では,ドットマトリクスディスプレイの初期化を行った後,下図の処理を行います.
    mainまず,ジョイスティックの初期化を行った後,while文による無限ループを作ります.このループ内でローカル変数hとvを宣言し,ジョイスティックの位置を計測します.ジョイスティックの位置の計測結果は水平方向,垂直方向それぞれ0~255までの値を取り得ますが,ドットマトリクスディスプレイには6桁もの数字を表示する能力がありません.そこで,水平および垂直方向の結果を0~7に正規化します.こうすれば,一度に両方の結果が表示できます.0~255を0~7に正規化するには32で割ればよいですが,除算はマイコンにとって処理時間のかかるものです.そこで,5ビット右シフトすることにします.その後,ドットマトリクスディスプレイを一旦消し,表示する値を設定し,最後に表示させます.表示する方法は,十の位に垂直方向,一の位に水平方向とします.