PICのI/Oプログラミング

  1. 入出力プログラム

    1. SFR

      PIC16F6**には各バンク毎に先頭の00-20h番地が特殊レジスタ(SFR)に割り当てられています。このSFRに値を設定したり、読み出すことで、各種の機能を利用することができます。

      SFR一覧

      バンク0のSFRとそのビット構成は以下のようです。16F84と比較してEEROM関連のSFRレジスタの番地が異なっています。


      (カタログより引用)

      以下はバンク1のSFRです。

    2. STATUSレジスタ

      STATUSレジスタには、プロセッサの重要な情報が保存されています。下位3ビットは演算処理に伴うフラグで、

       Z:結果が0
       C:最上位ビットからのキャリーがあると1
       DC:第4ビットからのキャリーがあると1(BCD演算)

      中央の
       TOはWDTでタイムアウトが起こると0になります。
       PDはsleep命令を実行すると0になります。

      STATUS(3H、83H)
      IRP RP1 RP0 *TO *PD Z DC C
  2. メモリアクセス

    1. データメモリとバンク

       PC16F628は 7ビット のアドレス(番地)で、内部のデータメモリにアクセス(読み書き)できます。7ビットでは128バイトまでのメモリしかアクセスできません。そこで、SFRの一つである STATUSレジスタのRP1,RP0 ビットを利用して、メモリを切り替えて利用することができます。この方式をバンク選択方式と呼びます。
       異なるバンクにアクセスするには、RP1,RP0ビットを変更する必要がありあます。PICには、RP0とRP1の2ビットが用意されていますから、最大4個のバンクの切り替えが必要です。

      STATUS(3H、83H)
      IRP RP1 RP0          
    2. データメモリの間接アクセス

       データメモリは、命令で番地を直接指定してアクセスしますが、繰返しの中で連続してアクセスしたい場合があります。この場合、まず、FSRレジスタに番地を設定し、
       movf INDF,W
      で、INDF レジスタをWレジスタに読み出します。INDFの値はFSRの番地のデータメモリになりますから、WにFSRの番地の内容を読み出すことができます。逆に書き込むには、書き込む値をWレジスタに設定し
       movwf INDF
      を実行します。これで、Wレジスタの値が、FSRの番地に記録されます。この機能を間接アドレス方式と呼びます。繰返しのなかで、FSRの値を1ずつ増せば、順にデータメモリの次の番地にアクセスできます。
       INDF、FSR はSTATUSレジスタの RP1,RP0 バンク指定には依存しません。また、FSRは8ビットですから直接、00..FFh 番地の範囲を指定できます。100H番地以上の番地にアクセスするには、STATUSのIRPビットを1にします。

      INDF(0H、80H)
      B7           B1 B0
      FSR(4H、84H)
      B7           B1 B0
      STATUS(3H、83H)
      IRP              
    3. EEメモリ

       データメモリは、電源を切ると記録した内容を保持できません。EEメモリは、記録に長い時間を必要としますが、記録した内容を長時間保持することができます。PC16F628は128バイトのEEメモリを内蔵しています。
       EEメモリからの読み出しは、EEADR レジスタを利用した、間接アドレス方式を利用します。EEROMの場合、EECON1の RD ビットを1にすることで、EEADR 番地の値をEEDATAから読み出すことができます。

      ;read EEADR data from EEROM
              bdf     STATUS,RP0
              movlw   CONFIG_ADR
              movwf   EEADR
              bsf     EECON1,RD
              movf    EEDATA,W
              BCF     RP0

      EEROMに値を書き込むには、注意が必要です。EEROMへの書き込みは「電源を切っても忘れない」処理が必要なため、高速にはできません。書き込みが完了すると、割り込み用のフラグが立ちますので、割り込みを利用して次のバイトの書き込みをします。書き込みには、次のように、EECON2レジスタに55hとAAhを書き込み、最後に、EECON1のWRビットを1にセットします。

         movlw   55h
         movwf  EECON2
         movlw  AAh
         movwf  EECON2
         BSF   EECON1,WR

       なぜ、このようなEECON2への書き込みを必要とするかは、明らかではありませんが、ミスによる書き込みを避けるための工夫のようです。

      EEADR(98H)
        a6           a0
      EECON2(9DH)
      b7 b6           b0
      EECON1(9CH)
              WRERR WREN WR RD
  3. 割り込み

    1. 割り込み処理

      PICは、プログラムにしたがって実行をしますが、以下の要因で、「割り込み処理」を実行します。ただし、上記の要因に対する割り込み許可を INTCOM レジスタに予め設定しておく必要があります。

       INTF: INT端子の変化
       RBIF: ポートBの上位4ビットの変化
       TOIF: タイマー0のオーバーフロー
       EERPMへの書き込み完了

       割り込み条件が成立すると、プロセッサは4番地からのサブルーティンを呼び出します。ここで、「割り込み処理」を実行した後、RETFIE 命令を実行すると、割り込み前の処理を再開できます。
       割り込み機能を利用すると、割り込み要件の発生に関する処理は、実行中のプログラムとは独立に要件発生時にリアルタイムで(直ちに)実行することができます。

      INT端子による割り込みでは、立ち上がり/立ち下がりエッジの指定が可能です。これは OPTION レジスタのINTEDGビットで行います。

           INTEDG=0:立ち下がりエッジで割込み
           INTEDG=1:立ち上がりエッジで割込み

      INTCON以外の割り込み要求と許可ビットは、各種のSFRに分散して配置されています。

    2. INTCONレジスタの詳細

      3:0 ビットのフラグが1の場合、各要因の割り込み要求が起こっていることを示します。

           0   RBIF   RB4〜RB7の状態変化割込みフラグ
           1   INTF   RB0/INTの割込みフラグ
           2   T0IF   TMR0タイマ割込みフラグ

      6:3ビットの許可ビットは、要因別の割り込みを許可します。

           3   RBIE   RB4〜RB7の割込み許可ビット
           4   INTE   RB0/INTの割込み許可ビット
           5   T0IE   TMR0タイマの割込み許可ビット
           6   EEIE   データEEPROM書き込み完了割込み許可

      GIEは割り込み処理を行うかどうかを設定します。

           7   GIE    全体割込み許可ビット

      その他の要因の、フラグと許可ビットはPIR1,PIE1にあります。EEIEはEEROM,CMIEは比較器割り込み、RCIEは受信回路、TXIEは送信回路、CCP1IEは比較器が一致割り込み、に関する許可を行います。

      INTCOM
      GIE EEIE TOIE INTE RBIE TOIF INTF RBIF
      PIR1(0CH)
      EEIF CMIF RCIF TCIF   CCP1IF TMR2IF TMR1IF
      PIE1(8CH)
      EEIE CMIE RCIE TXIE   CCP1IE TMR2IE TMR1IE
    3. レジスタの保存と回復

       割り込み処理の先頭で、最低でも W と STATUS の保存が必要です。STATUSは下位3ビットに直前の演算結果を保持しています。

          MOVWF  W_TEMP    ;Wレジスタ待避
          SWAPF  STATUS,W  ;STATUS取り出し
          MOVWF  ST_TEMP   ;STATUS待避

      割り込み処理終了後、WとSTATUSを元に戻します。

         SWAPF  ST_TEMP,W  ;STATUSを戻す
          MOVWF  STATUS   ;
          SWAPF  W_TEMP,F  ;Wレジスタを戻す
          SWAPF  W_TEMP,W  ;MOVF命令はZフラグを変更するから利用できない

          RETFIE       ;割込み許可リターン

      STATUS(3H、83h)
                Z DC C
  4. 入出力ポート

     
    1. 端子とポート

       PICにはRAxまたはRBxの記号で表される端子があり、これは、ポートA,B の入出力端子になります。ポートAの端子に出力をするには、レジスタファイルのPORTAにデータを書き込みます。また、ポートAに接続された信号を処理するに、PORTAの値を読み込みます。レジスタBも同様です。
       ただし、RAx端子が供給できる電圧はPICに接続する電圧とほぼ同じです。また、電力は発光ダイオードを点灯する程度です。これ以上の電力を制御するには、電力制御用の回路を接続する必要があります。
       各端子は入力または出力のどちらで利用するかを予め設定する必要があります。これには、バンク1のTRISA、または、TRISBのレジスタファイルで指定します。

      PORTA(5H)
      RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
      PORTB(6H)
      RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0

      TRISA(85H)
      RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
      TRISB(86H)
      RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
    2. ポートAの初期化

       ポートAの端子はアナログ比較回路と共用しています。ポートAとして利用するには、アナログ比較回路の出力をオフにする必要があります。

              CLRF    PORTA ;
              MOVLW   0X07
              MOVWF   CMCOM  ;比較器の出力をオフに設定
      
              BCF     STATUS ,RP1
              BSF     STATUS ,RP0;バンクを1に
              MOVLW   0x1F  ;
              MOVWF   TRISA ;下5ビットを入力に
    3. ポートBの入出力

      ポートBの入出力を設定するレジスタTRISBはバンク1にあります。したがって、TRISBに値を設定するにはバンクを切り替える必要があります。バンク切り替えはSTATUSレジスタのRP1とRP0ビットで行います。

              bsf     STATUS,RP0      ;バンク1に切り替え
              movlw   0fH             ;Wレジスタに設定
              movwf   TRISA           ;下位4ビットを入力にする
              bcf     STATUS,RP0      ;バンク0に切り替え
              bsf     PORTB,2         ;ポートBの第2ビットをオンにする

      SFRのOPTIONレジスタの RBPU を0にすると、ポートBをプルアップします。ポートBを入力として利用する場合、外部でプルアップしない限り、指定をする必要があります。

  5. カウンタ、タイマ

    1. 機能

      カウンタは信号に含まれるパルスの数を数える機能です。信号が0から1に変化し(立ち上がり)、また1から0に変化すると、1つのパルスになります。一定の周期で変化する信号を計数すると、時間を計測できます。例えば、1K(キロ)Hzの信号は、1秒に100回のパルスとなりますから、これを1000個数えると1秒になります。
       PC16F628は0,1,2の3種のタイマー/カウンタを持ちます。タイマーは一定の時間が経過すると、「割り込み」を起こすことができます。この機能を利用すると、一定の時間毎に計測を行うことができます。
       また、タイマー2の機能を利用すると、指定した時間間隔で指定した幅のパルスを生成することができます。

    2. タイマー0

      タイマー0はほとんどのPICに内蔵されている機能で、外部信号または内部のクロックを計数します。計数する信号は OPTION レジスタのTOCSビットで指定します。0のとき内部クロック、1のとき外部クリックです。内部クロックの1/4の周期(命令の実行周期)で計数します。
       外部信号の場合、エッジ(上がり、下がり)を指定できます。タイマー0の値は、SFRのTMR0で読み出すことができます。読みとり可能な計数値は8ビットです。

       タイマー0では8bitのプリスケーラを利用し、最大1/256 までクロックを低減できます。OPTION レジスタのPSAビットが0のとき、タイマー0がプリスケーラを使用します。1のときはプリスケーラはWDT(watch Dog Timer)に利用されます。
       プリスケーラの分周率は、OPTION レジスタの[2::0](PS2,PS1,PS0)で指定します。この値が0のとき1/2、1のとき1/4、..7のとき1/256になります。

       CLRWDT
       BSF     STATUS,RP0
       MOVLW   b'0000XXX'    ;プリスケーラの設定
       MOVWF   OPTION_REG
       BCF     STATUS,RP0

      OPTION レジスタのTOSEをセットするとオーバーフローしたとき、割り込みを起こします。INTEDGビットは外部信号に対し、割り込みを起こすエッジ(信号の上がり/下がり)を指定します。TOCSは専用発振回路(T1CK1,T1OSI)を使用するとき1にします。

      OPTION_REG(81H)
      RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0
      INTCOM(0B,8B))
      GIE EEIE TOIE INTE RBIE TOIF INTF RBIF
      TMR0(01H)
      TM7 TM6 TM5 TM4 TM3 TM2 TM1 TM0
    3. タイマー1

      タイマー1は、外部または内部の信号を計数し、16ビットで読み出すことができます。プリスケーラは最大1/8の分周率になります。また、外部クロックを内部のクロックに同期させることが可能です。

       計数値は、TMR1HとTMR1Lの二つのレジスタで読み出します。ただし、ラッチ機能はありませんから、TMR1Hを読みとり後、TMR1Lを読み出すときTMR1Hが変化している可能性があります。まず、TMR1HとTMR1Lの値を保存します。続けて、TMR1Hと保存値を比較し、等しくない場合再度読み直します。

      タイマー1の機能は T1CONレジスタで設定します。
       TMR1ONビットでタイマー1のオン、オフをします。
       TMR1CSビットでクロック信号の外部(1)/内部(0)を選択します。
       外部信号の場合、T1SYNCでクリックへの同期の有無(0で同期をとる)を指定します。

       (T1CKS1,T1CKS0)でプリスケーラの分周率を指定します。00のとき1,01で2,10で4,11で8倍になります。
       T1OSCEN:を1にすると専用内蔵発振回路が有効になります。このとき、PIC16F627 と PIC16F628,では、RB7,RB6はTRISBにかかわらず、入力の扱いになります。
      割り込み許可と要求ビットは、PIR1のTMR1IFビットとPIE1のTMR1IEビットに配置されています。

      T1CON(10H)
          T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON
      TMR1L(0EH)
      B7              B1 B0
      TMR1H(0FH)
      B7                B1 B0

      PIR1(0CH)
                        TMR2IF TMR1IF
      PIE1(8CH)
                        TMR2IE TMR1IE
    4. タイマー2

       タイマー2は、プリスケーラで内部クロックを分周した後、TMR2に計数します。この値はPR2の値と比較され、等しい場合ポストスケーラを通して、タイマー2の割り込みを起こします。
       ポストスケーラは TOUTPS3,2,1,0 の値にしたがい、1:1から1:16まで分周します。プリスケーラはT2CKPS1,0にしたがい、1:1、1:4、1:16に設定されます。
       割り込み許可と要求ビットは、PIR1のTMR2IFビットとPIE1のTMR2IEビットに配置されています。

      T2CON(12h)
        TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0
      TMR2(11H)
      B7           B1 B0
      RP2(92h)
      B7           B1 B0

      PIR1(0CH)
                  TMR2IF TMR1IF
      PIE1(8CH)
                  TMR2IE TMR1IE
  6. CCP

    1. CCP機能

       16ビットの比較回路がキャプチャ、比較、PWMのデューティレジスタとして利用できます。各モードはCCP1M3,2 ビットで設定できます。

       CCP1M3,2 01:キャプチャ
               10:比較モード
               11:PWMモード


      CCP1CON(17H)
          CCP1X CCP1Y CCP1M3 CCPIM2 CCP1M1 CCP1M0
      CCPR1L(15H)
      b7             b0
      CCPR1H(16H)
      b7             b0
    2. キャプチャモード

       RB3の下記のイベントで、TMR1H、TMR1L の値を CCPR1H、CCPR1L に取り込み(キャプチャ)します
       CCP1M1,CCP1M0で動作モードが決定します。

       立ち下がりエッジ:00
       立ち上がりエッジ:01
       4回目の立ち上がりエッジ:10
       16回目の立ち上がりエッジ:11

    3. 比較

       TMR1H、TMR1L と CCPR1H、CCPR1L の16ビットを比較し、一致が取れたとき、RG3および割り込みを設定します。
      CCP1M1,CCP1M0で動作モードが決定します。
       RB3を1にする:
       RB3を0にする:
       RB3は設定しないで、割り込み要求のみ出す:

    4. PWM

       RB3にPWM波形を出力します。デューティは10bitで指定できますから、1024段階の設定が可能です。まず、TRISB<3>をクリアして、RB3ピンを出力にセットしておきます。T2CONを設定し、TMR2のプリスケーラの値とTimer2をEanableに設定します。

      PWMの周期をPR2に設定します。周期は
       (PR2+1)*4*Tosc*TMR2プリスケーラ
      となります。*4は2ビットを付加して10ビットにすることを意味します。

      PWMのduty時間はCCPR1の上位8ビットとCCP1CONの5:4の2ビット、の計10ビットに設定します。
      (CCP1CONの2ビット書き込み時に、PWMの下位4ビットをPWMモードに設定します。)
       この値は次の周期の開始時に自動的にCCPR1Hと内部の2ビットラッチに移されます。
       CCPR1HはCCPR1Lのダブルバッファとして利用され、これで、2bitと8bitを2回に分けて送ることによるグリッチを回避します。
       dutyサイクルは
        (CCPR1の上位8ビットとCCP1CONの5:4の2ビット)*Tosc*TMR2プリスケーラ
       で定まります。

  7. シリアル通信

    1. シリアル通信とは

      PC16F628にはRS232C準拠のシリアル通信機能が内蔵されています。これを利用すると、パソコンや外部機器との通信が可能です。シリアル通信は送信と受信の2本の信号とグランド信号で、送受信可能です。8ビットのデータは一定の時間間隔で直列に送信されます。
       受信回路はこの信号を受け取り、元の1バイトのデータに復元します。送信や受信が完了すると割り込みを発生します。このシリアル信号は、同じ規格のシリアル端子付のパソコンや他の制御回路でデータ交換ができます。ただし、RS232Cでは、送受信の電圧が、+12V〜-12Vのため、このままでは、直接接続できません。RS232C信号へのレベル変換素子を利用して、接続する必要があります。
       ただし、最近ではUSBに移行したため、シリアル端子を持つパソコンは少なくなりました。多くの場合USBからシリアルに変換するケーブルが利用できます。

    2. シリアル送受信

       シリアル送受信は、RS232Cで規格化された非同期通信方式が良く利用されます。1バイトのデータをシフトしながら1本のケーブルで送信します。受信すら側では、逆に、シフトしながらデータを受け取ります。送受信でシフトする時間間隔を同一にする必要があります。RS232Cでは、19.2k、9.6k、bps(秒あたりのビット数)がよく利用されます。

       
    3. 送受信速度の設定:SPBRG:19H+80H

       送受信の速度は、SPBRGレジスタで設定できます。これは、CPU本体のクロックから次の式で生成されます。ここで、Xは SPBRG に設定する値です。
       クロック周波数/16(X + 1)
      クリックが20MHzで速度を19.2kにする場合、X=64、クリックが4MHzで速度を19.2kにする場合12になります。9.6kbpsの場合はこの倍の値です。

    4. 送信用レジスタ:TXSTA:18H+80H

       シリアル送信機能を設定し、送信するデータをTXREGに送ると。設定された速度で送信を開始します。ただし、送信が完了するまで、次のデータを TXREG に送ることはできません。TXSTAレジスタは送信の設定や、送信の完了を知ることができるレジスタで、TXREGと区別してステータスレジスタと呼ばれます。
       TXENを1にすると次の送信が可能になります。TRMTが1のとき次の送信が可能であることを示します。TX9はパリティを付加して9ビットで送る場合に1とし、TX9Dにパリティを設定します。このパリティ機能は現在利用されることは稀です。
       すべての送信データの送信完了はPIR1レジスタで知ることができます。

      TXSTA:18H+80H
      0 TX9 TXEN 0 0 BRGH TRMT TX9D
      TXREG:19H
      b7                   b0
    5. 受信用レジスタ:

       受信の設定や状態を知るにはRCSTAレジスタを利用します。シリアル送受信をするには、SPENを1にします。これで、RB1とRB2が受信と送信端子になります。
       受信可にするには、CRENを1にします。FERRは受信波形が異常の場合1になります。また、OERR は受信データの読み込みが遅れて、受信したデータが次のデータで書き換えられた場合1になります。いずれの場合も受信エラーになります。
       受信完了はPIR1レジスタで知ることができます。

      RCSTA:18H
      SPEN RX9 0 CREN 0 FERR OERR RX9D
      RCREG:1AH
      b7                 b0
    6. 送受信完了と割り込み

       送受信完了を知るにはPIR1レジスタのRCIF(受信)とTXIF(送信)ビットで知ることができます。シリアル送受信は比較的遅いため、送受信の完了をループで待っていると他の処理ができなくなります。そこで割り込み機能を利用できます。割り込み許可は、PIE1レジスタのRCIEビットとTXIEビットで設定します。

      PIR1(0CH)
            RCIF TXIF            
      PIE1(8CH)
            RCIE TXIE            
  8. アナログ電圧生成、比較機能

    1. 参照電圧生成

       PC16F628は16レベルのアナログ電圧の生成回路が内蔵されています。この電圧を「参照電圧」と呼んでいます。ディジタル値から対応する電圧を発生する機能はDA変換機能とも呼ばれます。参照電圧は、VRCON で設定します。VRENで回路がオンとなり、VROEで RA2 に出力します。この信号はインピーダンスが高いので、入力抵抗が高い回路で受け取る必要があります。VROEは0でも、次の比較回路に参照電圧を利用することができます。
       生成する電圧は、VRRで異なります。

       VRR=1 のとき VR<3:0>*(VDD/24)
       VRR=0 のとき  VDD/4 + VR<3:0>*(VDD/32)

      となります。いづれの場合でも最大電圧は、VDDが5Vのとき、3.2V程度です。

      VRCON:9fH
      VREN VROE VRR   VR3 VR2 VR1 VR0
    2. 比較回路

       また、PC16F628には、参照電圧を外部端子との比較回路が内蔵されており、電圧の大小を比較できます。参照電圧の発生機能と、電圧比較回路を利用したプログラムにより、入力されるアナログ電圧を16段階のディジタル信号に分類できます。この機能をDA変換機能と呼びます。
       比較器には8種のモードがありますが、一般形は次のモード(CM2:CM0=010)です。アナログ入力はCISビットで選択可能です。二つの信号が参照電圧と同時に比較できます。比較結果は C2INVで変化します。C1INVも同様です。
       C2INV=0 のとき、VIN+>VIN- のとき1になります。
       C2INV=1 のとき、VIN+<VIN- のとき1になります。
      結果は、C2OUTとC1OUTで参照可能です。

      CMCON:1fH
      C2OUT C1OUT C2INV C1INV  CIS CM2 CM1 CM0



      外部の信号間を比較したり、比較結果をRA4端子に出力するモードもあります。



      参照電圧を設定してから、比較結果を取得するまでに 10μ秒程度の遅延が必要です。

  9. WDT、リセット、スリープ

    1. ウオッチドッグタイマー

       ウオッチドッグとは「番犬」のことです。この機能は、一定時間間隔でPICをリセットする機能で、何らかの原因でプロセッサが暴走したとき、自動的に初期状態に戻す機能です。この機能は、コンフィグレーションビットで設定可能です。また、ウオッチドッグより短い時間で割り込みをかけ、ウオッチドッグタイマーをクリアすることができます。

    2. パワーオン・ブラウンリセット

       これは電源に関する機能です。パワーオンリセットは、電源が十分立ち上がるまでリセットを出し、電源が立ち上がるまでの不安定な動きを避ける機能です。ブラウンリセットは、電源電圧を監視し、一定以下の電圧になった場合、リセットをかけプロセッサの暴走を避ける機能です。

    3. スリープ機能

       sleep命令を実行すると、低電力の待機モードに入ります。この状態は、一部の割り込みやWDTのタイムアウトで元の状態に戻ります。この機能を利用すると、待機時の消費電力を抑えることができます。
      待機モードでは、クロックも停止しますから、タイマー0割り込みは効きません。外部クロック&非同期のタイマー1、外部割り込み、などの割り込みはかかります。