;************************************************* www.x-robotics.com ******* ;---------------- RUTINAS SENSOR HUMEDAD Y TEMPERATURA SHT11 ---------------- ;**************************************************************************** ;Comandos: ;sht11_Humedad :Lectura Humedad 16bits devuelve humedad en RH ;sht11_Set8bits :Configura el sensor para trabajar en modo 8 bits ;sht11_Set14bits :Configura el sensor para trabajar en modo 14 bits ;sht11_HeaterON :Conecta el calentador interno anticondensacion ;sht11_HeaterOFF :Desconecta el calentador interno anticondensacion ;sht11_Reset :Resetea el sensor sht11 ; ; ;---------------------------------------------------------------------------- ; Revision : 1.00 Fecha: 6/1/2005 Programa para : PIC16F876 ; CPU Clock : 4 MHz Tiempo instruccion : 1uS ; WDT : OFF Tipo de reloj : XT ; Code Prot : OFF cfg USART rs232 ; none ; Autor : Daniel C. Martin -> ionitron@x-robotics.com <- ;************************************************* www.x-robotics.com ******* sincbit EQU 0x50 ;contador envio de bits Wdata EQU 0x51 ;variable de intercambio de datos CMData EQU 0x52 ;variable de comandos RXmsb EQU 0x53 ;registros de recepcion de datos RXlsb EQU 0x54 RH EQU 0x55 ;Porcentaje de Humedad Relativa ACCaLO equ 0x61 ;Variables de calculos ACCaHI equ 0x60 ACCbLO equ 0x63 ACCbHI equ 0x62 ACCcLO equ 0x65 ACCcHI equ 0x64 ACCdLO equ 0x67 ACCdHI equ 0x66 temp equ 0x68 Flags equ 0x69 ;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ; ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ;Comandos rapidos------------------------------------------------------------- sht11_Humedad ;LECTURA HUMEDAD 2 bytes call SHT11_start ;Inicio de transmision movlw b'00000101' call SHT11_CMD ;Envio: Lectura de humedad call waitACK ;espera que llegue ACK desde el sensor call adqtime ;espera que pase el tiempo de adquisicion call readMSB ;lee el byte alto call setACK call readLSB ;lee el byte bajo call setNACK call CalcRH ;Calcula %RH y ajusta linealidad ;retorna variable RH con dato return ;Retorna sht11_Set8bits ;configura el sensor para trabajar en modo 8 bits call SHT11_start ;Inicio de transmision movlw b'00000111' ;------------------------------------- call SHT11_CMD ;Envio: Lectura en config interna call waitACK ;espera que llegue ACK desde el sensor call readMSB ;lee el byte alto (Dato) call waitACK ;------------------------------------- call readLSB ;lee el byte bajo (CheckSum) call setNACK call SHT11_start ;Inicio de transmision movlw b'00000110' ;------------------------------------- call SHT11_CMD ;Envio: Escritura en config interna call waitACK ;espera que llegue ACK desde el sensor bsf RXmsb,0 ;pone un 1 en el bit adecuado... movf RXmsb,W ;y carga el stats modificado del sensor call SHT11_CMD ;Envio: modificacion de status call waitACK ;espera que llegue ACK desde el sensor ;call SHT11_start ;Inicio de transmision ;movlw b'00000111' ;------------------------------------- ;call SHT11_CMD ;Envio: Lectura en config interna ;call waitACK ;espera que llegue ACK desde el sensor ;call readLSB ;lee el byte bajo ;call setNACK ;------------------------------------- return sht11_Set14bits ;configura el sensor para trabajar en modo 14 bits call SHT11_start ;Inicio de transmision movlw b'00000111' ;------------------------------------- call SHT11_CMD ;Envio: Lectura en config interna call waitACK ;espera que llegue ACK desde el sensor call readMSB ;lee el byte alto (Dato) call waitACK ;------------------------------------- call readLSB ;lee el byte bajo (CheckSum) call setNACK call SHT11_start ;Inicio de transmision movlw b'00000110' ;------------------------------------- call SHT11_CMD ;Envio: Escritura en config interna call waitACK ;espera que llegue ACK desde el sensor bcf RXmsb,0 ;pone un 1 en el bit adecuado... movf RXmsb,W ;y carga el stats modificado del sensor call SHT11_CMD ;Envio: modificacion de status call waitACK ;espera que llegue ACK desde el sensor return sht11_HeaterON ;conecta el calentador interno anticondensacion call SHT11_start ;Inicio de transmision movlw b'00000111' ;------------------------------------- call SHT11_CMD ;Envio: Lectura en config interna call waitACK ;espera que llegue ACK desde el sensor call readMSB ;lee el byte alto (Dato) call waitACK ;------------------------------------- call readLSB ;lee el byte bajo (CheckSum) call setNACK call SHT11_start ;Inicio de transmision movlw b'00000110' ;------------------------------------- call SHT11_CMD ;Envio: Escritura en config interna call waitACK ;espera que llegue ACK desde el sensor bsf RXmsb,2 ;pone un 1 en el bit adecuado... movf RXmsb,W ;y carga el stats modificado del sensor call SHT11_CMD ;Envio: modificacion de status call waitACK ;espera que llegue ACK desde el sensor return sht11_HeaterOFF ;desconecta el calentador interno anticondensacion call SHT11_start ;Inicio de transmision movlw b'00000111' ;------------------------------------- call SHT11_CMD ;Envio: Lectura en config interna call waitACK ;espera que llegue ACK desde el sensor call readMSB ;lee el byte alto (Dato) call waitACK ;------------------------------------- call readLSB ;lee el byte bajo (CheckSum) call setNACK call SHT11_start ;Inicio de transmision movlw b'00000110' ;------------------------------------- call SHT11_CMD ;Envio: Escritura en config interna call waitACK ;espera que llegue ACK desde el sensor bcf RXmsb,2 ;pone un 1 en el bit adecuado... movf RXmsb,W ;y carga el stats modificado del sensor call SHT11_CMD ;Envio: modificacion de status call waitACK ;espera que llegue ACK desde el sensor return sht11_Reset ;Resetea el sensor sht11 call SHT11_start ;Inicio de transmision movlw b'00011110' ;------------------------------------- call SHT11_CMD ;Envio: Lectura en config interna ;espera de 11mS al menos despues de esta instruccion return ;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ; ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() ;============================================================================== ;-------------------------------R U T I N A S---------------------------------- ;/////////////////////////////////////////////////////////////////////////// ;Protocolo de inicio de transmision SHT11_start ;transmision start bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf STATUS,RP1 bcf TRISB,0 ;puertos como salida bcf TRISB,1 bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bsf PORTB,0 ;DATA a 1 (por defecto) nop ;espera un poco nop bsf PORTB,1 ;CLK bcf PORTB,0 ;DATA (pulso bajo) bcf PORTB,1 ;CLK bsf PORTB,1 ;CLK bsf PORTB,0 ;DATA (por defecto alto) bcf PORTB,1 ;CLK return ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// ;Manda comando de lectura de humedad SHT11_CMD movwf CMData ;guarda el comando en variable clrf sincbit bcf STATUS,C ;borra carry bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf TRISB,0 ;pone DATA port,0 como salida bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- cont_send rlf CMData,F ;rota a la izquierda, bit alto en carry ;. . . . . . . . . . . . . . . . . . . . . . ;envio de datos segun el protocolo del sht11 send_data btfsc STATUS,C ;comprueba si es 1 o 0 goto uno ; ; cero bcf PORTB,1 ;SCK falling edge -_ bcf PORTB,0 ;DATA change bsf PORTB,1 ;SCK rising edge _- goto sht11_compTX ;salta uno bcf PORTB,1 ;SCK falling edge -_ bsf PORTB,0 ;DATA change bsf PORTB,1 ;SCK rising edge _- ;. . . . . . . . . . . . . . . . . . . . . . ;Comprobacion para 8 rotaciones, una por bit del comando. sht11_compTX movlw .7 ;comprobacion 8 bits subwf sincbit,W ;Compara btfsc STATUS,Z ;Es el ultimo? return ;Si, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> incf sincbit,f ;Incrementa numero de sincbit goto cont_send ;Vuelve a escribir ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// ;Espera la llegada de ACK desde el sensor waitACK ;espera el ACK del sensor bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bsf TRISB,0 ;pone DATA port,0 como entrada bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- nop nop nop nop ACKrx bcf PORTB,1 ;SCK falling edge nop nop ;5uS de retardo nop nop nop bsf PORTB,1 ;SCK rising edge btfsc PORTB,0 ;comprueba data goto ACKrx ;NO, bucle bcf PORTB,1 ;SCK falling edge estado bajo por defecto return ;ack desde SHT11 detectado y llegada de datos adqtime btfsc PORTB,0 ;comprueba data goto adqtime ;NO, bucle return ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// ;LECTURA DE DATOS DESDE EL SHT11 (Byte alto) readMSB clrf RXmsb ;limpia registro bsf RXmsb,0 ;pone un 1 que indicara en carry el final leemsb bcf PORTB,1 ;SCK falling edge bsf PORTB,1 ;SCK rising edge btfss PORTB,0 ;lee data goto es_ceromsb es_unomsb rlf RXmsb,f ;rota a la izquierda bsf RXmsb,0 ;pone un 1 en el bit 0 btfss STATUS,C ;salio la marca por carry? goto leemsb ;continua y captura el siguiente bit return es_ceromsb rlf RXmsb,f ;rota a la izquierda bcf RXmsb,0 ;pone un 0 en el bit 0 btfss STATUS,C ;salio la marca por carry? goto leemsb ;continua y captura el siguiente bit return ;retorna ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// ;LECTURA DE DATOS DESDE EL SHT11 (Byte bajo) readLSB clrf RXlsb ;limpia registro bsf RXlsb,0 ;pone un 1 que indicara en carry el final leelsb bcf PORTB,1 ;SCK falling edge bsf PORTB,1 ;SCK rising edge btfss PORTB,0 ;lee data goto es_cerolsb es_unolsb rlf RXlsb,f ;rota a la izquierda bsf RXlsb,0 ;pone un 1 en el bit 0 btfss STATUS,C ;salio la marca por carry? goto leelsb ;continua y captura el siguiente bit return es_cerolsb rlf RXlsb,f ;rota a la izquierda bcf RXlsb,0 ;pone un 0 en el bit 0 btfss STATUS,C ;salio la marca por carry? goto leelsb ;continua y captura el siguiente bit return ;retorna ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// setACK bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf TRISB,0 ;pone DATA port,0 como salida bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf PORTB,1 ;SCK falling edge bcf PORTB,0 ;DATA change nivel logico 0 bsf PORTB,1 ;SCK rising edge nop nop nop nop nop nop nop nop ;bsf PORTB,0 ;DATA change nivel logico 1(reposo) bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bsf TRISB,0 ;pone DATA port,0 como entrada bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- return ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// setNACK bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf TRISB,0 ;pone DATA port,0 como salida bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bcf PORTB,1 ;SCK falling edge bsf PORTB,0 ;DATA change nivel logico 0 bsf PORTB,1 ;SCK rising edge nop bcf PORTB,1 ;baja clk bsf STATUS,RP0 ;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_- bsf TRISB,0 ;pone DATA port,0 como entrada bcf STATUS,RP0 ;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- return ;=========================================================================== ;--------------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////////////// CalcRH ;RH% calculos de linealidad. (a*RH%+b)/256 movlw .0 ;0 ;MultiplicLO movwf ACCaHI movf RXlsb,W ;lectura 8 bits ;MultiplicHI movwf ACCaLO movlw .108 subwf RXlsb,W btfsc STATUS,C goto calcA2 ;-------------- Si lectura menor o igual a 107... calcA1 movlw .143 ;A ;ResultLLO movwf ACCbLO movlw .0 ;A ;ResultHHI movwf ACCbHI call D_mpyS ;multiplica (A*RH) ;el resultado esta en ACCcHI,ACCcLO ;resta 512 del resultado ;comprueba si el dato es mayor de 512 ;si fuera menor.. pone como resultado 512 ;si es mayor.. resta 2 a MSB que equivale a 512 ;del dato de 16bits movlw .3 ;resta 2 subwf ACCcHI,W btfss STATUS,C goto menord2 ;mayor de 2 mayord2 ;si es mayor de 512.. resta 512 al resultado ;y luego comprueba que el resultado no sea menor de 512 movlw .2 subwf ACCcHI,F ;resta 512 al dato alto movlw .3 ;si el resultado es subwf ACCcHI,W ;menor de 512... btfss STATUS,C goto menord2 ;mayor de 2 goto calccont ;si es mayor continua menord2 ;si es menor de 2 pone como resultado 512 movlw .2 movwf ACCcHI ;resultado=512 clrf ACCcLO goto calccont ;continua con los calculos goto calccont ;-------------- Si lectura mayor o igual a 108... calcA2 movlw .111 ;A ;ResultLLO movwf ACCbLO movlw .0 ;A ;ResultHHI movwf ACCbHI call D_mpyS ;multiplica (A*RH) ;suma 2893 al resultado ;suma 11 a MSB(mas acarrero de LSB) y 77 a LSB ;MSB=ACCcHI LSB=ACCcLO para 16bits de resolucion movlw .11 addwf ACCcHI ;suma 11 a MSB movlw .77 ;suma 77 a LSB y si hay acarreo addwf ACCcLO ;se lo suma a LSB btfsc STATUS,C ;comprueba el acarreo incf ACCcHI ;suma el acarreo a MSB ;no hay acarreo y salta calccont ;continua con el calculo de %RH ;ahora divide el resultado de 16bits / 256 ;El resultado completo de 32 bits = ( ACCbHI,ACCbLO,ACCcHI,ACCcLO ) ;el resutlado despues de rotar 8 bits es el mismo que ;el byte (ACCcHI) correspondiente al byte 2 menos significativo movf ACCcHI,W movwf RH ;RH = Relative Humidity return ;retorna con el resultado calculado ;================================================================================= ;================================================================================= ;================================================================================= ;******************************************************************* ; Double Precision Multiplication ; ; ( Optimized for Code Size : Looped Code ) ; ;*******************************************************************; ; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCb,ACCc ( 32 bits ) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_mpy ; (d) The 32 bit result is in location ( ACCbHI,ACCbLO,ACCcHI,ACCcLO ) ;*******************************************************************; ; ; ;******************************************************************* ; Double Precision Multiply ( 16x16 -> 32 ) ; ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word ; in ACCb ( ACCbHI,ACCbLO ) and low word in ACCc ( ACCcHI,ACCcLO ). ; D_mpyS ;results in ACCb(16 msb's) and ACCc(16 lsb's) call setupmult bcf STATUS,C mloop rrf ACCdHI,F ;rotate d right rrf ACCdLO,F btfss STATUS,C ;need to add? goto No_add movf ACCaLO,W ; Addition ( ACCb + ACCa -> ACCb ) addwf ACCbLO,F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI,F movf ACCaHI,W addwf ACCbHI,F ;add msb No_add rrf ACCbHI,F rrf ACCbLO,F rrf ACCcHI,F rrf ACCcLO,F decfsz temp,F ;loop until all bits checked goto mloop goto end1 ; Double Precision Addition ( ACCb + ACCa -> ACCb ) ; D_add bcf Flags,C ;Clear temp Carry bit movf ACCaLO,W ; Addition ( ACCb + ACCa -> ACCb ) addwf ACCbLO,F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI,F btfsc STATUS,C bsf Flags,C movf ACCaHI,W addwf ACCbHI,F ;add msb btfsc Flags,C bsf STATUS,C return ; ; ;******************************************************************* ; setupmult movlw .16 ; for 16 shifts movwf temp movf ACCbHI,W ;move ACCb to ACCd movwf ACCdHI movf ACCbLO,W movwf ACCdLO clrf ACCbHI clrf ACCbLO return ; ;**************************************************************** end1 return