;*************************************************************** ;*************************************************************** ;Programm zum Auslesen verschiedener Sensoren (u.a. DS1820) ; ; Hanno Rein - http://www.hanno-rein.de - August 2004 ; ;*************************************************************** ;*************************************************************** ;*************************************************************** ;********** HEADER ********************************************* __CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC list p=16f870 #include ERRORLEVEL -302 ;*************************************************************** ;********** Variablen und Konstanten *************************** onewire equ 1 ;1 Wire an RB1 ow_counter1 equ 0x22 ow_counter2 equ 0x23 ow_write equ 0x24 ow_read equ 0x25 ow_temp equ 0x26 ow_sign equ 0x27 ow_einer equ 0x28 ow_zehner equ 0x29 ow_hunderter equ 0x2A ow_calctemp equ 0x2F ws_min equ 0x31 ws_count equ 0x32 ws_max equ 0x33 ws_min_old equ 0x34 ws_max_old equ 0x35 ra_count equ 0x36 ra_last equ 0x37 ;*************************************************************** ;********** PROGRAMM ******************************************* org 0 ; USART initialisieren BSF STATUS,RP0 ; Bank 1 MOVLW 0x20 ; MOVWF TXSTA ; MOVLW D'10' ; = 57 kbps bei 10 MHz MOVWF SPBRG BSF TXSTA, BRGH ; BCF STATUS,RP0 ; Bank 0 MOVLW 0x90 ; Empfänger: RS232 MOVWF RCSTA ; return ; ADC initialisieren movlw B'00000000' ; RA0, RA1 = input, vref = vdd movwf ADCON1 movlw B'10000000' ; 10 MHz, ausschalten movwf ADCON0 ; Timer1 initialisieren movlw B'00000111' ; Timer1 auf RC0 legen, teiler 1:1, kein verstärker, kein sync movwf T1CON clrf ws_max movlw D'254' movwf ws_min movlw D'1' movwf ws_count ; Regenmesser initialisieren bcf ra_last,0 btfsc PORTA,4 bsf ra_last,0 clrf ra_count ; mal etwas via RS232 ausgeben.. :-) Call newline Call newline movlw 'S' CaLL RS232out movlw 'T' CaLL RS232out movlw 'A' CaLL RS232out movlw 'R' CaLL RS232out movlw 'T' CaLL RS232out call newline call newline Loop: ; Der Überischt halber mit Funktionsaufrufen CALL READHU CALL READWD CALL READTIMER1 CALL READRAIN CALL READTEMP movlw '*' CALL RS232out CALL newline goto Loop ;********** Timer Methoden ************************************* ; Regenmessercounter ausgeben READRAIN movlw 'R' CALL RS232out movlw 'A' CALL RS232out btfsc ra_last,0 goto lastwas1 btfss PORTA,4 goto raweiter incf ra_count,1 bsf ra_last,0 goto raweiter lastwas1: btfsc PORTA,4 goto raweiter incf ra_count,1 bcf ra_last,0 goto raweiter raweiter: movfw ra_count CALL RS232decout CALL newline return ; Windgeschwindigkeit auslesen READTIMER1 movlw 'W' CALL RS232out movlw 'S' CALL RS232out CLRF TMR1H CLRF TMR1L bsf T1CON, TMR1ON ;Timer an clrf ow_counter1 movlw D'244' ; = 1s messzeit movwf ow_counter2 CaLL OW_LONG_WAIT bcf T1CON, TMR1ON ;Timer aus movf TMR1L ,0 CALL RS232decout CALL newline movf TMR1L ,0 subwf ws_min ,0 btfss STATUS ,C goto notmin movf TMR1L ,0 movwf ws_min notmin: incf ws_max ,0 subwf TMR1L ,0 btfss STATUS ,C goto notmax movf TMR1L ,0 movwf ws_max notmax: ; Maximum ausgeben movlw 'W' CALL RS232out movlw 'H' CALL RS232out movf ws_max_old ,0 CALL RS232decout CALL newline ; Minimum ausgeben movlw 'W' CALL RS232out movlw 'L' CALL RS232out movf ws_min_old ,0 CALL RS232decout CALL newline decfsz ws_count,1 return movlw D'100' movwf ws_count movf ws_min,0 movwf ws_min_old movf ws_max,0 movwf ws_max_old clrf ws_max movlw D'254' movwf ws_min return ;********** ADC Methoden *************************************** ; Windrichtung auslesen READWD movlw 'W' CALL RS232out movlw 'D' CALL RS232out BCF ADCON0, CHS0 ; Eingang wählen CALL READADC return ; Feuchtigkeit auslesen READHU movlw 'H' CALL RS232out movlw 'U' CALL RS232out BSF ADCON0, CHS0 ; Eingang wählen CALL READADC return READADC: BSF ADCON0, ADON ; einschalten movlw D'40' ; Pause nach Portwechsel (80 uS) Call OW_WAIT_W BSF ADCON0, GO ; start ADCloop2: BTFSC ADCON0, GO GOTO ADCloop2 BCF ADCON0, ADON ; ausschalten movfw ADRESH CALL RS232decout CALL newline return ;********** RS232 Methoden ************************************* ; Das Arbeitsregister wird seriell ausgegeben. RS232decout Call BIN2DEC movf ow_hunderter,0 addlw D'48' Call RS232out movf ow_zehner,0 addlw D'48' Call RS232out movf ow_einer,0 addlw D'48' Call RS232out return RS232out btfss PIR1,TXIF ; kann ich senden? goto RS232out movwf TXREG return ; Neue Zeile newline movlw '\n' CALL RS232out movlw '\r' CALL RS232out return ;********** 1 Wire Methoden ************************************ ; schält onewire-Pin auf Eingang/Ausgang INP: BSF STATUS, RP0 ; Bank 1 BSF TRISB, onewire BCF STATUS, RP0 ; Bank 0 return OUT: BSF STATUS, RP0 ; Bank 1 BCF TRISB, onewire BCF STATUS, RP0 ; Bank 0 BCF PORTB, onewire ; Bus = low return ;********** Führt einen Reset des OW-Busses durch ************** RESET: CALL OUT movlw D'150' ; Reset 600uS CALL OW_WAIT_W CALL INP ; wait again 600uS movlw D'150' CALL OW_WAIT_W return ;********** Gibt Byte an OW aus ******************************** ; Gibt das Arbeitsregister an den OW Bus aus. Write2OW: movwf ow_write movlw D'8' movwf ow_counter2 writeloop: Call OUT BTFSC ow_write,0 ; 1? goto Write1 movlw D'16' ; Schreibe 0 CALL OW_WAIT_W Call INP goto weiter Write1: ; Schreibe 1 nop nop nop nop nop Call INP movlw D'15' ; wait 60 us CALL OW_WAIT_W weiter: rrf ow_write,1 ; rechtsshift decfsz ow_counter2,1 goto writeloop rrf ow_write,1 rrf ow_write,1 return ;********** Lese Byte von OW ein ******************************* ; Ergebnis ist in ow_read gespeichert. ReadOWByte movlw D'8' movwf ow_counter2 CLRF ow_read readloop: Call OUT nop nop nop nop CALL INP movlw D'1' ; wait 4 us CALL OW_WAIT_W rrf ow_read, 1 btfsc PORTB, onewire bsf ow_read, 0 movlw D'12' ; wait 48 us CALL OW_WAIT_W decfsz ow_counter2,1 goto readloop rrf ow_read,1 rrf ow_read,1 movf ow_read,0 ; return with value in w return ;********** Lese Temperatur von OW ein ************************** ; liest Temperatur von DS1820 ein. Es wird das "Skip Rom" Command ; benutzt. Die Routine funktioniert also nur, wenn nur ein Sensor ; an dem Bus angeschlossen ist! Parasite Power Mode tut nicht. (warum?!) READTEMP: movlw 'T' CALL RS232out Call RESET movlw 0xCC ; skip ROM command Call Write2OW movlw 0x44 ; convert Temperature Call Write2OW Call INP ; provide power (obsolet) movlw D'182' ; wait 750 ms (to convert temp) movwf ow_counter2 Call OW_LONG_WAIT ; zweiter Resetpuls Call RESET movlw 0xCC ; skip ROM command Call Write2OW movlw 0xBE ; read Scratchpad command Call Write2OW ; get Data Call ReadOWByte ; Temp movwf ow_temp Call ReadOWByte ; Sign movwf ow_sign Call ReadOWByte ; T_H Call ReadOWByte ; T_L Call ReadOWByte ; reserved Call ReadOWByte ; reserved ; output Data movlw '+' btfsc ow_sign,0 ; Minus-Temperatur? NEGF ow_temp,1 ; -> Zweierkoplement bilden btfsc ow_sign,0 ; Minus-Temperatur? movlw '-' ; -> minus ausgeben Call RS232out rrf ow_temp,0 CALL RS232decout ; output Dezimalpunkt movlw '.' Call RS232out ; last important byte Call ReadOWByte ; count remain Call RS232decout Call newline return ;********** Binar zu Dezimal *********************************** ; erwartet zu konvertierenden Wert in w und speichert Ergebnis ; in ow_einer, ow_zehner, ow_hunderter BIN2DEC: clrf ow_einer clrf ow_zehner clrf ow_hunderter movwf ow_calctemp movlw D'100' hundertercounter: incf ow_hunderter, 1 subwf ow_calctemp, 1 btfsc STATUS, C goto hundertercounter ; carry ? decf ow_hunderter, 1 addwf ow_calctemp, 1 movlw D'10' zehnercounter: incf ow_zehner, 1 subwf ow_calctemp, 1 btfsc STATUS, C goto zehnercounter ; carry ? decf ow_zehner, 1 addwf ow_calctemp, 0 movwf ow_einer ; Rest in einer return ;********** Wartemethoden ************************************** ; alle auf 10 Mhz ausgelegt OW_WAIT_W: movwf ow_counter1 OW_WAIT: ; Dauer: ow_counter1*4+1.2 uSec nop nop nop nop nop nop nop DECFSZ ow_counter1,1 goto OW_WAIT return OW_LONG_WAIT: ; Dauer ca: ow_counter2*4.10 mSec call OW_WAIT call OW_WAIT call OW_WAIT call OW_WAIT DECFSZ ow_counter2,1 goto OW_LONG_WAIT return ;*************************************************************** ;********** ENDE *********************************************** end