舞鶴技術研究会ホームページへ
2002年6月25日


1チップマイコンPICの勉強会
〜アーキテクチャの理解からロボットランサーの設計製作まで〜
by 舞鶴技術研究会 情報システム部門「ものづくりプロジェクト:PIC&AVRによる1チップマイコン応用技術」

第2回:PICのアーキテクチャとプログラミング

情報システム分科会幹事 舞鶴工業高等専門学校 電子制御工学科 町田秀和
連絡先 E-mail machida@maizuru-ct.ac.jp 電話 0773-62-8957
 assisted by the 舞鶴工業高等専門学校 電子制御研究会同好会

テキスト CQ出版社、トランジスタ技術別冊、ECB No.4 PICマイコンを使おう



目次



本文

  1. はじめに(1回目)
  2. ワン・ボード・マイコン(1回目)
     2.1 ワン・ボード・マイコン(1回目)
     2.2 原始的なワンチップ・マイコン(1回目)
     2.3 最近のワンチップ・マイコン(1回目)
  3. ロボットランサー(1回目)
  4. PICのアーキテクチャ
    1. ワンチップマイコンとは
      PICはワンチップマイコンの一品種であり、ワンチップマイコンとは、
      • プログラムを入れておく=メモリ
      • プログラムを実行する=CPU
      • 外部機器を制御する=インターフェース
      これらの3つが1つに集約されているもの=ICです。

      PIC16F84の概観と、そのピン配置は下図のとおりです。
      実際の回路図については、後ほど述べます。


       PICのプログラミングの勉強をするには、まずそのアーキテクチャ(構造)を よく理解することが必要です。 PICのアーキテクチャについては、テキスト17ページ図2-2をご覧ください。

       ここでは、データバスだけに関連したアーキテクチャを図1に示します。


    2. レジスタ
       レジスタとは計算結果などを一時的に記憶させておくためのデータの入れ物  なんです。  レジスタのほうが簡単に出し入れできる。
      4種類のレジスタ(PICにおいて)
      • 自分で任意に決められる=ファイルレジスタ(128個存在が2バンク、それぞれが8ビット)
        • マイコンの周辺機能を利用する為=特殊レジスタ(00h〜0Bhおよび80h〜8Bh)
        • マイコンの状態を示す為=ステータスレジスタ(03h)
      • 計算専用に使われる=Wレジスタ(1つのみ存在)

      PICを攻略するためには、下の図2のファイルレジスタおよび 図3のステータスレジスタの理解が避けてとおれない。
      • 2バンク構成(第0バンク=00h〜7Fh、第1バンク80h〜FFh)
      • 特殊レジスタ(00h〜0Bhおよび80h〜8Bh)
      • ユーザメモリ(0Ch〜FFhは8C〜FFhと同じイメージ)、
        (16F84では50h〜FFhは未実装、すなわち68バイト利用できる)



      ちなみに、プログラム・メモリのデータはデータバスには出てきません。
      プログラムメモリのアドレス幅は13bit(8kワード)であり、データ(命令長)は14bitです。


  5. PICのプログラミング

    1. 命令
         PICの命令は、テキストp.36,37の表3-1のとおりの35個しかありません。
      [全命令の一覧などを付録に示します。]
      かなり特殊な命令もありますが、基本はデータの扱いと分岐、ステータスフラグ関連の 操作です。それ以外ではビット操作命令が強力ですので、ビットフラグを多用する プログラムとするとパフォーマンスが上がります。

       命令の種類 例
         @命令だけ NOP
         A1オペランド命令 MOVLW K 定数
         B2オペランド命令 ADDF f,d


      はじめての例題:たし算するプログラム 10+5→15
      (最初の10行は他のプログラムでもそのまま再利用できる。)
      ;	file name = add.asm	an example of the addition 
      
      	list p=16f84
      
      #include "p16f84.inc"
      
      	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
      
      	RADIX	DEC
      
      TEMP	EQU	20H	;20H番地に、TEMPというラベルをつける
      
      	ORG	00H	;00H番地からプログラムをはじめる。
      	
      	MOVLW	10	;Wレジスタ←10
      	MOVWF	TENP	;TEMP←Wレジスタのデータを入れる
      	MOVLW	5	;Wレジスタ←5
      	ADDWF	TEMP,0	;Wレジスタ←TEMP+Wレジスタ(0ならば、Wレジスタに演算結果を収納する。
                              ;			  1ならば、ファイルレジスタに演算結果を収納する。) 
      	
      	END
      

      MOVLW	k	k(定数)をWレジスタに格納する
      MOVWF	f	f(ファイルレジスタ)にWレジスタのデータを格納する
      ADDWF	f,d	f(ファイルレジスタ)とWレジスタを足し合わせてdが
      		示す場所(0ならばWレジスタへ、1ならばファイルレジスタへ)
      		に演算結果を格納する。
      
      注1)数値を直接入力できるのはWレジスタのみ
      注2)ファイルレジスタに代入するにはWレジスタに一度入力してからのみ
      注3)ADDWF TEMP,0 の0のときはWレジスタに、1のときはファイルレジスタに代入される
      

      このプログラムの動作イメージは下図のとおりです。



    2. アセンブラMPLABの使い方

      PICのプログラミング言語としては、C言語も利用できますが、本勉強会では 純正のアセンブラシステムである MPLABを使います。
       MPLABはメーカ・ホームページ (http://www.microchip.com/) から最新版がダウンロードできますが、本勉強会では トランジスタ技術誌2000年7月号に付録のCD-ROMに収録されているMPLAB 5.00を インストールして使います。

      1. アセンブラとは
        アセンブリ言語  → 例 MOVLW 10  このような文字はPICマイコンには理解できない。
          ↓
        そこで、アセンブラで機械語(01の列)に変換し、PICマイコンで実現可能にする。

        アセンブリ言語と機械語は1対1に対応しており、詳細な記述が可能です。


      2. MPLAB起動
           スタート→プログラム→Microchip MPLAB→MPLAB

        適当なドライブに作業名のディレクトリを作成する。ただし、MPLABは日本語を 解釈できないので、ローマ字を推奨する。 コメントでもMPLAB内では日本語を打ち込むことはできない。 外部からコピペはでける。


      3. プロジェクトの定義
        project→ New project

          Directories: 作業用ディレクトリ
          File Name:   add
        
        Edit project ダイアログボックスで

         Project
           Target Filename  add.hex
           ....
         
         Project Filesの
          Add Node.. ボタンを押し、
          add.asmを加える。
          
         OKボタンを押す。
        

      4. エディタの起動
        Ctrl-N (File→New)を押し、エディット・ウィンドウを開く。
        プログラムリストを打ち込む。
      5. アセンブル
        project→ Make project (F10)

        save as ダイアログボックスで、 add.asm と入力すると
        Building ADD.HEX...
        
        Compiling ADD.ASM:
        Command line: "C:\PROGRA~1\MPLAB\MPASMWIN.EXE /p16F84 /q C:\MPLAB\ADD.ASM"
        Warning[205] C:\MPLAB\ADD.ASM 1 : Found directive in column 1. (list)
        Error[113]   C:\MPLAB\ADD.ASM 13 : Symbol not previously defined (EMP)
        
        MPLAB is unable to find output file "ADD.HEX".
        
        Build failed.
        
        13行目の TENPをTEMPに変更し、もう一度コンパイルする。
        Building ADD.HEX...
        
        Compiling ADD.ASM:
        Command line: "C:\PROGRA~1\MPLAB\MPASMWIN.EXE /p16F84 /q C:\MPLAB\ADD.ASM"
        Warning[205] C:\MPLAB\ADD.ASM 1 : Found directive in column 1. (list)
        
        Build completed successfully.
        

      6. シミュレータ:一番重要

        ここで(MPLABの一回目の起動時のみ)、次のようにMPLABのモードを更新し、シミュレート可能にしておく。
        Project→Edit projectで、以下のように指定する。
          changeで、Tools→MPLAB simulator
                       processor = 16f84
                       clock  HS  10
        


        確認用のウィンドウを表示する。
         Window→Program Memory :アセンブル結果のリスト
         Window→File Register Window:ファイルレジスタを表示する
         Window→Special Function Register:特殊機能レジスタ(ステータスフラグ等)を表示する。

        Debug→Run→Run
        下に黄色の帯びがでて、高速で実行中を示す。

        Debug→Run→Halt
        で停止する。

        Debug→Run→Reset(F6)
        でリセットする。

        Debug→Run→Step(F7)
        でステップ実行する。
        	movlw	0xA
        
        が実行され、Special Function Registerウィンドウ内の ワーキングレジスタwの値が0Aとなる。更新されたので赤文字である。
        w            0A    10   00001010   .   
        
        以下同様に確認する。

        注: File Register Windowの 0002 がステップ実行の度に更新されるが、 これはプログラムカウンタである。


        TOPIS!
        ファイルレジスタ0020番地を 00 にするには、
        Window→Modify
        Address 20
        Data 00
        として Write ボタンを押すと書き換わる。

        簡単なやり方として、 File Register Window の値を左ドラッグで選択し、 右クリックすると File Registers メニューがでるので、楽勝である。


    参考画面例



  6. プログラミング演習

    1. 条件付ループ

       次のプログラムをMPLABにコピペしてシミュレーションしよう。 動作については勉強会のときに解説します。

      ;	file name = cjump.asm		an example of the conditional jump 
      
      	list p=16f84
      
      #include "p16f84.inc"
      
      	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
      
      	RADIX	DEC
      COUNT	EQU	20H		;20HをCOUNTと呼ぶ
      ANS	EQU	21H		;21HをANSと呼ぶ
      	MOVLW	0		;Wに0を代入
      	MOVWF	ANS		;AnsにWの値を代入
      	MOVLW	10		;Wに10を代入
      	MOVWF	COUNT		;COUNTにWの値を代入
      LOOP	INCF	ANS,1		;ANSの値をインクリメント
      	DECF	COUNT,1		;COUNTの値をデクリメント
      	BTFSS	STATUS 2		;スキップする
      	GOTO	LOOP		;無条件ループ
      	END
      

      LOOP    ANS+1
              COUNT-1
              COUNTが0であるか? →LOOPへ戻る
                ↓YES
              次の処理
      

    2. サブルーチン

       サブルーチンとは、副プログラム(C言語の関数)の事である。
      プログラムのどこからでも同じ名前で呼び出せる。一定の意味のある処理 をまとめるにも良い手段である。
       処理
       ↓
       ↓
       ↓<処理
       ↓
      

       
       次のプログラムをMPLABにコピペしてシミュレーションしよう。
      解説は勉強会のときに解説します。

       レジスタTEMPを1→10に1ずつ変化させ5のとき、 SIGNALを1にして脱出する。

      ;	file name = subr.asm	an example of the subroutine 
      
      	list p=16f84
      
      #include "p16f84.inc"
      
      	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
      
      	RADIX	DEC
      TEMP	EQU	20H        
      SIGNAL	EQU	21H
      	MOVLW	0 		;W←0
      	MOVWF	TEMP		;TEMP←W
      	MOVWF	SIGNAL		;SIGNAL←W
      LOOP	INCF	TEMP,1		;TEMP←TEMP+1
      	CALL	CHECK		;サブルーチンコール 
      	BTFSS	SIGNAL,0 		;SIGNALの第0BITが1だったらスキップ
      	GOTO	LOOP
      
      CHECK  	MOVLW	5		;W←5
      	SUBWF	TEMP,0		;W←TEMP-W  0:W , 1:F と割り当てられている
      	BTFSC	STATUS,2        	;STATUSの2bit(ZERO)が0スキップ
      	INCF	SIGNAL,1
      	RETURN
      	END
      


      L:リテラル(定数)
      F:ファイルレジスタ
      W:ワーキングレジスタ



  7. 入出力

    入出力I/O(Input/Output)とはマイコンの外にある機器からデータを取り込んだり送りつけたりすること。

    機器の例:
    ・LED(光素子:ランプのようなもの)、
    ・モータ
    ・スイッチ
    ・リレー(電磁スイッチ)
    ・パソコン(シリアル、パラレル通信)
    ・A/D,D/A変換(スピーカ、温度計)

         
    ポートA、ポートBは、次のレジスタとつながっている。
    PORT A,PORT B ← ファイルレジスタの05,06番地にある。
    INPUT,OUTPUTなどの入出力専用の命令がない。
      
                76543210
      PORT A  XXX00000   0:使用可能
      PORT B  00000000   X:使用不可能
    
      PORT B  00000001 とすると、PB0だけが5Vとなる。
               他は0Vだが実際には0.6Vくらい(論理的に'0')
               これはPICが大出力電流をサポートするためと思われ。
      '1'=5V   -----
               |
               |
      '0'=0V___|
    
    ポートA,ポートBから、データを取り込むか、出力するか を設定しなければならない。その為のレジスタがTRISAおよびTRISBである。
        TRISA,TRISB ← ファイルレジスタ (Special Function Registerの)
          ↑  ↑
        portA portB
      
      1:入力、0:出力 
      すなわちportA,portBの出力ごとに入出力方向を指定できる。
    
    そのためには、ファイルレジスタ中のSTATUSレジスタの第5bitをRP0といい、 これを0にするとbank0, 1にするとbank1になる。
      ファイルレジスタのアドレス
         bank0         bank1
      00h ......    80h ......
          ......        ......
      05h portA     85h trisA
      06h portB     86h trisB
          ......        ......
    
     アドレス
       00000100 04h
       10000100 84n
       ↑
      MSBがRP0なんだー。RP0はステータス・レジスタの第5bitなんだー。
    
    では具体的にどうするん?
    	BSF	STATUS,RP0  ; bank1に指定する。Bit Set File Register
     	MOVLW	02          ; 入出力方向設定   1bit:入力、0bit:出力
     	MOVWF	TRISA       ; 方向を指定
    
    とすると、
    	BCF	STATUS,RP0  ; bank0に指定する。Bit Set File Register
    	MOVLW	01          ; 出力値設定       
     	MOVWF	PORTA       ; 値出力
    
    INPUTポートに1を出力しても問題ない。
    パワーオン時には出力指定で、0V出力になっている。

    page0,page1,page2,page3:プログラムメモリの切り替え(PIC16F84にはない)
    bank1,bank0:ファイルレジスタの切り替え
    	BSF	STATUS,5		; Bank1に切り替える。
    	MOVLW	B'00000001'	; ポートAの入出力を設定
    	MOVWF	TRISA		; TRISAに書き込む
    	MOVLW	B'00000000'	; ポートBの入出力を設定
    	MOVWF	TRISB		; TRISBに書き込む
    	BCF	STATUS,5		; Bank0に戻す
    
    注意 !!!
    BCFでバンク0に戻さないと、ある値を出力したかったのに 入出力方向を切り替えてしまうことになる。