楽天市場
[無料でホームページを作成] [通報・削除依頼]

PIC_WAIT

拡張ミッドレンジコアのPICでは、CALLW命令が追加され相対アドレスへのサブルーチンコールが可能となったので、CALLW命令を用いた任意サイクルのWAIT方法を考案してみた。
(2013.11.21 全面改訂)

<考え方の基本>

1. WAITの引数はFレジスタで渡す。(以下の例ではDH,DM,DLを使用)

2. 最小範囲 (~255サイクルまで) のWAITにはCALLW命令を使用する。

3. プログラムメモリを多少使用してでも、できるだけ少ないサイクル遅延で、広範囲かつ任意サイクルのWAITを実現する。


< 255サイクルまでのWAIT>

255サイクルまでのWAITにはCALLW命令を使用する。

メインルーチン中の記述。
       ・
       ・
  MOVF    DL,W
  MOVLP  0x05    ← PCLATH=0x05(テーブルの先頭位置により値が変わる)
  CALLW
       ・
       ・

として、下記テーブルを参照する。

注意点1 WAITの値に関わらず上記構文で6サイクル遅延する。
(PCLATHが予め固定できれば5サイクルの遅延にできる。)

注意点2 DLにはWAIT値の1の補数をセットする。
DL=0x00 の時に最大WAIT 6(MOVF,MOVLP,CALLW,RETURN)+255(NOP)=261サイクル
DL=0xff の時に最小WAIT 6(MOVF,MOVLP,CALLW,RETURN)=6サイクル


テーブルの構成例: 0x500~0x05fe までNOP、0x05ffのみRETURN

        ORG    0x0500
;
W255 NOP
W254 NOP
W253 NOP
W252 NOP
W251 NOP
W250 NOP
W249 NOP
W248 NOP
W247 NOP
W246 NOP
W245 NOP
W244 NOP
W243 NOP



W006 NOP
W005 NOP
W004 NOP
W003 NOP
W002 NOP
W001 NOP
W000 RETURN



<256~65280(=255*256)サイクルまでのWAIT>

256~65280サイクルまでのWAITにはサブルーチンを使用する。

メインルーチン中の記述。
              ・
              ・
            INCFSZ    DM,W
            CALL       W256
              ・
              ・

W256     ADDLW    0x01
             BTFSC     STATUS,Z
             GOTO      W249            ← RETURN命令はジャンプ先のテーブルの最後に存在。
             MOVWF    REG0           ← ユーザーがレジスタを定義
             CALL       W249
             INCFSZ     REG0,F
             GOTO       $-2
             NOP
             GOTO       W247           ← RETURN命令はジャンプ先のテーブルの最後に存在。

注意点1 WAITの値に関わらず上記構文で2サイクル遅延する。

注意点2 DMにはWAITの値の1の補数をセットする。
DM=0x00 の時に最大WAIT 255*256+2=65282サイクル
DM=0xff の時に最小WAIT 0*256+2=2サイクル

注意点3 サブルーチン中のラベルW249とW247の位置は先のテーブル中に記してある。

注意点4 サブルーチン中のサブルーチンコールでPCLATHの設定が不要となるようにテーブルは0x800未満に配置しておく。

WAITの計算
1. DM = 0xff のとき、
INCFSZ命令で+1されてW=0となりスキップ。
総サイクルは2(INCFSZ,SKIP)

2. DM = 0xfe のとき、
INCFSZ命令で+1されてW=0xffとなりW256をコール、ここまで3サイクル (INCFSZ,CALL)
W256で+1されてW=0となりW249にジャンプ、
テーブルの最後のRETURNでサブルーチンから復帰。
総サイクルは3+4(ADDLW,BTFSC,GOTO)+249(NOP)+2(RETURN)=258=256+2

3. DM = 0xfd のとき、
INCFSZ命令で+1されてW=0xfeとなりW256をコール、ここまで3サイクル (INCFSZ,CALL)
W256中で+1されてW=0xffとなりGOTO命令をスキップ、ここまで7サイクル 3+3(ADDLW,BTFSC,SKIP)=6
WをREG0に保存し、W249をコールした後、ループを抜けてW247にジャンプ、テーブルの最後のRETURNでサブルーチンから復帰。
総サイクルは6+12(MOVWF,CALL,RETURN,INCFSZ,SKIP,GOTO,RETURN,NOP)+249(NOP)+247(NOP)=514=2*256+2

4. DM < 0xfd のとき、
ループ中のサイクルは、4(CALL,RETURN)+249(NOP)+1(INCFSZ)+2(GOTO)=256
であるからDMが1つ減るごとにWAITは256サイクル加算される。



<65536~16711680(=255*65536)サイクルまでのWAIT>

65536~16711680サイクルまでのWAITにもサブルーチンを使用する。

メインルーチン中の記述。
                  ・
                  ・
              INCFSZ    DH,W
              CALL       W65536
                  ・
                  ・

W65536   ADDLW    0x01
              BTFSC     STATUS,Z
              GOTO      W65529
              MOVWF    REG1         ← ユーザーがレジスタを定義
              CALL       W65529
              INCFSZ    REG1,F
              GOTO      $-2
              NOP                           ;[1]
W65529   MOVLW    0x01           ;[1]
              CALL        W256          ;[65281]=2+254x256+255=255x256+1
              GOTO       W245          ;[249]=2+245+2

1. DH = 0xfe のとき、
INCFSZ命令で+1されてW=0xffとなりW65536をコール、ここまで3サイクル (INCFSZ,CALL)
W65536で+1されてW=0となりW65528にジャンプ、
テーブルの最後のRETURNでサブルーチンから復帰。
総サイクルは3+4(ADDLW,BTFSC,GOTO)+65529+2(RETURN)=65538=65536+2

2. DH = 0xfd のとき、
INCFSZ命令で+1されてW=0xfeとなりWDHをコール、ここまで3サイクル (INCFSZ,CALL)
W65536中で+1されてW=0xffとなりGOTO命令をスキップ、ここまで6サイクル 3+3(ADDLW,BTFSC,SKIP)=6
WをREG1に保存し、W65529をコールした後ループを抜ける。
ここまで65543サイクル 6+8(MOVWF,CALL,RETURN,INCFSZ,SKIP,NOP)+65529=65543
最後にW244にジャンプ、テーブルの最後のRETURNでサブルーチンから復帰。
総サイクルは65543+65529+2(RETURN)=131074=2*65536+2

4. DH < 0xfd のとき、
ループ中のサイクルは、4(CALL,RETURN)+65529+1(INCFSZ)+2(GOTO)=65536
であるからDHが1つ減るごとにWAITは65536サイクル加算される。

<使用例1>

10から16777215(=256*256*256-1)までの任意のサイクルのWAITを作る。

[前提条件]
WAITのサイクル数はDH,DM,DLの3つのレジスタに格納されている。(1の補数ではない)
DH,DM,DLは上書きされてもかまわない。

1. DH,DM,DLの値を補正した後、1の補数を作る
WAIT処理に関わる遅延サイクル (6+2+2=10 サイクル) を補正
       ・
       ・
    MOVLW    0x0A    ← 10 (補正値)
    SUBWF     DL,F
    CLRW
    SUBWFB   DM,F
    SUBWFB   DH,F
    COMF       DL,F    ← DL=/DL
    COMF       DM,F   ← DM=/DM
    COMF       DH,F    ← DH=/DH


2. ウェイトの実施
        ・
        ・
    MOVF       DL,W
    MOVLP     0x05
    CALLW
    INCFSZ     DM,W
    CALL        W256
    INCFSZ     DH,W
    CALL        W65536



<使用例2>

8から65535(=256*256-1)までの任意のサイクルのWAITを作る。

[前提条件]
WAITのサイクル数はDM,DLの2つのレジスタに格納されている。(1の補数ではない)
DM,DLは上書きされてもかまわない。

1. DM,DLの値を補正した後、1の補数を作る
WAIT処理に関わる遅延サイクル (6+2=8 サイクル) を補正
       ・
       ・
   MOVLW    0x08    ← 8 (補正値)
   SUBWF     DL,F
   CLRW
   SUBWFB   DM,F
   COMF       DL,F   ← DL=/DL
   COMF       DM,F   ← DM=/DM


2. ウェイトの実施
       ・
       ・
   MOVF      DL,W
   MOVLP    0x05
   CALLW
   INCFSZ    DM,W
   CALL       W256



<使用例3>

6から255までの任意のサイクルのWAITを作る

[前提条件]
WAITのサイクル数はDLレジスタに格納されている。(1の補数ではない)
DLは上書きされてもかまわない。

1. DLの値を補正した後、1の補数を作る
WAIT処理に関わる遅延サイクル (6 サイクル) を補正
       ・
       ・
   MOVLW    0x06    ← 6 (補正値)
   SUBWF     DL,F
   COMF       DL,F    ← DL=/DL


2. ウェイトの実施
       ・
       ・
   MOVF      DL,W
   MOVLP    0x05
   CALLW



<使用例4>

9から16777216(=256*256*256)サイクルまでの任意の幅のワンショットパルスを作る

[前提条件]
WAITのサイクル数はDH,DM,DLの3つのレジスタに格納されている。(1の補数ではない)
DH,DM,DLは上書きされてもかまわない。

PORTAの0ビットが事前に出力ポートとして設定されている。

1. DH,DM,DLの値を補正した後、1の補数を作る
WAIT処理に関わる遅延サイクル (4+2+2= 8サイクル) を補正
          ・
          ・
     MOVLW    0x08     ← 8 (補正値)
     SUBWF     DL,F
     CLRW
     SUBWFB   DM,F
     SUBWFB   DH,F
     COMF       DL,F     ← DL=/DL
     COMF       DM,F     ← DM=/DM
     COMF       DH,F     ← DH=/DH


2. パルスの生成
         ・
         ・
     BCF        PORTA,0   ← PORTA,0をLowレベルにしておく
         ・
         ・
     MOVLP    0x05         ← ポート変化の前に設定、遅延-1
     MOVF      DL,W         ← ポート変化の前に設定、遅延-1
     BSF         PORTA,0   ← PORTA,0をHigh レベルにする
     CALLW
     INCFSZ    DM,W
     CALL       W256
     INCFSZ    DH,W
     CALL       W65536
     BCF         PORTA,0   ← PORTA,0をLowレベルにする

注意点 WAITの最小サイクルは8であるが、ポート出力変化が1サイクルあるため、パルス幅の最小サイクルは9となる。最大サイクルも1増える。





<使用例5>

6から33554432(=2*256*256*256)サイクルまでの任意の周期の発振器。

[前提条件]
WAITのサイクル数はDH,DM,DLの3つのレジスタに格納されている。(1の補数ではない)
DH,DM,DLは上書きされてもかまわない。 (DH ・DM ・DL > 0x000002)

PORTAの0ビットが事前に出力ポートとして設定されている。



           MOVF    DM,W
           IORWF   DH,W
           BTFSS   STATUS,Z
           GOTO    OCH
           MOVF    DL,W
           SUBLW   0x0B
           BTFSS   STATUS,C
           GOTO    OCH
           BRW
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLPL
           GOTO    OLP4
;
OLP3   INCF      PORTA,F
           GOTO    $-1
;
OLP4   INCF      PORTA,F
           NOP
           GOTO    $-2
;
OLPL   INCF     PORTA,F
           BRW
           NOP
           NOP
           NOP
           NOP
           NOP
           NOP
           GOTO    $-8
;
OCH    MOVLW  0x0C
           SUBWF   DL,F
           CLRW
           SUBWFB DM,F
           SUBWFB DH,F
           COMF     DL,F
           COMF     DM,F
           COMF     DH,F
           MOVLP   0x05

OLPH  INCF       PORTA,F
           MOVF     DL,W
           CALLW
           INCFSZ   DM,W
           CALL      W256
           INCFSZ   DH,W
           CALL      W65536
           GOTO     $-7