8.パケット取得(タイマ2)


18bitのパケットを取得するルーチンを検討します。

8.1. RS232Cとの類似点 —調歩同期方式—

MMプロトコルは0と1のパルスが等間隔で出力されますが、これは一定のボーレートで通信するRS232Cと似た形式です。そこでRS232Cと同様なデータ取得法を考えてみます。前章のようにパルスの立ち上がりを検出し、パケットの先頭であれば、1/2周期だけ待ち、RA4(RXPIN)の状態を調べます。このときHであれば1、Lであれば0となります。次からは1周期ごとにRA4(RXPIN)の状態を17bit分調べればパケットを取得できることになります。


シリアルパッケトの受信


8.2. タイマ2を使った等間隔のタイミング発生

タイマ2を使うと一定周期で割り込み(TMR2IF)を発生させることができます。PR2レジスタとTMR2カウンタが一致すると割り込みが発生し、TMR2がクリアされます。したがって周期はタイマ2の条件とPR2の値で決ります。タイマ2はクロック8 MHz(タイマ2クロックは1/4になる)、プリスケーラ1/4の場合、1カウントが2 μsとなります。文献によれば、アクセサリデコーダの周期は104 μsなので、TMR2が52カウントで1周期になります。周期分に相当するカウント数は変数BAUDに入れることとし、PR2=BAUDを設定します。


8.3. 通信速度とタイミングの微調整

パケットの取得し始めは、なかなか忙しいです。

  立ち上がりの検知
  Lレベルの長さによるパケット取得の判定
  変数の初期化

という、もろもろの処理を行った後、1/2周期待ってRXPINの状態を調べる訳です。これらの処理には当然、ある程度の時間がかかるので、その分の時間をxとして、1/2BAUD – x だけ待ってRXPINの状態変化を調べるのがベターかと思われます。そこでxの値を決めるため、実際にxを振りながら、パケットが正常に受信できる範囲を調べてみました。その結果はxが3から25の範囲になりました。この測定結果は他の処理に47μsかかっていることを示しています。1/2周期の真ん中に合わせるため1/2BAUD – xが3μsとなるよう、xは22としました。

 一方、周期を表すパラメータBAUDは文献値によれば52のはずですが、この値では正常にパケットを受信することができませんでした。そこで、BAUDについても値を振って調べてみたところ、BAUD=49 ~ 51の範囲で正常に受信できることがわかりました。こちらは誤差が累積する性質のものですが、それにしては許容範囲が広いな、という印象です。この実験結果より、BAUD=50としました。

8.4. プログラミング

18bitのパケットをアドレス部のDataA、ファンクション部のDataF、データ部のDataDの三つに分けて受信するルーチンを考えます。タイマ2がオンの間もRXPINの状態変化はありますが、ここで割り込みが発生してしまうとややこしいことになるので、パケット受信中は状態変化割り込みを不許可とします。(IOCIE=0)また、逆になりますが、パケットを受信していない状態ではタイマ2を停止しています。

割り込み部

タイマ2割り込みが発生すると、BitCounterをステートとして、RXPINの状態に応じて下位ビットからデータを入力します。DataF部は2bitしかないのでループにはしませんでした。最後の18bit目(BitCounter:17)では次のパケット取得に向けて、タイマ1の準備を行います。

/*
*Interrupt by timer2
*Pulse duration is 100us, but 50us for the first pulse
*total:18bit consisting of 8bit(DetaA), 2bit(DetaF) and 8bit(DetaD)
*/
  if(TMR2IF){
    if(BitCounter == 0){ //the first bit?
      if(RXPIN) //if High, bit:1, Low, bit 0
        DataA |= BitPos; //Set Data
        BitPos = BitPos << 1; //Shift bit position
        BitCounter++; //Increment bit counter
        PR2 = BAUD; //change timer2 period to 1 pulse width
     }
     else{
       if((BitCounter < 8)&&(BitCounter >0)){ //for DetaA
         if(RXPIN) //if High, bit:1, Low, bit 0
           DataA |= BitPos; //Set Data
           BitPos = BitPos << 1; //Shift bit position
           BitCounter++; //Increment bit counter
         }
       else{
         if(BitCounter == 8){ //for DetaF, upper bit
            if(RXPIN) //if High, bit:1, Low, bit 0
              DataF |= 0x01; //Set Data
              BitCounter++; //Increment bit counter
            }
         else{
           if(BitCounter == 9){ //for DetaF, lower bit
             if(RXPIN) //if High, bit:1, Low, bit 0
               DataF |= 0x02; //Set Data
               BitPos = 0x01; //Set bit position to 1
               BitCounter++; //Increment bit counter
             }
           else{
             if((BitCounter > 9)&&(BitCounter < 17)){
             //for DataD
               if(RXPIN) //if High, bit:1, Low, bit 0
                 DataD |= BitPos; //Set Data
                 BitPos = BitPos << 1; //Shift bit position
                 BitCounter++; //Increment bit counter
               }
             else{
               if(BitCounter == 17){ //for DataD
                 if(RXPIN) //if High, bit:1, Low, bit 0
                   DataD |= BitPos; //Set Data
                   BitPos=BitPos << 1; //Shift bit position
                   BitCounter++; //Increment bit counter
                   TMR1H=0;//タイマ1の準備
                   TMR1L=0;//
                   TMR1ON=1;//タイマ1オン
                   IOCAF4=0;//フラグのクリア
                   IOCIE=1;//状態割り込み許可
                 }
              }
            }
          }
        }
      }
      TMR2IF=0; //timer2 interrupt flag clear
    }



関数Get_Packet()

18bitのパケットをDataA、DataF、DataDに分散して取得する関数。まずパラメータの初期化を行いますが、最初の周期としてPR2 = BAUD/2-14としているのは前節のとおり。タイマ2をオンにした後、BitCounterが18になるまで待機、割り込み処理によるパケット取得が完了したらタイマ2をオフにして戻ります。

void Get_Packet(void){
  BitCounter = 0; //total 18bit
  DataA = 0; //Upper 8bit
  DataF = 0; //Middle 2bit
  DataD = 0; //Lower 8bit
  BitPos = 0x01; //Position of Bit
  TMR2 = 0; //Initialize Timer2
  PR2 = BAUD/2-14; //A half of pulse width for the first bit
/*14引いているのは処理によるタイマ2タイミングのずれの補正用
*実験では3から25の間で正常にパケットを取得できたので中間の14とした*/
  T2CON=0x05; //Timer2:on, prescaler1/4
  /**wait here for interrupt by timer2*/
  while(BitCounter < 18); //until 18bit input
    TMR2ON = 0; //timer2 off
}




7.パケット取得開始タイミングの決定(タイマ1) TOP pageへ 9.アクセサリデコーダのアドレス       
inserted by FC2 system