摘要:Dallas Semiconductor的產品中有些包含了1-Wire?通信接口,適用于不同系統。這些系統中可能需要與著名的Microchip PICmicro? (PIC)接口。為方便1-Wire器件與PIC微控制器的接口,本應用筆記給出了用于PIC微控制器的1-Wire軟件例程,時序說明和相關資料。本應用還提供一個包含了所有1-Wire子程序的文件,所提供的匯編程序是針對PIC16F628讀取高精度Li+電池監視器DS2761的數據編寫的。
第二個宏指令OW_LO的功能就是把DQ強制變為低電平。首先選擇數據存儲器的bank 0,這樣PORTB寄存器就被尋址。PORTB寄存器是數據存儲器,當設置作為輸出時,它包含了那些TRISB中配置為輸出引腳的強制輸出值。
將PORTB的DQ位清零,這樣引線就強制變為低電平。最后選擇數據存器的bank 1,PORTB寄存器的DQ位清零,使其用作輸出驅動。和其它一樣,宏指令以選擇數據存儲器的bank 0結束。
最后的宏指令WAIT用于產生1-Wire信令所需要的延時。WAIT可產生5μs的整數倍的延時。在這個宏指令中,先簡單計算出所需的5μs延時的整倍數,然后在WAIT5U做相應次數的循環。WAIT5U子程序將在下一節討論。對于WAIT內的每一條指令,所用處理時間都進行了注釋,以方便理解延時是怎樣實現的
表1. 標準速率下1-Wire接口定時要求
1-Wire通信的所有過程都是從主機發的一個復位脈沖開始,隨后跟著從機的應答檢測脈沖(presence detect pulse)。 圖1對這個事務處理進行了闡述。初始化序列可通過PIC發出,很簡單,對應的匯編代碼如圖1所示。初始化、讀操作、寫操作的時序參數已在表1中列出。在本文的后面部分也將以這些參數為參考。
圖1. 1-Wire的初始化序列
1-Wire通信需要的另外一個子程序就是DSTXBYTE,用于向1-Wire從器件發送數據。這個子程序的PIC代碼如圖2所示。這個子程序需要和WREG寄存器中要發送的數據一起調用。首先將要發送的數據立即放入IOBYTE寄存器,隨后將COUNT寄存器初始化為8,以用來對要在DQ口線上發送的位進行計數。從DSTXLP開始,PIC才送出數據。開始時不管發送的電平是高是低,DQ引腳都變低電平3μs,這樣就可滿足tLOW1的要求。隨后IOBYTE的LSB移位至CARRY位,然后檢測是0還是1。如果CARRY是1,TRISB的DQ位置位,引腳變為高阻態,線路被上拉電阻拉為高電平。如果CARRY是0,線路就維持低電平。之后又引入60μs的延時以便在tLOW0在最小值時仍能正常工作。60μs的等待之后,該引腳變為高阻態,之后又是2μs的附加延時以便上拉電阻復原。最后COUNT減1。如果COUNT寄存器的值成了0,表示所有的數據已經發送完畢,子程序結束。如果COUNT寄存器的值不是0,就從DSTXLP開始繼續發送下一位數據。關于如何在程序中寫入0或寫入1參見圖2。
圖2. 1-Wire寫操作時序
圖3. 1-Wire讀時隙
引言
Microchip公司的PICmicro微控制器(PIC)已經成為低功耗、低成本系統解決方案的主流選擇。這些微處理器有多個通用輸入輸出引腳(GPIO),通過對這些引腳進行簡單組合就可實現Dallas Semiconductor的1-Wire協議,1-Wire協議可使包括電池管理、溫度管理、存儲器、iButton?在內的多種Dallas Semiconductor器件協調工作。本應用筆記給出了基于PIC16F628的1-Wire通信子程序,并對其時序及其它相關內容進行了詳細介紹。為方便起見,所有的時鐘頻率假定為4MHz。大家知道這個頻率也是許多PIC的內部時鐘頻率。附錄A是這些所有子程序都包含的一個文件,附錄B是PIC16F628從高精度鋰電池監視器DS2761讀取數據的一段匯編語言代碼。這里要說明的一點是,本應用筆記僅僅適合于常規速度的1-Wire通信。通用宏指令
主機端1-Wire協議的實現,GPIO只需要兩個狀態即可,即高阻態和邏輯低電平,下面這一小段匯編程序就是用來實現這個功能的。PIC16F628有兩組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_LMACRO ;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這兩段代碼都是作為宏指令來編寫的。把它們寫成宏指令,在匯編源代碼中通過一個宏指令調用即可自動插入這些代碼,這樣就減少了代碼重寫的次數。第一個宏指令OW_HIZ的功能就是把DQ強制變為高阻態。由于TRISB寄存器位于數據存儲器的bank 1,所以第一步就是選擇數據存器的bank 1。接著通過把TRISB寄存器的DQ位置位,使DQ輸出驅動器變為高阻態。代碼的最后一行變回到數據存儲器的bank 0,最后一行不是必需的,但這里還是加進去了,以便所有的宏指令和功能調用之后數據存儲器都處在一個確定的狀態。
第二個宏指令OW_LO的功能就是把DQ強制變為低電平。首先選擇數據存儲器的bank 0,這樣PORTB寄存器就被尋址。PORTB寄存器是數據存儲器,當設置作為輸出時,它包含了那些TRISB中配置為輸出引腳的強制輸出值。
將PORTB的DQ位清零,這樣引線就強制變為低電平。最后選擇數據存器的bank 1,PORTB寄存器的DQ位清零,使其用作輸出驅動。和其它一樣,宏指令以選擇數據存儲器的bank 0結束。
最后的宏指令WAIT用于產生1-Wire信令所需要的延時。WAIT可產生5μs的整數倍的延時。在這個宏指令中,先簡單計算出所需的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的延時,然后運行6次WAIT5U的前4行,每次產生5μs的延時,總延時為30μs,最后一圈的WAIT5U需要6μs,然后就返回到WAIT宏指令,這樣總的處理時間就是30 + 4 + 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通信的所有過程都是從主機發的一個復位脈沖開始,隨后跟著從機的應答檢測脈沖(presence detect pulse)。 圖1對這個事務處理進行了闡述。初始化序列可通過PIC發出,很簡單,對應的匯編代碼如圖1所示。初始化、讀操作、寫操作的時序參數已在表1中列出。在本文的后面部分也將以這些參數為參考。
圖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 0OW_RESET子程序從確保DQ引腳處于高阻態開始,這樣就可以通過上拉電阻把DQ拉為高電平。隨后清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口線上發送的位進行計數。從DSTXLP開始,PIC才送出數據。開始時不管發送的電平是高是低,DQ引腳都變低電平3μs,這樣就可滿足tLOW1的要求。隨后IOBYTE的LSB移位至CARRY位,然后檢測是0還是1。如果CARRY是1,TRISB的DQ位置位,引腳變為高阻態,線路被上拉電阻拉為高電平。如果CARRY是0,線路就維持低電平。之后又引入60μs的延時以便在tLOW0在最小值時仍能正常工作。60μs的等待之后,該引腳變為高阻態,之后又是2μs的附加延時以便上拉電阻復原。最后COUNT減1。如果COUNT寄存器的值成了0,表示所有的數據已經發送完畢,子程序結束。如果COUNT寄存器的值不是0,就從DSTXLP開始繼續發送下一位數據。關于如何在程序中寫入0或寫入1參見圖2。
圖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 01-Wire通信的最后一個子程序是DSRXBYTE,主要功能是從從器件接收信息,其代碼如圖3所示。在DQ有所動作之前首先把COUNT寄存器初始化為8,表示要接收的位數。開始時DSRXLP首先把DQ引腳變為低電平,向從器件發出信號,表示已經做好接收數據的準備。該線保持低電平6μs,通過將DQ線置為高阻態來釋放口線,隨后PIC在采樣數據線之前要再等待4μs。當口線電平變低之后,在OW_LO存在1行代碼,在OW_HIZ之中存在3行代碼。一行代碼的處理時間為1μs,所有的時間加在一起就是1 + 6 + 3 + 4 = 14μs,剛好比15μs的tRDV低。PORTB讀取之后,DQ位被屏蔽,該寄存器進行加法運算直到255,強制CARRY位去鏡像DQ位,然后CARRY位移位至保存接收數據的IOBYTE。一旦這個字節被存儲起來,就需要再引入50μs的延時,以保證滿足tSLOT的要求。最后檢查是判斷COUNT寄存器是否為零。如果為零,則表明已讀完8位,退出子程序;否則,轉到DSRXLP處重復這個循環。讀0和讀1的過程如圖3所示。
圖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<小結
Microchip微控制器的PICmicro可以很容易地實現Dallas Semiconductor的1-Wire通信協議。1-Wire數據傳輸的實現,只需要GPIO的兩個狀態。PIC有多個GPIO,因此很容易就可完成這樣的工作。1-Wire通信有3個基本的字程序:初始化、讀數據、寫數據。本文對這3個子程序完整詳細地作了介紹,用它可以完成常規速度的1-Wire通信,這樣就可使PIC與Dallas Semiconductor的任何1-Wire器件接口。文后的附錄A是一個3個子程序的傳統頭文件,附錄B則是PIC16F628與高精度鋰電池監視器DS2761相連的一段匯編小程序。
附錄A:1-Wire包含FILE (1W_16F6X.INC)
; ******************************************************* ; ; Dallas 1-Wire Support for PIC16F628 ; ; Processor has 4MHz clock and 1μs per instruction cycle. ; ; ******************************************************* ; ******************************************************* ; Dallas Semiconductor 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_LMACRO 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 ; ******************************************************* ; Dallas Semiconductor 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<附錄B:PIC16F628至DS2761匯編代碼(PIC_2_1W.ASM)
; ******************************************* ; ; Dallas Semiconductor PIC code ; ; This code will interface a PIC16F628 microcontroller to ; a DS2761 High-Precision Li+ Battery Monitor ; ; *******************************************; ; ; VCC ; ^ ; | ; | ; / ; \ Rpup ; / ; \ ; | ; 16F628 | DS2761 ; RB1 (pin 7) ------------------------------ DQ (pin 7) ; ; *******************************************; ;--------------------------------------------------------- ; List your processor here. list p=16F628 ; Include the processor header file here. #include;--------------------------------------------------------- ; 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 DS2761 Current Register MSB address (0x0E) CALL DSRXBYTE ; Read the DS2761 Current Register MSB MOVF IOBYTE,W MOVWF PICMSB ; Put the Current MSB into file PICMSB CALL DSRXBYTE ; Read the DS2761 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
評論
查看更多