テーブルデータの扱い方


【テーブルデータ】

多くの並んだ定数データを順番に取り出したい時にテーブル方式を使います。
(ルックアップテーブルとも呼ばれます。)
PIC18Fxxxxシリーズでは、テーブルアクセス用の専用命令が追加されましたから
こういう時には便利に扱えます。

【定数データの作成】

テーブルアクセスをする時には、まず定数データをテーブルとして並べたものを
プログラムメモリエリアに作成する必要があります。
この定数データをプログラムエリアに確保する方法には、下記のようにいくつかの
方法があります。

(1) RETLW命令として確保する方法
  これまでのPIC16Fシリーズの時と同じ方法で、RETLW kという命令で定数kを
  取り出せるようにする方法です。
  この場合には、「DT」という擬似命令を使います。

  《例》 DT擬似命令の展開内容例
        DT   0AAH, "ABC", '0', 0
        このアセンブル結果は
         0CAA 0C41 0C42 0C43 0C30 0C00
        となり、これは下記と同じ結果となります。
          RETLW   0XAA
          RETLW   'A'
          RETLW   'B'
          RETLW   'C'
          RETLW   '0'
          RETLW   0

(2) 1バイト毎のデータとして確保する方法
  PIC18シリーズでは、プログラムメモリが16ビットありますから、1バイトごとの
  データを2バイト分まとめて各ワードの中に格納することができ、効率良く格納
  できます。このように格納するためには、「DB」という擬似命令を使います。
   (逆にPIC16シリーズでDBを使うと上位2ビットが欠けたデータとなります。
    PIC16シリーズの場合にはDAという擬似命令を使い7ビット×2とします。)

  《例》 DB擬似命令の展開内容例
       (LabelのアドレスはFEDC番地とします)
       DB   0AAH, "ABC", '0', 0, 0F18H, Label
        このアセンブル結果は
         41AA  4342  0030  DC18
        となり、1ワードの中に、上位、下位の順に格納されています。
        これでバイトアドレス順に並んでいることになります。
        さらに奇数個のデータの場合は、自動的に最後のデータの上位に
        00のデータが追加されています。
        また2バイトデータや、ラベルのアドレスをデータとして確保しようと
        すると、下位バイトのみが確保され上位バイトは無視されます。

(3) ワードデータとして確保する方法
  バイト毎ではなく、1ワードに1バイトずつのデータを確保するときには、「DW
  という擬似命令を使います。ただし、文字列の場合には、DBと同じようにパック
  されて確保され、文字列データが奇数個のときには自動的に00が追加されます。

  《例》 DW擬似命令の展開内容例
        DW   0AAH, "ABC", '0', 0, 0F18H, Label
        このアセンブル結果は
         00AA  4241  0043  0030  0000  0F18  FEDC
        となり、文字列はパックされていますが、1文字やその他のデータは
        1ワード毎に、1個のデータが確保されていることが判ります。
        そしてこの場合には2バイトデータやアドレスも確保されています。

(4) ワードデータとして確保する方法 その2
  DWと同じように、数値データとASCII文字データは1ワードで1要素を格納し
  文字列の場合には、1ワードに2文字分を確保する方法がもう一つあります。
  「DATA」という擬似命令を使います。

  《例》 DATA擬似命令の展開内容例
        DATA   0AAH, "ABC", '0', 0, 0F18H, Label
        これのアセンブル結果は、
         00AA  4241  0043  0030  0000  0F18  FEDC
        となり、DWと全く同じになっています。


【アクセス方法】

次は用意された定数テーブルデータを順に取り出すプログラムです。
こちらには大別して2種類の方法があります。

(1) RETLW命令の場合
  これまでのPIC16シリーズと同じ方法で取り出す仕方です。ADD PCL命令を
  使います。
  この実際の例は下記のようになります。
  この例は、数値からセグメントデータに変換するサブルーチンになっています。

  この方法での注意は、PIC18Fシリーズではプログラムカウンタがバイト単位の
  アドレスカウンタになったことで、ADD  PCLの場合に加える数は2倍する必要
  があることです。つまり「RETLW  k」命令は1ワード命令なので、プログラムカウンタ
  が+2づつ進むため、加えるWレジスタの値も2倍する必要があるということです。
  さらに、2倍することで、演算結果でオーバーフローが起きないようにするためには
  最大サイズが128個になってしまいます。
  128個を超えると2倍したとき、ADD PCL,F命令でオーバーフローがおき、正しい
  位置にはジャンプせず、128ワードだけ小さいアドレスにジャンプしてしまいます。
  
  またもう一つ注意が必要です。PCLレジスタに書き込むと、プログラムカウンタの
  上位バイトも同時にPCLATH、PCLATUからコピーされて変更されます。
  しかし、PCLATH、PCLATUレジスタはPCLの読み込み動作をしないと、現在値を
  得ることはできず、00のままとなっています。そこで、現在のPCの値をPCLATH、
  PCLATUにコピーするためPCLの空読みが必要になります。これでこのサブルーチン
  がどこにあってもアドレスxx00さえ跨がなければ正常に動作します。






(2) テーブルアクセス命令の場合
  新たに追加されたテーブルアクセス関数を使う方法です。
  下記がその実際の例で、上記と同じ、数値からセグメントデータに変換する
  サブルーチンとなっています。
  
  この例ではDB擬似命令ですべて1バイトのデータをパックして1ワードに格納して
  います。
  そして、テーブルアクセスのポインタである、TBLPTRU、TBLPTRH、TBLPTRL
  にテーブルの先頭アドレスを代入するのですが、そのときには、
    UPEER、HIGH、LOW という擬似命令が便利に使えます。使い方は下記の
  ようにします。
  そしてこの3バイトのポインターに変数のWレジスタの内容を加算しますが、
  この場合にはバイト単位で扱いますから2倍する必要はありません。
  その代わり、TBLPTRの上位への桁上げもきちんと計算する必要があります。
  このテーブルアクセスを使えば、プログラムメモリ全部をテーブルにすることが
  可能になります。











  トップページへ