引言
Microchip公司的PICmicro微控制器(PIC)已經(jīng)成為低功耗、低成本系統(tǒng)解決方案的主流選擇。這些微處理器有多個通用輸入輸出引腳(GPIO),通過對這些引腳進行簡單組合就可實現(xiàn)Dallas Semiconductor的1-Wire協(xié)議,1-Wire協(xié)議可使包括電池管理、溫度管理、存儲器、iButton?在內(nèi)的多種Dallas Semiconductor器件協(xié)調(diào)工作。本應用筆記給出了基于PIC16F628的1-Wire通信子程序,并對其時序及其它相關(guān)內(nèi)容進行了詳細介紹。為方便起見,所有的時鐘頻率假定為4MHz。大家知道這個頻率也是許多PIC的內(nèi)部時鐘頻率。附錄A是這些所有子程序都包含的一個文件,附錄B是PIC16F628從高精度鋰電池監(jiān)視器DS2761讀取數(shù)據(jù)的一段匯編語言代碼。這里要說明的一點是,本應用筆記僅僅適合于常規(guī)速度的1-Wire通信。通用宏指令
主機端1-Wire協(xié)議的實現(xiàn),GPIO只需要兩個狀態(tài)即可,即高阻態(tài)和邏輯低電平,下面這一小段匯編程序就是用來實現(xiàn)這個功能的。PIC16F628有兩組GPIO端口:PORTA和PORTB,其中任何一組都可以用來完成1-Wire通信。在這個例子中,選擇了PORTB,同時在匯編代碼中也配置了一個常數(shù)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這兩段代碼都是作為宏指令來編寫的。把它們寫成宏指令,在匯編源代碼中通過一個宏指令調(diào)用即可自動插入這些代碼,這樣就減少了代碼重寫的次數(shù)。第一個宏指令OW_HIZ的功能就是把DQ強制變?yōu)楦咦钁B(tài)。由于TRISB寄存器位于數(shù)據(jù)存儲器的bank 1,所以第一步就是選擇數(shù)據(jù)存器的bank 1。接著通過把TRISB寄存器的DQ位置位,使DQ輸出驅(qū)動器變?yōu)楦咦钁B(tài)。代碼的最后一行變回到數(shù)據(jù)存儲器的bank 0,最后一行不是必需的,但這里還是加進去了,以便所有的宏指令和功能調(diào)用之后數(shù)據(jù)存儲器都處在一個確定的狀態(tài)。
第二個宏指令OW_LO的功能就是把DQ強制變?yōu)榈碗娖健J紫冗x擇數(shù)據(jù)存儲器的bank 0,這樣PORTB寄存器就被尋址。PORTB寄存器是數(shù)據(jù)存儲器,當設置作為輸出時,它包含了那些TRISB中配置為輸出引腳的強制輸出值。
將PORTB的DQ位清零,這樣引線就強制變?yōu)榈碗娖健W詈筮x擇數(shù)據(jù)存器的bank 1,PORTB寄存器的DQ位清零,使其用作輸出驅(qū)動。和其它一樣,宏指令以選擇數(shù)據(jù)存儲器的bank 0結(jié)束。
最后的宏指令WAIT用于產(chǎn)生1-Wire信令所需要的延時。WAIT可產(chǎn)生5μs的整數(shù)倍的延時。在這個宏指令中,先簡單計算出所需的5μs延時的整倍數(shù),然后在WAIT5U做相應次數(shù)的循環(huán)。WAIT5U子程序?qū)⒃谙乱还?jié)討論。對于WAIT內(nèi)的每一條指令,所用處理時間都進行了注釋,以方便理解延時是怎樣實現(xiàn)的
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定時協(xié)議中有一些必須遵守的特殊定時限制。為方便產(chǎn)生特殊的延時,可采用子程序WAIT5U來產(chǎn)生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宏指令一起使用,即可產(chǎn)生常用的延時。例如如果需要40μs的延時,就調(diào)用WAIT 0.40。先運行WAIT的前3行,產(chǎn)生4μs的延時,然后運行6次WAIT5U的前4行,每次產(chǎn)生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通信的所有過程都是從主機發(fā)的一個復位脈沖開始,隨后跟著從機的應答檢測脈沖(presence detect pulse)。 圖1對這個事務處理進行了闡述。初始化序列可通過PIC發(fā)出,很簡單,對應的匯編代碼如圖1所示。初始化、讀操作、寫操作的時序參數(shù)已在表1中列出。在本文的后面部分也將以這些參數(shù)為參考。
圖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引腳處于高阻態(tài)開始,這樣就可以通過上拉電阻把DQ拉為高電平。隨后清PDBYTE寄存器,這樣就為隨后的在位檢測脈沖做好了準備。之后DQ變?yōu)榈碗娖?00μs,這就滿足了表1中tRSTL參數(shù)的要求,同時還留出了20μs額外的緩沖時間。把這個引腳變?yōu)榈碗娖街螅只氐礁咦钁B(tài),在開始讀取在位檢測脈沖之前又加入一70μs的延時。這個70μs的延時可以保證無論tPDL、 tPDH如何變化,PIC總能在有效的時間進行取樣。一旦讀到在位檢測脈沖,PDBYTE寄存器就設置為已讀到邏輯狀態(tài)值。DQ引腳再保持高阻態(tài)430μs,以保證滿足tRSTH的要求,還可留出20μs額外的緩沖時間。
1-Wire通信需要的另外一個子程序就是DSTXBYTE,用于向1-Wire從器件發(fā)送數(shù)據(jù)。這個子程序的PIC代碼如圖2所示。這個子程序需要和WREG寄存器中要發(fā)送的數(shù)據(jù)一起調(diào)用。首先將要發(fā)送的數(shù)據(jù)立即放入IOBYTE寄存器,隨后將COUNT寄存器初始化為8,以用來對要在DQ口線上發(fā)送的位進行計數(shù)。從DSTXLP開始,PIC才送出數(shù)據(jù)。開始時不管發(fā)送的電平是高是低,DQ引腳都變低電平3μs,這樣就可滿足tLOW1的要求。隨后IOBYTE的LSB移位至CARRY位,然后檢測是0還是1。如果CARRY是1,TRISB的DQ位置位,引腳變?yōu)楦咦钁B(tài),線路被上拉電阻拉為高電平。如果CARRY是0,線路就維持低電平。之后又引入60μs的延時以便在tLOW0在最小值時仍能正常工作。60μs的等待之后,該引腳變?yōu)楦咦钁B(tài),之后又是2μs的附加延時以便上拉電阻復原。最后COUNT減1。如果COUNT寄存器的值成了0,表示所有的數(shù)據(jù)已經(jīng)發(fā)送完畢,子程序結(jié)束。如果COUNT寄存器的值不是0,就從DSTXLP開始繼續(xù)發(fā)送下一位數(shù)據(jù)。關(guān)于如何在程序中寫入0或?qū)懭?參見圖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,表示要接收的位數(shù)。開始時DSRXLP首先把DQ引腳變?yōu)榈碗娖?,向從器件發(fā)出信號,表示已經(jīng)做好接收數(shù)據(jù)的準備。該線保持低電平6μs,通過將DQ線置為高阻態(tài)來釋放口線,隨后PIC在采樣數(shù)據(jù)線之前要再等待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位移位至保存接收數(shù)據(jù)的IOBYTE。一旦這個字節(jié)被存儲起來,就需要再引入50μs的延時,以保證滿足tSLOT的要求。最后檢查是判斷COUNT寄存器是否為零。如果為零,則表明已讀完8位,退出子程序;否則,轉(zhuǎn)到DSRXLP處重復這個循環(huán)。讀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<小結(jié)
Microchip微控制器的PICmicro可以很容易地實現(xiàn)Dallas Semiconductor的1-Wire通信協(xié)議。1-Wire數(shù)據(jù)傳輸?shù)膶崿F(xiàn),只需要GPIO的兩個狀態(tài)。PIC有多個GPIO,因此很容易就可完成這樣的工作。1-Wire通信有3個基本的字程序:初始化、讀數(shù)據(jù)、寫數(shù)據(jù)。本文對這3個子程序完整詳細地作了介紹,用它可以完成常規(guī)速度的1-Wire通信,這樣就可使PIC與Dallas Semiconductor的任何1-Wire器件接口。文后的附錄A是一個3個子程序的傳統(tǒng)頭文件,附錄B則是PIC16F628與高精度鋰電池監(jiān)視器DS2761相連的一段匯編小程序。
附錄A:1-Wire包含F(xiàn)ILE (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
評論
查看更多