マイクロチップ社のPICmicroマイクロコントローラを用いた1-Wire通信

2004年09月29日
myAnalogに追加

myAnalog のリソース セクション、既存のプロジェクト、または新しいプロジェクトに記事を追加します。

新規プロジェクトを作成

要約

マキシム製品の幾つかは1-Wire®通信インタフェースを備えており、さまざまなアプリケーションで使用されています。このアプリケーションの中には、良く知られたマイクロチップ社のPICmicro® (PIC)とのインタフェースなどがあります。1-Wireデバイスとペリフェラルインタフェースコントローラ(PIC)マイクロコントローラとの間のインタフェース接続を容易にするために、このアプリケーションノートでは、PICマイクロコントローラ用として汎用の1-Wireソフトウェアルーチンを紹介し、タイミングとその詳細について説明します。また、このアプリケーションノートには、すべての1-Wireルーチンを収録したインクルードファイルも掲載しています。さらに、サンプルのアセンブリコードも掲載しています。このアセンブリコードは、PIC16F628がDS2762高精度リチウムイオンバッテリモニタを読み取ることができるように特別に記述されています。

はじめに

マイクロチップ社のPICmicroマイクロコントローラデバイス(PIC)は、低電力で低コストのシステムソリューションを設計する際の良く知られた選択肢となっています。マイクロコントローラには、複数の汎用入力/出力(GPIO)ピンがあり、マキシムの1-Wireプロトコルを実現するように容易に設定することができます。1-Wireプロトコルを使用すると、バッテリおよび熱管理、メモリ、iButton®デバイスなど、多くのマキシム製品との連携が可能になります。このアプリケーションノートでは、PIC16F628用の汎用の1-Wireルーチンを紹介し、タイミングとその詳細について説明します。分かりやすくするために、紹介するすべての機器が4MHzクロックで動作するものと想定しています。多くのPICでこの周波数を内部クロックとして利用することができます。このアプリケーションノートの付録Aには、すべての1-Wireルーチンを収めたインクルードファイルを掲載しています。付録Bでは、PIC16F628がDS2762高精度リチウムイオンバッテリモニタを読み取れるように設計されたサンプルのアセンブリコードプログラムを紹介します。このアプリケーションノートでは、標準速度の1-Wire通信に範囲を限定しています。

一般的なマクロ

1-Wireプロトコルをマスタとして送信するために必要となるGPIO状態は、次の2つだけです。すなわち、ハイインピーダンスとロジックローです。以下のPICアセンブリコードの抜粋は、これら2つの状態を実現しています。PIC16F628は2つのGPIOポート(PORTAおよびPORTB)を備えています。いずれのポートも1-Wire通信用に設定することができますが、この例ではPORTBを使用しています。また、以下のコードでは、アセンブリコード内で定数DQを設定し、これによって、PORTB内のどのビットが1-Wire端子に対応するかを示すことを想定しています。コード全体にわたって、このビット番号を単にDQと呼びます。この端子は、外付けのプルアップ抵抗を介して電源に接続する必要があります。

      OW_HIZ:MACRO
      ;Force the DQ line into a high impedance state.
             BSF    STATUS,RP0                  ; Select Bank 1 of data memory
             BSF    TRISB, DQ                   ; Make DQ pin High Z
             BCF    STATUS,RP0                  ; Select Bank 0 of data memory
             ENDM

      OW_LO:MACRO
      ;Force the DQ line to a logic low.
             BCF    STATUS,RP0                  ; Select Bank 0 of data memory
             BCF    PORTB, DQ                   ; Clear the DQ bit
             BSF    STATUS,RP0                  ; Select Bank 1 of data memory
             BCF    TRISB, DQ                   ; Make DQ pin an output
             BCF    STATUS,RP0                  ; Select Bank 0 of data memory
             ENDM

これらのコード抜粋は、いずれもマクロとして記述されています。コードをマクロとして記述することによって、マクロを1個呼び出すことで自動的にアセンブリソースコードにコードが挿入されます。こうすることにより、コードの再記述を必要とする回数を抑えることができます。1つ目のマクロ(OW_HIZ)は、DQラインをハイインピーダンス状態にします。最初の手順は、データメモリのバンク1を選択することです。これはTRISBレジスタがバンク1にあるからです。次に、TRISBレジスタの中のDQビットを1に設定することにより、DQ出力ドライバをハイインピーダンス状態に変更します。コードの最終行では、データメモリのバンク0に戻しています。最終行は必須ではありませんが、これを使用すれば、すべてのマクロと関数の呼び出しに対してデータメモリを既知の状態に保持しておくことができます。

2つ目のマクロ(OW_LO)は、DQラインをロジックローにします。最初に、データメモリのバンク0を選択して、PORTBレジスタにアクセスできるようにします。PORTBレジスタはデータレジスタであり、TRISB端子を出力として設定した場合にTRISB端子に渡す値が含まれます。

PORTBのDQビットはクリアされ、DQラインはローになります。最後にデータメモリのバンク1を選択してTRISBレジスタのDQビットをクリアし、DQを出力ドライバにします。先ほどと同様、データメモリのバンク0を選択してマクロは終了します。

WAITと名付けられた最後のマクロは、1-Wireの信号送出の遅延を生成するために存在します。WAITを使用して、5µsの倍数の遅延を生成します。マクロはTIMEの値(マイクロ秒単位)を用いて呼び出され、これに相当する遅延時間が生成されます。マクロは単純に5µsの遅延が必要な回数を計算して、WAIT5U内でループします。WAIT5Uルーチンを、次の項で紹介します。WAIT内の各命令では、遅延が実現される様子をわかりやすくするために、処理時間をコメントとして記しています。

      WAIT:MACRO TIME
      ;Delay for TIME µs.
      ;Variable time must be in multiples of 5µs.
             MOVLW (TIME/5) - 1                 ;1µs to process
             MOVWF TMP0                         ;1µs to process
             CALL WAIT5U                        ;2µs to process
             ENDM

汎用の1-Wireルーチン

1-Wireタイミングプロトコルには規定されたタイミング制約があり、通信を成功させるためにはこの制約に従う必要があります。特定のタイミング遅延を作り出せるようにするため、WAIT5Uのルーチンを使用して5µsの遅延を生成します。このルーチンを以下に示します。

      WAIT5U:
      ;This takes 5µs to complete
             NOP                                ;1µs to process
             NOP                                ;1µs to process
             DECFSZ TMP0,F                      ;1µs if not zero or 2µs if zero
             GOTO WAIT5U                        ;2µs to process
             RETLW 0                            ;2µs to process

WAITマクロと同時に使用すると、単純なタイミング遅延を生成することができます。たとえば、40µsの遅延が必要な場合、WAIT 0.40を呼び出します。これによって、WAITの初めの3行が実行され、4µsの遅延が生成されます。次にWAIT5Uのコードの初めの4行が5µsで実行され6回ループして、合計30µsになります。WAIT5Uの最後のループは6µsかかり、その後WAITマクロに戻ります。したがって、処理時間の合計は、4 + 30 + 6 = 40µsとなります。

表1. 標準速度の1-Wireインタフェースのタイミング
2.5V < VDD < 5.5V, TA = -20°C to +70°C
Parameter Symbol Min Typ Max Units
Time Slot tSLOT 60   120 µs
Recovery Time tREC 1     µs
Write 0 Low Time tLOW0 60   120 µs
Write 1 Low Time tLOW1 1   15 µs
Read Data Valid tRDV     15 µs
Reset-Time High tRSTH 480     µs
Reset-Time Low tRSTL 480   960 µs
Presence-Detect High tPDH 15   60 µs
Presence-Detect Low tPDL 60   240 µs

1-Wire通信処理はいずれも、マスタデバイスが送出するリセットパルスから開始され、その後にスレーブデバイスから送出されるプレゼンス検出パルスが続きます。図1にこの処理を示しています。この初期化シーケンスは、PICを介して容易に送信することが可能で、このアセンブリコードを図1の下に示しています。1-Wireの初期化、読取り、および書込みのタイミング仕様を上記の表1に示しています。これらのパラメータは、このアプリケーションノート内で参照することができます。

図1. 1-Wireの初期化シーケンス

図1. 1-Wireの初期化シーケンス

      OW_RESET:
             OW_HIZ                             ; Start with the line high
             CLRF      PDBYTE                   ; Clear the PD byte
             OW_LO
             WAIT      .500                     ; Drive Low for 500µs
             OW_HIZ
             WAIT      .70                      ; Release line and wait 70µs for PD Pulse
             BTFSS     PORTB,DQ                 ; Read for a PD Pulse
             INCF      PDBYTE,F                 ; Set PDBYTE to 1 if get a PD Pulse
             WAIT      .430                     ; Wait 430µs after PD Pulse
             RETLW     0

OW_RESETルーチンは、最初にDQ端子がハイインピーダンス状態にあることを確認します(プルアップ抵抗によってハイにプルできるようにするためです)。次に、OW_RESETルーチンは、PDBYTEレジスタをクリアし、次のプレゼンス検出パルスを有効にする準備を行います。その後、DQ端子は500µsの間ローになります。これは、表1に示されているtRSTLパラメータを満たすものであり、20µsの追加バッファも設けられています。この端子をローにした後、端子は開放されてハイインピーダンス状態になり、プレゼンス検出パルスを読み取る前に70µsの遅延が追加されます。この70µsを追加することによって、tPDLとtPDHのどのような組み合わせについても、PICが適切な時刻にサンプリングできるようになります。プレゼンス検出パルスが読み取られると、PDBYTEレジスタは、ロジックレベルの読取りを示すように調整されます。この後、DQピンのハイインピーダンス状態がさらに430µsの間維持されるので、tRSTH時間が満たされ、また、20µsの追加バッファも含まれます。

1-Wire通信で必要な次のルーチンはDSTXBYTEです。これを使用して、1-Wireのスレーブデバイスにデータを送信します。このルーチンのPICコードを図2の下に示しています。このルーチンは、WREGレジスタ内に送信データを用意して呼び出され、直ちにIOBYTEレジスタに移動されます。次に、COUNTレジスタが8に初期化され、DQラインに送出されるビット数をカウントします。PICは、DSTXLPから始めてデータの送出を開始します。送信されるロジックレベルに関わらず、最初にDQ端子が3µsの間ローになります。こうすることで、tLOW1時間が満たされます。次に、IOBYTEのLSBがCARRYビットにシフトされ、1か0かをテストされます。CARRYが1の場合、TRISBのDQビットがセットされて、ピンはハイインピーダンス状態に変化し、ラインはプルアップ抵抗によってハイにプルされます。CARRYが0の場合、ラインはローの状態を維持します。次に、tLOW0の最小時間を満たすため60µsの遅延が追加されます。60µsの待機後、この端子はハイインピーダンス状態に変化し、プルアップ抵抗の回復のためにさらに2µsが追加されます。最後に、COUNTレジスタがデクリメントされます。COUNTレジスタが0の場合、8ビットのすべてが送信されており、ルーチンは終了します。COUNTレジスタが0でない場合、DSTXLPから始めて別のビットが送信されます。図2は、「書込み0」と「書込み1」の手順を視覚的に説明しています。

図2. 1-Wireの書込みタイムスロット

図2. 1-Wireの書込みタイムスロット

      DSTXBYTE:                                 ; Byte to send starts in W
             MOVWF     IOBYTE                   ; We send it from IOBYTE
             MOVLW     .8
             MOVWF     COUNT                    ; Set COUNT equal to 8 to count the bits
      DSTXLP:
             OW_LO
             NOP
             NOP
             NOP                                ; Drive the line low for 3µs
             RRF        IOBYTE,F
             BSF        STATUS,RP0              ; Select Bank 1 of data memory
             BTFSC      STATUS,C                ; Check the LSB of IOBYTE for 1 or 0
             BSF        TRISB,DQ                ; HiZ the line  if LSB is 1
             BCF        STATUS,RP0              ; Select Bank 0 of data memory
             WAIT      .60                      ; Continue driving line for 60µs
             OW_HIZ                             ; Release the line for pullup
             NOP
             NOP                                ; Recovery time of 2µs
             DECFSZ    COUNT,F                  ; Decrement the bit counter
             GOTO      DSTXLP
             RETLW     0

1-Wire通信の最後のルーチンはDSRXBYTEです。これによってPICはスレーブデバイスから情報を受信することができます。このコードは、図3の下に示されています。COUNTレジスタが8に初期化された後、DQ動作が開始されます。この機能は、受信したビット数をカウントします。まず、DSRXLPはDQ端子をローにし、PICがデータを受信する準備ができていることをスレーブデバイスに通知します。ラインは6µsの間ローになり、その後DQ端子をハイインピーダンス状態にすることで開放されます。次に、PICはさらに4µsの間待機してからデータラインをサンプリングします。ラインがローになった後、OW_LO内には1行のコードがあり、OW_HIZ内には3行のコードがあります。各行の処理には1µsかかります。これらの時間をすべて加算すると、1 + 6 + 3 + 4 = 14µsになりますが、これはtRDV仕様の15µsをわずかに下回っています。PORTBレジスタを読み取った後、DQビットのみを取り出し、レジスタに255を加算してCARRYビットにDQビットを反映させます。CARRYビットは次にIOBYTEにシフト入力され、着信バイトはここに格納されます。バイトが格納されたら、tSLOTが満たされるように50µsの遅延が追加されます。最後のチェックは、COUNTレジスタが0かどうかを判定することです。0の場合、8ビットが読み取られており、ルーチンは終了します。そうでない場合は、DSRXLPからループは繰り返されます。「読取り0」および「読取り1」の処理を図3に視覚的に示しています。

図3. 1-Wireの読取りタイムスロット

図3. 1-Wireの読取りタイムスロット

      DSRXBYTE:                                ; Byte read is stored in IOBYTE
             MOVLW     .8
             MOVWF     COUNT                   ; Set COUNT equal to 8 to count the bits
      DSRXLP:
             OW_LO
             NOP
             NOP
             NOP
             NOP
             NOP
             NOP                                ; Bring DQ low for 6µs
             OW_HIZ
             NOP
             NOP
             NOP
             NOP                                ; Change to HiZ and Wait 4µs
             MOVF      PORTB,W                  ; Read DQ
             ANDLW     1<<DQ                    ; Mask off the DQ bit
             ADDLW     .255                     ; C = 1 if DQ = 1: C = 0 if DQ = 0
             RRF       IOBYTE,F                 ; Shift C into IOBYTE
             WAIT      .50                      ; Wait 50µs to end of time slot
             DECFSZ    COUNT,F                  ; Decrement the bit counter
             GOTO      DSRXLP
             RETLW     0

まとめ

マキシムの1-Wire通信プロトコルは、マイクロチップ社のPICmicroファミリのマイクロコントローラ内に容易に実現することができます。1-Wire処理を完了するために必要となるGPIO状態は2つだけであり、PICにある多数のGPIOは、この仕事を行うように容易に設定することができます。1-Wire通信には、3つの基本ルーチンが必要となります。「初期化」、「バイトの読取り」、および「バイトの書込み」です。正確な1-Wireの標準速度の通信を実現するため、これら3つのルーチンを提示して詳細に説明しました。これらを使用することで、PICは多くのマキシムの1-Wireデバイスのいずれにでも接続することができます。このアプリケーションノートの付録Aは、3つのルーチンすべてを使いやすいインクルードファイルに収録しています。付録Bは、DS2762高精度リチウムイオンバッテリモニタにPIC16F628を接続するための短いアセンブリプログラムを収録しています。

付録A:1-Wireのインクルードファイル(1W_16F6X.INC)

; *******************************************************
;
; Maxim 1-Wire Support for PIC16F628
;
; Processor has 4MHz clock and 1µs per instruction cycle.
;
; *******************************************************


; *******************************************************
; Maxim 1-Wire MACROS
; *******************************************************
OW_HIZ:MACRO
      BSF           STATUS,RP0                  ; Select Bank 1 of data memory
      BSF           TRISB, DQ                   ; Make DQ pin High Z
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
      ENDM
; --------------------------------------------------------
OW_LO:MACRO
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
      BCF           PORTB, DQ                   ; Clear the DQ bit
      BSF           STATUS,RP0                  ; Select Bank 1 of data memory
      BCF           TRISB, DQ                   ; Make DQ pin an output
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
      ENDM
; --------------------------------------------------------
WAIT:MACRO TIME
;Delay for TIME µs.
;Variable time must be in multiples of 5µs.
      MOVLW         (TIME/5)-1                  ;1µs
      MOVWF         TMP0                        ;1µs
      CALL          WAIT5U                      ;2µs
      ENDM

; *******************************************************
;       Maxim 1-Wire ROUTINES
; *******************************************************
WAIT5U:
;This takes 5µS to complete
      NOP                                       ;1µs
      NOP                                       ;1µs
      DECFSZ        TMP0,F                      ;1µs or 2µs
      GOTO          WAIT5U                      ;2µs
      RETLW 0                                   ;2µs
; --------------------------------------------------------
OW_RESET:
      OW_HIZ                                    ; Start with the line high
      CLRF PDBYTE                               ; Clear the PD byte
      OW_LO
      WAIT          .500                        ; Drive Low for 500µs
      OW_HIZ
      WAIT          .70                         ; Release line and wait 70µs for PD Pulse
      BTFSS         PORTB,DQ                    ; Read for a PD Pulse
      INCF          PDBYTE,F                    ; Set PDBYTE to 1 if get a PD Pulse
      WAIT          .400                        ; Wait 400µs after PD Pulse
      RETLW 0
; --------------------------------------------------------
DSRXBYTE: ; Byte read is stored in IOBYTE
      MOVLW         .8
      MOVWF         COUNT                       ; Set COUNT equal to 8 to count the bits
DSRXLP:
      OW_LO
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP                                       ; Bring DQ low for 6µs
      OW_HIZ
      NOP
      NOP
      NOP
      NOP                                       ; Change to HiZ and Wait 4µs
      MOVF          PORTB,W                     ; Read DQ
      ANDLW         1<<DQ                       ; Mask off the DQ bit
      ADDLW         .255                        ; C=1 if DQ=1: C=0 if DQ=0
      RRF           IOBYTE,F                    ; Shift C into IOBYTE
      WAIT          .50                         ; Wait 50µs to end of time slot
      DECFSZ        COUNT,F                     ; Decrement the bit counter
      GOTO          DSRXLP
      RETLW         0
; --------------------------------------------------------
DSTXBYTE:                                       ; Byte to send starts in W
      MOVWF         IOBYTE                      ; We send it from IOBYTE
      MOVLW         .8
      MOVWF         COUNT                       ; Set COUNT equal to 8 to count the bits
DSTXLP:
      OW_LO
      NOP
      NOP
      NOP                                       ; Drive the line low for 3µs
      RRF           IOBYTE,F
      BSF           STATUS,RP0                  ; Select Bank 1 of data memory
      BTFSC         STATUS,C                    ; Check the LSB of IOBYTE for 1 or 0
      BSF           TRISB,DQ                    ; HiZ the line  if LSB is 1
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
      WAIT          .60                         ; Continue driving line for 60µs
      OW_HIZ                                    ; Release the line for pullup
      NOP
      NOP                                       ; Recovery time of 2µs
      DECFSZ        COUNT,F                     ; Decrement the bit counter
      GOTO          DSTXLP
      RETLW         0
; --------------------------------------------------------

付録B:PIC16F628をDS2762に接続するためのアセンブリコード(PIC_2_1W.ASM)

; *******************************************
;
; Maxim PIC code
;
; This code will interface a PIC16F628 microcontroller to
; a DS2762 High-Precision Li+ Battery Monitor
;
; *******************************************;
;
;                   VCC
;                     ^
;                    |
;                    |
;                    /
;                    \ Rpup
;                    /
;                    ;                    |
; 16F628             |                   DS2762
; RB1 (pin 7) ------------------------------ DQ (pin 7)
;
; *******************************************;

;---------------------------------------------------------
; List your processor here.

      list p=16F628

; Include the processor header file here.

      #include <p16F628.inc>
;---------------------------------------------------------
; Assign the PORTB with Constants

      constant DQ=1                             ; Use RB1 (pin7) for 1-Wire
;--------------------------------------------------------
; These constants are standard 1-Wire ROM commands

      constant SRCHROM=0xF0
      constant RDROM=0x33
      constant MTCHROM=0x55
      constant SKPROM=0xCC
;---------------------------------------------------------
; These constants are used throughout the code

      cblock        0x20
             IOBYTE
             TMP0                               ; Address 0x23
             COUNT                              ; Keep track of bits
             PICMSB                             ; Store the MSB
             PICLSB                             ; Store the LSB
             PDBYTE                             ; Presence Detect Pulse
      endc
;---------------------------------------------------------
; Setup your configuration word by using __config.

; For the 16F628, the bits are:
; CP1,CP0,CP1,CP0,N/A, CPD, LVP, BODEN, MCLRE, FOSC2, PWRTE, WDTE, FOSC1, FOSC0
; CP1 and CP0 are the Code Protection bits
; CPD: is the Data Code Protection Bit
; LVP is the Low Voltage Programming Enable bit
; PWRTE is the power-up Timer enable bit
; WDTE is the Watchdog timer enable bit
; FOSC2, FOSC1 and FOSC0 are the oscillator selection bits.

; CP disabled, LVP disabled, BOD disabled, MCLR enabled, PWRT disabled, WDT disabled, INTRC I/O oscillator
; 11111100111000

      __config 0x3F38
;---------------------------------------------------------
; Set the program origin for subsequent code.

      org 0x00
      GOTO          SETUP
      NOP
      NOP
      NOP
      GOTO          INTERRUPT                   ; PC 0x04...INTERRUPT VECTOR!
;---------------------------------------------------------
INTERRUPT:
      SLEEP
;---------------------------------------------------------
; Option Register bits
; ____
; RBPU,INTEDG,TOCS,TOSE,PSA,PS2,PS1,PS0
; 7=PORTB Pullup Enable, 6=Interrupt Edge Select, 5=TMR0 Source,
; 4=TMR0 Source Edge, 3=Prescaler Assign, 2-0=Prescaler Rate Select

; 11010111
; PORTB pullups disabled,rising edge,internal,hightolow,TMR0,1:256

SETUP:
      BCF           STATUS,RP1
      BSF           STATUS,RP0                  ; Select Bank 1 of data memory
      MOVLW         0xD7
      MOVWF         OPTION_REG
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
;---------------------------------------------------------

      BCF           INTCON,7                    ; Disable all interrupts.

;---------------------------------------------------------
      GOTO          START
;---------------------------------------------------------
; Include the 1-Wire communication routines and macros

      #INCLUDE 1w_16f6x.inc
;---------------------------------------------------------
START:
;---------------------------------------------------------
GET_TEMP:
      CALL          OW_RESET                    ; Send Reset Pulse and read for Presence Detect Pulse
      BTFSS         PDBYTE,0                    ; 1 = Presence Detect Detected
      GOTO          NOPDPULSE
      MOVLW         SKPROM
      CALL          DSTXBYTE                    ; Send Skip ROM Command (0xCC)
      MOVLW         0x69
      CALL          DSTXBYTE                    ; Send Read Data Command (0x69)
      MOVLW         0x0E
      CALL          DSTXBYTE                    ; Send the DS2762 Current Register MSB address (0x0E)
      CALL          DSRXBYTE                    ; Read the DS2762 Current Register MSB
      MOVF          IOBYTE,W
      MOVWF         PICMSB                      ; Put the Current MSB into file PICMSB
      CALL          DSRXBYTE                    ; Read the DS2762 Current Register LSB
      MOVF          IOBYTE,W
      MOVWF         PICLSB                      ; Put the Current LSB into file PICLSB
      CALL          OW_RESET

NOPDPULSE:                                      ; Add some error processing here!
      SLEEP                                     ; Put PIC to sleep
;---------------------------------------------------------
      end


最新メディア 21

Subtitle
さらに詳しく
myAnalogに追加

myAnalog のリソース セクション、既存のプロジェクト、または新しいプロジェクトに記事を追加します。

新規プロジェクトを作成