PICマイコン/テンプレート計画/common.inc

common.incで提供される機能の説明です。

目次

テーブルジャンプ

プログラムカウンタとRETLW命令を利用したテーブル機能を提供します。引数は変数のみです。

on_goto_U1  MACRO  varU1

このマクロ呼出しに続けてRETLW命令でテーブルを構成します。

例では、変数varの値(0〜3)によって'A' 'B' 'C' 'D'のいずれかを返すようになっています。

    on_goto_U1 var
    RETLW   'A'
    RETLW   'B'
    RETLW   'C'
    RETLW   'D'

0〜255までの値に対応、テーブル領域がxxFFhとxx00hの境を含む場合も考慮してます。

メモリクリア

指定のメモリブロックを任意の値で埋める機能を提供します。

memset_V1V1V1  MACRO  start, c, n

start番地からn個のメモリブロックを、値cで埋めます。ゼロクリアなどに利用できます。

下記の例では、0x20〜0x3fまでを0xffで埋めています。

    memset_V1V1V1  0x20, 0xff, 16

直アドレスではなく、ラベルでも構いません。

テンポラリ変数を使用しているので

        COMMON_functions

という記述をソースの最後に付けて、自動定義されるようにしておきます。

間接参照

PICのちょっと面倒なメモリ間接参照を簡単に使えるような機能を提供します。C言語のイメージとしては、「start[index] 」こんな感じです。

読出し系

先頭番地、加算値ともに定数の場合

W_read_ram_V1V1  MACRO  start, index

読み出し結果ははWレジスタに入ります。

U1_read_ram_V1V1  MACRO  varU1, start, index

読み出し結果はvarU1で指定する変数に入ります。

先頭番地が定数、加算値が変数の場合

idxU1に加算値が格納されている変数を指定します。

W_read_ram_V1U1  MACRO  start, idxU1

読み出し結果ははWレジスタに入ります。

U1_read_ram_V1U1  MACRO  varU1, start, idxU1

読み出し結果はvarU1で指定する変数に入ります。

書込み系

先頭番地、加算値、書込み値が定数の場合

write_ram_V1V1V1  MACRO  start, index, value

先頭番地が定数、加算値・書込み値が変数の場合

write_ram_V1U1U1  MACRO  start, idxU1, varU1

テーブルジャンプの例

  • リロケータブル形式となりますので、16f819.lkrファイルをプロジェクトに加える必要があります。
  • 簡単に記述するため、intr.incope.incを使っています。詳しくはそれぞれの使い方を参照してください。
  • ヘッダファイルはソースファイルの一つ上の階層に置かれているので、'../common.inc'のように相対パスで記述しています。
  • dec2hexというラベル部分でテーブルジャンプを使用しています。変数tempの値によって、'0'〜'F'までの16進数文字に変換する機能を作ってみました。
  • MPLABで_NOP_部分などにブレークポイントを置いて、正常に動作していることを確認してみてください。
  • dtマクロの他にdataマクロも使えます。
; Title       : common.inc test 1
; By          : komi
; Last update : 2007.04.21
; Version     : 0.1
;------------------------------------------------------------------
; use MPLAB IDE v7.52
;------------------------------------------------------------------
        PROCESSOR  PIC16F819
        INCLUDE    P16F819.INC

        __CONFIG   _CP_OFF & _DEBUG_ON & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO

        ERRORLEVEL -302             ; bank message 抑制
        ERRORLEVEL -312             ; page message 抑制

        RADIX      DEC              ; base 10

;------------------------------------------------------------------
#define CLOCK_FREQ 20000000
;------------------------------------------------------------------
        INCLUDE  "../common.inc"
        INCLUDE  "../intr.inc"
        INCLUDE  "../ope.inc"
        
#define _NOP_   NOP
;------------------------------------------------------------------
;                                                         変数定義
        UDATA
temp    RES     1

;------------------------------------------------------------------
;                                                   スタートコード
      START_VECTOR
;------------------------------------------------------------------
;                                                           メイン
      MAIN_ROUTINE
        
        move_U1V1   temp, 0
        
loop1:
        CALL    dec2hex
        
        _NOP_
        
        inc_U1    temp
        
        if_U1V1_goto   temp, _IsNotEqualTo_, 16, loop1
        
        
stop_loop:
        GOTO    stop_loop

dec2hex:
        on_goto_U1  temp
        dt      '0', '1', '2', '3', '4', '5', '6', '7'
        dt      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        
;------------------------------------------------------------------
;                                                     割り込み処理
  INTERRUPT_START
    SAVE_CONTEXT
    
    LOAD_CONTEXT
  INTERRUPT_END
;------------------------------------------------------------------
        END

メモリクリアの例

  • リロケータブル形式となりますので、16f819.lkrファイルをプロジェクトに加える必要があります。
  • 簡単に記述するため、intr.incope.incを使っています。詳しくはそれぞれの使い方を参照してください。
  • ヘッダファイルはソースファイルの一つ上の階層に置かれているので、'../common.inc'のように相対パスで記述しています。
  • 32バイトのメモリを確保してbufferというラベルを付けます。
  • 3回にわたってメモリクリアしてます。
  • 今回は0xA0から32バイト確保されましたので実行結果は下図のようになりました。
  • COMMON_functionsを最後に記述するのを忘れずに。
;------------------------------------------------------------------
;                                                         変数定義
        UDATA
buffer  RES     32 

;------------------------------------------------------------------
;                                                   スタートコード
      START_VECTOR
;------------------------------------------------------------------
;                                                           メイン
      MAIN_ROUTINE
        
        memset_V1V1V1   buffer, 0xff, 32
        _NOP_
        
        memset_V1V1V1   buffer, 0x55, 16
        _NOP_
        
        memset_V1V1V1   buffer, 0xaa, 8
        _NOP_
        
stop_loop:
        GOTO    stop_loop

        
;------------------------------------------------------------------
;                                                     割り込み処理
  INTERRUPT_START
    SAVE_CONTEXT
    
    LOAD_CONTEXT
  INTERRUPT_END
;------------------------------------------------------------------
;                                                           共用部
        COMMON_functions
;------------------------------------------------------------------
        END

間接参照の例

  • リロケータブル形式となりますので、16f819.lkrファイルをプロジェクトに加える必要があります。
  • 簡単に記述するため、intr.incope.incを使っています。詳しくはそれぞれの使い方を参照してください。
  • ヘッダファイルはソースファイルの一つ上の階層に置かれているので、'../common.inc'のように相対パスで記述しています。

本分でないトコロが多くなってますが・・・。

  1. buffer[0]〜[31]までに32から1までの値を入れる。(loop1)
  2. buffer[0]〜[31]を読み出して、それぞれ4倍(2ビットシフト)し格納しなおす。(loop2)

といった処理を行っています。C言語っぽいコメントを参考にしてみてください。

loop1が終わった時点。0x20(32)〜0x01(1)までが書き込まれています。

loop2が終わった結果。4倍になった値、0x40(80)〜0x04(4)までが書き込まれています。

;------------------------------------------------------------------
;                                                         変数定義
        UDATA
buffer  RES     32
cnt     RES     1
imm     RES     1

;------------------------------------------------------------------
;                                                   スタートコード
      START_VECTOR
;------------------------------------------------------------------
;                                                           メイン
      MAIN_ROUTINE
        
        move_U1V1  imm, 32          ; imm = 50;
        move_U1V1  cnt, 0           ; cnt = 0;
        
loop1:
                                    ; buffer[cnt] = imm;
        write_ram_V1U1U1  buffer, cnt, imm
        
        dec_U1     imm              ; imm--;
        inc_U1     cnt              ; cnt++;
        
                                    ; if (cnt < 32) goto loop1;
        if_U1V1_goto   cnt, _IsSmallerThan_, 32, loop1
        
        move_U1V1  cnt, 0           ; cnt = 0;
        
        _NOP_
loop2:
                                    ; imm = buffer[cnt];
        U1_read_ram_V1U1  imm, buffer, cnt
        
                                    ; imm <<= 2;
        lshift_U1  imm, 2;
        
                                    ; buffer[cnt] = imm;
        write_ram_V1U1U1  buffer, cnt, imm
        
        inc_U1     cnt              ; cnt++;
        
                                    ; if (cnt < 32) goto loop1;
        if_U1V1_goto   cnt, _IsSmallerThan_, 32, loop2
        
        _NOP_
stop_loop:
        GOTO    stop_loop

        
;------------------------------------------------------------------
;                                                     割り込み処理
  INTERRUPT_START
    SAVE_CONTEXT
    
    LOAD_CONTEXT
  INTERRUPT_END
;------------------------------------------------------------------
        END

2007-04-21 komina