;SONOMETRO version 16 final ;Lista de funciones acumuladas por versiones anteriores: muestra valor instantáneo- ;- muestra promedio de los valores mostrados en otro sector del LCD ;Se realiza la coversión a dbA por medio de tabla- ;Reordenamiento de pantalla - se incluye cálculo de temperatura mediante la utilización del LM 35 con amplificador de ganancia 2 ;Se trabaja el conversor AD con 3 entradas analógicas - ; posibilidad de elegir la escala mediante tecla (L o H) cambiando asi el canal del conversor ente RA0 (AN0) y RA3 (AN3). ;Incluye subrutinas de sonido ;alarma sonora programable-correccion de 3 grados anulada ;se calibra escala H ;Se reordenan en subrutinas partes del programa- Se incluye calibracion sonometro ;Se incluye menu de funciones- sonometro+termómetro- timer ;Variante por versión: correcciones finales ;PROGRAMA VALIDO PARA PIC16F818 ;-------------------------------------- ;RECORDAR CAMBIAR DIRECCIONES DE REGISTROS DE PROPOSITO GENERAL A PARTIR DE 20h EN ESTE PIC ;-------------------------------------- ;toma lectura mediante conversor A/D y almacena en registro leido ;muestra en LCD - MUESTRA VALOR DE REGISTRO LEIDO EN DECIMAL 3 DIGITOS - en interfase de 4 bits ;se usara 4 bits MSB del puertob para envio de datos a 4bits - RB4 RB5 RB6 RB7 respectivamente conectados a D4 D5 D6 D7 y RB0 RB1 a RS y E respectivamente- RW va a masa. list p=16f818 #include p16f818.inc portb equ 06h ;el puerto b esta en la posicion 06h de la ram porta equ 05h;el puerto b esta en la posicion 05h de la ram trisa equ 85h ;regis de config de puerto b esta en la direcc 85h de la ram trisb equ 86h ;regis de config de puerto b esta en la direcc 86h de la ram status equ 03h ;registro de estado esta en la direcc 03h de la ram adresh equ 1Eh; registro donde se almacena el resultado alto del conversor adcon0 equ 1Fh; registro del conversor adcon1 equ 9Fh; registro del conversor fsr equ 04h; registro de direccionamiento indirecto indf equ 00h; registro para direccionamiento indirecto ;--comienzan registros de propositos generales----- temp5 equ 20h aux equ 21h; este sera un registro auxiliar para la subrutina instruc/escrib unidad equ 22h; registro unidades decena equ 23h; registro decenas centena equ 24h; registro centenas leido equ 25h; registro leido tempo1 equ 26h ;registro tempo1 esta en la direcc 26h de la ram tempo2 equ 28h ;registro tempo2 esta en la direcc 28h de la ram tempo3 equ 2Ah ;registro tempo3 esta en la direcc 2Ah de la ram -Estos 3 ultimos son para sub espera espc equ 2Bh; registro para retardo dentro de subrutina leercv-factible de eliminar en futuro espc2 equ 2Ch; registro para retardo dentro de subrutina leercv-factible de eliminar en futuro np equ 2Dh; registro de subrutina promedx - es el divisor- leido2 equ 2Eh; registro para guardar valor original de leido aux2 equ 2Fh; registro de subrutina promedionp - guarda el valor acumulado de las sucesivas lecturas bandera equ 30h; registro equivalente a status pero para uso particular - ej se usa en subrutina promednp promedio equ 31h; registro de la subrutina promedionp dcent equ 32h; registro de almacenar dirección de memoria del LCD donde se va a escribir las centenas ddece equ 33h; registro de almacenar dirección de memoria del LCD donde se va a escribir las decenas dunid equ 34h; registro de almacenar dirección de memoria del LCD donde se va a escribir las unidades opc equ 35h; registro de subrutina menu ;--- registros se subrutina reloj----------- ps1 equ 36h ps2 equ 37h ps3 equ 38h ps4 equ 7Dh ;---Fin registros se subrutina reloj----------- ;--- registros se subrutina timer----------- segund equ 7Eh minut equ 7Fh ;--- fin registros se subrutina timer----------- ;------Registros reservados para la tabla de conversión----------- d1 equ 39h d2 equ 3Ah d3 equ 3Bh d4 equ 3Ch d5 equ 3Dh d6 equ 3Eh d7 equ 3Dh d8 equ 3Fh d9 equ 40h d10 equ 41h d11 equ 42h d12 equ 43h d13 equ 44h d14 equ 45h d15 equ 46h d16 equ 47h d17 equ 48h d18 equ 49h d19 equ 4Ah d20 equ 4Bh d21 equ 4Ch d22 equ 4Dh d23 equ 4Eh d24 equ 4Fh d25 equ 50h d26 equ 51h d27 equ 52h d28 equ 53h d29 equ 54h d30 equ 50h d31 equ 51h d32 equ 52h d33 equ 53h d34 equ 51h d35 equ 52h d36 equ 53h d37 equ 54h d38 equ 55h d39 equ 56h d40 equ 57h d41 equ 58h d42 equ 59h d43 equ 5Ah d44 equ 5Bh d45 equ 5Ch d46 equ 5Dh d47 equ 5Eh d48 equ 5Fh d49 equ 60h d50 equ 61h d51 equ 62h d52 equ 63h d53 equ 64h d54 equ 65h d55 equ 66h d56 equ 67h d57 equ 68h d58 equ 69h d59 equ 6Ah d60 equ 6Bh d61 equ 6Ch d62 equ 6Dh d63 equ 6Eh d64 equ 6Fh d65 equ 70h d66 equ 71h d67 equ 72h ;------Fin de registros reservados para la tabla de conversión----------- ;----------registros de subrutina tono1--------- tf1 equ 73h tf2 equ 74h ts1 equ 75h ts2 equ 76h ts3 equ 77h ctperi equ 78h frecu equ 79h durac equ 7Ah ;--------Fin registros de subrutina tono1-------- alarm equ 7Bh; registro de subrutina alarma - guarda el valor de sonar alarma memtemp equ 7Ch; registro que memoriza temperatura al salir de subrutina temperatura ;--Fin de registros de propositos generales----- org 00h; vector de reset goto inicio; va a iniciar el programa principal org 05h ;--------SUBRUTINAS------------- ;Subrutina que manda una instruccion o dato al LCD instruc bcf portb,0; RB0=0 o sea RS=0 es una instruccion para LCD goto dato2 escrib bsf portb,0; RB0=1 o sea RS=1 es una dato para LCD dato2 movwf aux; guarda contenido de w en aux movlw 0fh; carga 00001111 en w andwf portb,1; AND entre w=00001111 y portb y guarda resultado en portb movf aux,0; carga aux en w andlw b'11110000'; AND entre literal 11110000 y w en el cual esta copiado aux (guarda el resultdado en w) iorwf portb,1; OR entre w y portb - guarda resultado en portb bsf portb,1; RB1=1 o sea E=1 habilito LCD call retardo bcf portb,1; RB1=E=0 deshabilita LCD call retardo ;---terminó envio 4 bit MSB------- ;---comienza el envio de 4 bit LSB--- movlw 0fh; carga 00001111 en w andwf portb,1; AND entre w=00001111 y portb - guarda resultado en portb swapf aux,0; intercambia NIBLES de aux y lo guarda en w andlw b'11110000'; AND entre literal 11110000 y w en el cual esta copiado aux con los NIBLES intercambiados (guarda el resultdado en w) iorwf portb,1; OR entre w y portb - guarda resultado en portb bsf portb,1; RB1=1 o sea E=1 habilito LCD call retardo call retardo bcf portb,1; RB1=E=0 deshabilita LCD call retardo ;---termino el envio de lo 4bit LSB--- return ;---------------------------------------- ;Subrutina retardo retardo movlw 0ffh; carga literal 0ffh en w movwf temp5; mueve contenido de w a temp5 decr decfsz temp5,1; decrementa temp5 y guarda resultado en temp5- salta la intruccion siguiente si temp5 es igual a cero goto decr movlw 0ffh; carga literal 0ffh en w movwf temp5; mueve contenido de w a temp5 decr2 decfsz temp5,1; decrementa temp5 y guarda resultado en temp5- salta la intruccion siguiente si temp5 es igual a cero goto decr2 return ;----------------------------------------------------------------------------- ;Subrutina espera - Retardo general- espera nop retardo1 incf tempo1,1 retardo2 incf tempo2,1 retardo3 incf tempo3,1 btfss tempo3,6 goto retardo3 clrf tempo3 btfss tempo2,5 goto retardo2 clrf tempo2 btfss tempo1,4 goto retardo1 clrf tempo1 return ;-----Fin subrutina espera------------------------------------------- ;----SUBRUTINA mostrar que realiza escritura de CENTENAS DECENAS Y UNIDADES para valor instantaneo SPL - promedio SPL - temperatura--o cualquier ;cosa almacenada en los registros CENTENAS DECENAS Y UNIDADES------- ;la dirección de memoria LCD para centenas se toma del registro dcent - ;la dirección de memoria LCD para decenas se toma del registro ddece - ;la dirección de memoria LCD para unidades se toma del registro dunid - ;los registros dcent ddece y dunid se deben cargar antes de llamar a esta subrutina mostrar ;--comienza el envío de CENTENAS--- movlw d'48'; cargo 48 decimal en w addwf centena,1; sumo 48 decimal a centena para que el numero en centena este en ASCII movf dcent,0; carga dirección de memoria del LCD donde se va a mostrar CENTENAS call instruc movf centena,0; btfsc centena,0; si el bit 0 de centenas es 0 salta siguiente instruccion- no muestra centenas cero call escrib; muestra CENTENAS call retardo ;---termino envio de CENTENAS--- ;--comienza el envío deDECENAS--- movlw d'48'; cargo 48 decimal en w addwf decena,1; sumo 48 decimal a decena para que el numero en decena este en ASCII movf ddece,0; carga dirección de memoria del LCD donde se va a mostrar DECENAS call instruc movf decena,0; call escrib; muestra DECENAS call retardo ;---termino envio de DECENAS--- ;--comienza el envío de UNIDADES--- mostrarunidad movlw d'48'; cargo 48 decimal en w addwf unidad,1; sumo 48 decimal a unidad para que el numero en unidad este en ASCII movf dunid,0; carga dirección de memoria del LCD donde se va a mostrar UNIDADES call instruc movf unidad,0; call escrib; muestra unidades ;---termino envio de UNIDADES--- call espera; tiempo de espera para leer comodamente el display return ;--FIN SUBRUTINA -mostrar- que realiza escritura de CENTENAS DECENAS Y UNIDADES - válida para SPL instantáneo SPL promedio - temperatura ;------Subrutina DECIMAL-------------------- ;Convierte el número almacenado en un registro leido (si estamos usando un conversor A/D leido se cargará con el contenido de adress) en 3 dígitos (BCD) que seran en lo registros centena - decena - unidad. ;****ADVERTENCIA***- subrutina decimal destruye contenido del registro leido al ser usada****ADVERTENCIA*** decimal clrf unidad clrf decena clrf centena ;----va a determinar las centenas---- movlw d'100'; carga decimal 100 en w cent subwf leido,1; resta 100 a leido y lo guarda en leido btfss status,0; verifica el carry (el bit 0 de status)- la instruccion dice salta intrucción ;siguiente si es 1 goto sum; si el carry es 0 deja de restar incf centena,1; si carry es 1 incrementa centena goto cent; volverá a restar 100 a leido sum addwf leido,1; suma 100 a leido- esto es porque antes de llegar aqui le habia restado 100 a leido buscando las centenas y leido valia menos de 100 antes de hacerlo ;---terminó de obtener las centenas--- ;----va a determinar las decenas---- movlw d'10'; carga decimal 10 en w dece subwf leido,1; resto 10 a leido y lo guardo en leido btfss status,0; verifica el carry (el bit 1 de status)la instruccion dice salta intrucción ;siguiente si es 1 goto sum1; si el carry es 0 deja de restar incf decena,1; si el carry es 1 incrementa decena goto dece; volverá a restar 10 a leido sum1 addwf leido,1; suma 10 a leido- esto es porque antes de llegar aqui le habia restado 10 a leido buscando las centenas y leido valia menos de 10 antes de hacerlo ;---terminó de obtener las decenas--- ;----va a determinar las unidades---- movf leido,0; carga w con lo que ha quedado en leido- representa las unidades movwf unidad; carga w en registro unidad ;---terminó de obtener las unidades--- return ;------FIN Subrutina DECIMAL-------------------- ;----Subrutina (leercv) leer el conversor--------------------- leercv bcf status,5 ;se posiciona en banco 0 bcf adcon0,0; arbitrariamente apago el convesor bsf status,5 ;se posiciona en banco1 bcf adcon1,6; se hace 0 el bit 6 de adcon1 - ADCS2 para que NO divida por 2 el clock del conversor bcf status,5 ;se posiciona en banco0 movlw b'01000001' movwf adcon0; se selecciona fconv=fosc/8 - se elije canal0 RA0/AN0 como entrada analógica principal en este programa ;pero tambien seran analógicas RA1/AN1 y RA3/AN3- en instruccion siguiente las declaro- ;- conversión no en progreso-go/done* en 0- enciende el conversor haciendo bit adon = 1 del registro adcon0 movlw b'00000100'; este es el cambio versión 10 bsf status,5 ;se posiciona en banco1 movwf adcon1; justificación a izquierda - se trata conversor como de 8 bits - se usará solo registro ADRESH como resultado de conversión ;- las entradas RA2 RA4 de porta se trataran como entradas digitales mientras que RA0/AN0 RA1/AN1 y RA3/AN3 serán entradas analógicas del conversor bcf status,5 ;se posiciona en banco0 leercv2 bsf adcon0,2; comienza la conversión - hace 1 bit 2 de ADCON0 o sea go/done* consu btfsc adcon0,2; pregunta si bit2 de ADCON0 es 0 (cero) o sea si termino la conversión - salta si es cero goto consu; si no termino sigue esperando movf adresh,0; carga registro ADRESH (resultado de la conversión) en w ;porque el contenido de w fue alterado al amplificar movwf leido; carga en registro leido el valor de la conversión ;detección de bajo escala - hace digitos spl instantaneo igual a ( -- ) ;esto se basa en que si leido es menor o igual a 2 no se muestre numeros sino (--) ;leido igual a 3 sera considerado 50dB spl movlw d'2'; carga decimal 2 en w subwf leido,0; resta decimal 2 a leido btfss status,0; verifca bit de carry- si es 1 (leido mayor a 2) salta siguiente instrucción bsf bandera,3; hace 1 el bit 3 de bandera para indicar por debajo de escala - spl instantaneo (---) movlw d'2'; carga decimal 2 en w addwf leido,1; restauro leido al que le habia restado 2 ;Fin detección de bajo escala - mensaje LOW return ;----Fin Subrutina (leercv) leer el conversor--------------------- ;Subrutina promednp --hace el promedio de sucesivas lecturas - lo devuelve por leido pero lo acumulado queda en aux2 ;ADVERTENCIA: no es igual a la subrutina con el mismo nombre de versiones anteriores ;aux2 registro auxiliar usado como acumulador de suma del promedio ;promedio registro donde se almacena el resultado del promedio - al terminar la subrutina para luego cargarlo en leido antes de return promednp movf leido2,0; carga leido en w addwf aux2,1; suma acumulando en aux2 btfsc status,0; verifica carry de la operación anterior, el cual será 1 si hubo overflow en el ;registro aux2 - la instrucción verifica el bit 0 de status - la instrucción dice salta la próxima ;instrucción si es 0 (cero) goto overaux2 incf np,1; incrementa el divisor del promedio btfsc status,0; verifica carry de la operación anterior, el cual será 1 si hubo overflow en el registro np - la instrucción verifica el bit 0 de status - dice salta la próxima instrucción si es 0 (cero) goto overnp goto promediar; salta a promediara si no hubo overflow ni de aux2 ni de np overaux2 subwf aux2,1; resta la ultima suma que provocó overflow en aux2 bsf bandera,0; hace 1 el bit 0 del registro bandera - indicando así que hubo overflow goto promediar overnp decf np,1; decrementa np - hubo overflow en np subwf aux2,1; resta la ultima suma ya que no la puedo contar - hubo overflow en np goto promediar ;comienza el calculo del promedio promediar clrf aux clrf promedio movf aux2,0; carga aux2 en w movwf aux; carga w en aux - se pasó el contenido de aux2 a aux movf np,0; carga np en w restnp subwf aux,1; resto np a aux y lo guardo en aux (aux es un registro auxiliar para operar localmente btfss status,0; verifica el carry (el bit 1 de status)la instruccion dice salta intrucción ;siguiente si es 1 goto finpro; si el carry es 0 deja de restar incf promedio,1; si el carry es 1 incrementa promedio goto restnp; volverá a restar np a aux finpro movf promedio,0; carga promedio en w movwf leido; carga w en leido - se pasó el contenido de promedio a leido btfss bandera,0; prueba si hay 1 en el bit 0 de bandera - o sea si ocurrió algún overflow - si hay 1 salta la siguiente instrucción return movf leido2,0; carga leido2 en w movwf aux2; carga w wn aux2 - o sea está guardando leido2 (última lectura) en aux2 clrf np; limpia np incf np,1; cuenta 1 en np porque ya tiene un valor acumulado (el último) aux2 return ;----Fin Subrutina promednp -------------------------- ;----Subrutina de conversión a db------------------------ ;Toma leido y lo transforma mediante una tabla (situada entre posicion -registros ;generales- 39h y 66h ) y el uso de direccionamiento indirecto --(fsr)- ;La lógica es: toma contenido de leido- descarta los 2 bits LSB - hace desplazamiento de leido hacia la derecha (2 bits) - ;- suma 39h a contenido de leido para caer dentro de la zona de la tabla- ;carga este resultado a fsr - siendo esta la posición de memoria que contiene el ;valor transformado- se carga en leido antes de salir de la subrutina --- covdb movf leido,0; carga en w el contenido leido andlw b'11111100'; and entre w (que contiene leido) y 11111100 para enmascar y descartar los 2 bits LSB movwf leido; se carga leido con resultado operación anterior rrf leido,1; hace otro desplazamiento en 1 bit hacia la derecha del registro leido rrf leido,1; hace desplazamiento en 1 bit hacia la derecha del registro leido movlw 39h; carga literal 39h en w addwf leido,0; suma 39h (contenido en w) y leido - para desplazar a posición de memoria correspondiente al valor en db de leido- lo guarda en w movwf fsr; carga en fsr (registro de direccionamiento indirecto) el valor al que debe apuntar y que estaba contenido en w movf indf,0; carga en w el contenido de la posición de memoria al que apuntaba fsr movwf leido; carga en leido el resultado de la conversión return ;--Fin subrutina de conversión a db------------------------------------ ;---------Subrutina temperatura----------- temperatura bcf adcon0,4; hace 0 el bit 4 de adcon0 -junto con la proxima instrucción selecciona AN1 bsf adcon0,3; hace 1 el bit 3 de adcon0 seleccionando asi el canal AN1 del conversor - donde se leerá la temperatura call retardo; call leercv2; se realiza la lectura del conversor - sale guardado en registro leido ;corrección del valor de temperatura ;decf leido,1 ;decf leido,1 ;decf leido,1; acaba de restar 3 grados a lectura de temperatura ;fin de corrección de temperatura movf leido,0; carga contenido de leido a w movwf memtemp; carga contenido de leido en memtemp que previamente se cargo en w ;memorizando en este registro el valor de la temperatura bcf adcon0,3; hace cero el bit3 de adcon0 dejando así seleccionado la entrada AN0 del conversor- considero no hacer retardo porque no lo usaré inmediatamente return ;---------Fín subrutina temperatura----------- ;---------Subrutina tecla1-------------------- tecla1 btfss porta,2; prueba si bit (RA2) es 1 - si lo es salta siguiente instrucción ;- RA2 como entrada digital detecta si se presiono la tecla de escala - es 1 si se presionó ; y 0 si no se presionó la tecla 1 goto notecla1 movlw b'00000010'; carga (00000010) en w xorwf bandera,1; hace XOR entre registro bandera y contenido de w - esto se hace para complementar el bit 1 de bandera call dingdong; señal audible para avisar que se presionó la tecla de cambio de escala notecla1 return ;---------Fin subrutina tecla1-------------------- ;----------Subrutina tecla2 programacion temperatura---- tecla2 btfss porta,4; prueba si bit (RA4) es 1 - si lo es salta siguiente instrucción ;- RA4 como entrada digital detecta si se presiono la tecla 2 de programar alarma ;- es 1 si se presionó y 0 si no se presionó la tecla 2 return ;sección de la alarma call escribealarma; escribe mensaje Alarma call beep call beep call dingdong btfss bandera,2; prueba si bit2 de bandera es 1 - si lo es salta siguiente instrucción - bit2=1 alarma activada clrf alarm; asi la temperatura de alarma inicialmente es cero si nunca se programó todavía selecionando movf alarm,0; carga contenido de alarma a w movwf leido; carga contenido de alarma en leido que previamente se cargo en w call decimal; va a convertir el contenido de leido a decimal y lo carga en registros centena-decena-unidad ;(aqui leido ya no contiene el valor original) movlw 090h; carga en w dirección de centenas-LO MANDO FUERA DEL DISPLAY para evitar mostrar centenas movwf dcent; carga registro dcent con dirección movlw 08Dh; carga en w dirección de decenas movwf ddece; carga registro ddece con dirección movlw 08Eh; carga en w dirección de unidades movwf dunid; carga registro dunid con dirección call mostrar; muestra contenido de centena-decena-unidad en el display- temperatura ;muestra cero temperatura la primera vez y luego el valor incrementado btfsc porta,4; prueba si bit (RA4) es 0 - si lo es salta siguiente instrucción ;- RA2 como entrada digital detecta si se presiono la tecla 2 que ahora sirve para salir de ;programar alarma - es 1 si se presionó (sale) y 0 si no se presionó la tecla 2 (no sale) goto saletecla2; se va a la salida btfss porta,2; prueba si bit (RA2) es 1 - si lo es salta siguiente instrucción ;- RA2 como entrada digital detecta si se presiono la tecla1 la cual incrementa la temperatura ; de alarma ahora - fuera de esta subrutina es la tecla de escala - es 1 si se presionó y ; 0 si no se presionó la tecla 1 goto selecionando incf alarm,1; incrementa temperatura de alarma call beep; pitido de avance- cada pitido incrementa temperatura de alarma goto selecionando saletecla2 bsf bandera,2; hace 1 el bit 2 de bandera para indicar alarma activada movlw 8Ah; call instruc movlw "*"; call escrib call midiendo call sonisalida nuncatecla2 return ;----------Fin subrutina tecla2 programacion temperatura---- ;-------Subrutina ver si es la temperatura de alarma------ ;Incluye activar sonidos de alarma------------------------ tempalarm movf memtemp,0; carga memtemp en w- contiene el valor de temperatura xorwf alarm,0 ;lo guardo en w porque no me interesa guardarlo en otro lado btfss status,2 ;junto con la intruccion anterior ve si alarm (alarm contiene temperatura de alarma) ; es igual a memtemp- si bit 2 de status es 1 es porque son iguales- ;la instrucción actual dice salta si es 0- si es 1 suena la alarma y no se detiene hasta presionar ; tecla2 - en ese caso se apaga y se desactiva- goto saletempalarm siguesonando bsf portb,2; coloca en estado alto el pin 2 (RB2) del puerto b call escribealarma; escribe mensaje Alarma call beep call dingdong call dingdong1 btfss porta,4; prueba si bit (RA4) es 1 - si lo es salta siguiente instrucción ;- RA2 como entrada digital detecta si se presiono la tecla 2 que ahora sirve para salir de ;tempalarm - es 1 si se presionó (sale) y 0 si no se presionó la tecla 2 (no sale) goto siguesonando clrf alarm bcf portb,2; asegura bit 2 de portb en 0 bcf bandera,2; hace 0 el bit 2 de bandera para indicar alarma desactivada movlw 8Ah; call instruc movlw " "; call escrib saletempalarm call midiendo; escribe mensaje Midiendo return ;-------Fin subrutina ver si es la temperatura de alarma------ ;---------Subrutina cambio de escala------------ escala btfss bandera,1; prueba si bit1 de bandera es 1 - si lo es salta siguiente instrucción - bit1=1 escala H - bit1=0 escala L goto escabaja escaalta bsf adcon0,3 bsf adcon0,4; se seleccionó canal 3 del conversor -RA3/AN3 movlw 0C9h call instruc movlw "H" call escrib; se escribe H en la posición C9h del LCD goto salescala escabaja bcf adcon0,3 bcf adcon0,4; se seleccionó canal 0 del conversor -RA0/AN0 movlw 0C9h call instruc movlw "L" call escrib; se escribe L en la posición C9h del LCD salescala return ;---------Fin subrutina cambio de escala------------ ;-------------Subrutina tono1-------------------------- ;subrutina tono1 -antes de llamarla se debe cargar el regist frecu (1 a 80) y el registro durac (de 0 a 255)- ;el valor de frecu 1 (agudos) a 80 (graves) determina la frecuencia. ; el valor de durac (hasta 255) determina la duración. NO es igual para todas las frecuencias tono1 clrf ts1 clrf ts2 clrf ts3 rt1 incf ts1,1 rt2 incf ts2,1 rt3 call periodo incf ts3,1 movf durac,0 xorwf ts3,0 ;lo guardo en w porque no me interesa guardarlo en otro lado btfss status,2 ;junto con la intruccion anterior ve si ts3 es igual a durac- goto rt3 clrf ts3 movf durac,0 xorwf ts2,0 ;lo guardo en w porque no me interesa guardarlo en otro lado btfss status,2 ;junto con la intruccion anterior ve si ts2 es igual a durac- goto rt2 clrf ts2 movf durac,0 xorwf ts1,0 ;lo guardo en w porque no me interesa guardarlo en otro lado btfss status,2 ;junto con la intruccion anterior ve si ts1 es igual a durac- goto rt1 return ;------Subrutina periodo ( para subrutina tono1--- periodo clrf ctperi bajo bcf portb,3 ;semiciclo bajo (cero) de la onda cuadrada.Esta intrucc selec salida sonora. call semiciclo ;determina la duracion de este semiciclo incf ctperi,1 movf frecu,0 xorwf ctperi,0 ;lo guardo en w porque no me interesa guardarlo en ctperi btfss status,2 goto bajo clrf ctperi alto bsf portb,3 ;semiciclo alto (uno) de la onda cuadrada.Esta intrucc selec salida sonora. call semiciclo incf ctperi,1 movf frecu,0 xorwf ctperi,0 ;lo guardo en w porque no me interesa guardarlo en ctperi btfss status,2 goto alto return ;----Subrutina semiciclo (para subrutina tono1)----- semiciclo clrf tf1 clrf tf2 retf1 incf tf1,1 retf2 incf tf2,1 btfss tf2,1 ;determina la duracion del semiciclo T/2 (controla la frec) goto retf2 clrf tf2 btfss tf1,1 ;determina la duracion del semiciclo T/2 (controla la frec) goto retf1 return ;-------------Fin subrutina tono1------------------ ;---------------------------------------------------------------------------- ;subrutina ding dong dingdong movlw d'10' movwf frecu movlw d'6' movwf durac call tono1 movlw d'6' movwf frecu movlw d'6' movwf durac call tono1 return ;--------------------------------------------------------------------- ;subrutina beep beep movlw d'10' movwf frecu movlw d'5' movwf durac call tono1 return ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ;subrutina beep2 beep2 movlw d'14' movwf frecu movlw d'10' movwf durac call tono1 return ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ;subrutina beep3 beep3 movlw d'6' movwf frecu movlw d'6' movwf durac call tono1 return ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ;subrutina ding dong1 dingdong1 movlw d'6' movwf frecu movlw d'6' movwf durac call tono1 movlw d'10' movwf frecu movlw d'6' movwf durac call tono1 return ;--------------------------------------------------------------------- ;------Subrutina escribe Midiendo----------------------------------- midiendo movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc movlw "M"; este es el primer carcater del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw "i"; call escrib movlw 82h; call instruc movlw "d"; call escrib movlw 83h; call instruc movlw "i"; call escrib movlw 84h; call instruc movlw "e"; call escrib movlw 85h; call instruc movlw "n"; call escrib movlw 86h; call instruc movlw "d"; call escrib movlw 87h; call instruc movlw "o"; call escrib movlw 88h; call instruc movlw "."; call escrib movlw 89h; call instruc movlw " "; call escrib return ;------Fin subrutina escribe Midiendo----------------------------------- ;------Subrutina escribe Alarma----------------------------------- escribealarma movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc movlw "*"; este es el primer carcater del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw "A"; call escrib movlw 82h; call instruc movlw "L"; call escrib movlw 83h; call instruc movlw "A"; call escrib movlw 84h; call instruc movlw "R"; call escrib movlw 85h; call instruc movlw "M"; call escrib movlw 86h; call instruc movlw "A"; call escrib movlw 87h; call instruc movlw "*"; call escrib movlw 88h; call instruc movlw " "; call escrib movlw 89h; call instruc movlw " "; call escrib return ;------Fin subrutina escribe Alarma----------------------------------- ;---Subrutina copyright----------------------------------------------- copyright movlw 01h call instruc; borrar pantalla movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc movlw "("; este es el primer caracter del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw "c"; call escrib movlw 82h; call instruc movlw ")"; call escrib movlw 83h; call instruc movlw " "; call escrib movlw 84h; call instruc movlw "D"; call escrib movlw 85h; call instruc movlw "J"; call escrib movlw 86h; call instruc movlw "B"; call escrib movlw 87h; call instruc movlw "-"; call escrib movlw 88h; call instruc movlw "2"; call escrib movlw 89h; call instruc movlw "0"; call escrib movlw 8Ah; call instruc movlw "0"; call escrib movlw 8Bh; call instruc movlw "7"; call escrib call dingdong call dingdong1 call beep2 call dingdong call dingdong1 call espera call espera call espera call espera return ;---Fin subrutina copyright----------------------------------------------- ;---Subrutina vario - escritura de - t= - c - SPL- dB - Pr------------ varios movlw 8Bh; call instruc movlw "t"; call escrib movlw 8Ch; call instruc movlw "="; call escrib movlw 8Fh; call instruc movlw "c"; call escrib movlw 0C0h; call instruc movlw "S"; call escrib movlw 0C1h; call instruc movlw "p"; call escrib movlw 0C2h; call instruc movlw "l"; call escrib movlw 0C6h; call instruc movlw "d"; call escrib movlw 0C7h; call instruc movlw "B"; call escrib movlw 0CBh; call instruc movlw "P"; call escrib movlw 0CCh; call instruc movlw "r"; call escrib return ;---Fin subrutina escritura de mensaje - t= - c - SPL- dB - Pr----------- ;------Subrutina escribe Calibrando--------------------------- calibrando movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc movlw "C"; este es el primer caracter del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw "a"; call escrib movlw 82h; call instruc movlw "l"; call escrib movlw 83h; call instruc movlw "i"; call escrib movlw 84h; call instruc movlw "b"; call escrib movlw 85h; call instruc movlw "r"; call escrib movlw 86h; call instruc movlw "a"; call escrib movlw 87h; call instruc movlw "n"; call escrib movlw 88h; call instruc movlw "d"; call escrib movlw 89h; call instruc movlw "o"; call escrib return ;------Fin subrutina escribe Calibrando------------------------------- ;-----Subrutina calibra-------------- ;el conversor A/D tiene seleccionado en este momento la entrada AN0 o sea está en escala H calibra movlw 01h; carga w con literal 01h ;la intrucc asociada dice: BORRAR PANTALLA call instruc; enviaremos este valor al portb y por lo tanto al LCD call calibrando; escribe mensaje calibrando call varios scalibra call espera call espera call espera call espera call espera call espera call beep3; emite sonido que recibirá por aire el MIC call leercv2; realiza la lectura de la salida del LM386 en la escala alta call splinstantaneo call beep3; emite sonido que recibirá por aire el MIC call leercv2; realiza la lectura de la salida del LM386 en la escala alta movlw d'180'; carga en w el literal decimal 180(sonometro gabinete) subwf leido,0; resta w (que ahora contiene 180) a leido btfss status,0; si carry=1 es porque leido es mayor que xx(SPL=67) - si carry=0 entonces leido es menor o igual a xx ;la instrucción dice si carry=1 entonces salta instrucción siguiente (leido es mayor que xx) ;lo cual indicaría que el sistema esta listo para medir ;si carry=0 entonces no salta siguiente instrucción (leido es menor o igual que 30 (SPL=67))sigue calibrando goto scalibra; sigue calibrando call sonisalida call sonisalida call midiendo return ;-----Fin subrutina calibra----------- ;--------Subrutina sonisalida------------------------------------ sonisalida call dingdong1 call beep call beep call beep return ;--------Fin subrutina sonisalida------------------------------------ ;--------Subrutina splinstantaneo------------------------------------ splinstantaneo call covdb; llama a subrutina que hace pasaje a db call decimal; va a convertir el contenido de leido a decimal y lo carga en registros centena-decena-unidad ;(aqui leido ya no contiene el valor original) movlw 0C3h; carga en w dirección de centenas movwf dcent; carga registro dcent con dirección movlw 0C4h; carga en w dirección de decenas movwf ddece; carga registro ddece con dirección movlw 0C5h; carga en w dirección de unidades movwf dunid; carga registro dunid con dirección btfsc bandera,3; prueba si bit3 de bandera es 0-si lo es salta siguiente instrucción ;el bit 3 de bandera valiendo 1 implica escala por debajo de 50 (--)dB call escbajo btfss bandera,3; prueba si bit3 de bandera es 1-si lo es salta siguiente instrucción call mostrar; muestra contenido de centena-decena-unidad en el display- muestra SPL instantáneo bcf bandera,3; hace 0 el bit 3 de bandera return ;--------Fin subrutina splinstantaneo------------------------------------ ;-------Subrutina LOW-------- no se muestra valores bajos (menos de 50) instantaneos escbajo movlw 0C3h; call instruc movlw " "; call escrib movlw 0C4h; call instruc movlw "-"; call escrib movlw 0C5h; call instruc movlw "-"; call escrib return ;-------Fin subrutina LOW----------------------- ;------Subrutina menu------- ; sale de esta subrutina quedando almacenado la opción elegida en registro opc ;Registros necesarios a declarar para uso de esta subrutina: opc menu bcf portb,2; asegura que el pin de salida RB2 sea 0 clrf opc; limpia registro opc movlw 01h; codigo para borrar pantalla call listamenu; se escribe el menu en pantalla siguemenu movf opc,0; carga valor de opc en w movwf unidad; carga contenido w en registro unidad movlw 8Fh; carga literal 8Fh en w movwf dunid; carga en registro dunid la direccion del LCD (8Fh) en donde aparecerá el número de opción call mostrarunidad; llama a subrutina que esta dentro de subrutina mostrar btfsc porta,4; detecta si se presionó tecla2 (RA4) o sea sale del menu si es 1 ya la intruccion dice salte proxima instrucción si es cero goto salemenu btfss porta,2; prueba si bit RA2 (si se presionó tecla1)es 1- incrementará registro opc si es así goto siguemenu incf opc,1; incrementa registro opc guarda en opc call beep movf opc,0; carga opc en w xorlw d'2'; hace xor entre decimal y contenido de w btfss status,2; junto con la instrucción anterior verifica si registro opc=2 - (verifica bit z de status) - si no lo es z de status es cero, por lo tanto salta la siguiente instrucción goto siguemenu clrf opc goto siguemenu salemenu return ;------------Fin subrutina menu------------ ;--------Subrutina timer---------------------------- ;Registros necesarios para esta subrutina segund-minut timer movlw 01h call instruc; borrar pantalla call esctimer; escribe en pantalla TIMER -min-seg clrf segund clrf minut call mostminseg sigueseg btfss porta,2; prueba si se presionó la tecla 1 (RA2) utilizada para incrementar segundos en este punto goto sigueseg2 incf segund,1; incrementa segundos call masde60 call mostminseg call beep sigueseg2 btfsc porta,4; prueba si se presionó tecla 2 (RA4)- pasa a minutos- 1 si se presionó - 0 si no se presionó goto sigueminut goto sigueseg sigueminut call dingdong call dingdong1 call dingdong sigueminut3 btfss porta,2; prueba si se presionó la tecla 1 (RA2) utilizada para incrementar minutos en este punto goto sigueminut2 incf minut,1; incrementa minutos call mostminseg call beep sigueminut2 btfsc porta,4; prueba si se presionó la tecla 2 (RA4)-salir de programacion-en este punto goto contando goto sigueminut3 contando call sonisalida contando2 ;--------------------------------------------------------------- movlw 87h; call instruc movlw "*"; call escrib call tcalib movlw 87h; call instruc movlw " "; call escrib call tcalib ;-------------------------------------------------------------------------- call mostminseg decf segund,1 call menosde0 btfss porta,2; prueba si se presionó la tecla 1 (RA2)-conteo mudo o no mudo-en este punto goto nomudo movlw b'00010000'; carga (00010000) en w xorwf bandera,1; hace XOR entre registro bandera y contenido de w - esto se hace para complementar el bit 4 de bandera nomudo btfss bandera,4; si el bit 4 de bandera esta en 1 salta siguiente instrucción- conteo mudo- call beep btfsc bandera,4; si el bit 4 de bandera esta en 1 salta siguiente instrucción-retardo para compensar mudo call espera; espera para compensar el tiempo de la subrutina beep cuando esta mudo movf segund,0; carga segund en w iorwf minut,0; hace OR entre w y minut-guarda en w para no guardar en otro lugar- btfss status,2; salta si bit z= 1 ;intrucción si es 0 o sea minut=0 y segund=0- terminó la cuenta goto contando2 sonando bsf portb,2; coloca en estado alto el pin 2 (RB2) del puerto b call mostminseg call escribealarma call dingdong1 call beep2 call dingdong1 btfss porta,4; sale de sonando solo si se presiona RA4 - tecla 2- goto sonando return ;despues de esta subrutina se debe llamar al menu con goto menu ;--------Fin de subrutina timer----------------------- ;-----Subrutina masde60------------ masde60 movf segund,0; carga segund en w xorlw d'60'; XOR entre decimal 60 y w btfss status,2; salta si bit z= 1 return clrf segund return ;-----Fin subrutina masde60------------ ;-----Subrutina menosde0------------ menosde0 movf segund,0; carga segund en w xorlw d'255'; XOR entre decimal 255 y w btfss status,2; salta siguiente instrucción si bit z=1 return movlw d'59'; carga decimal 59 en w movwf segund; carga w en segund decf minut,1; decrementa minut return ;-----Fin subrutina menosde0------------ ;-----Subrutina mostminseg----------- ;Trabaja con 2 registros que contienen minut (minutos) y segund (segundos) cargados en otra subrutina mostminseg movf segund,0; carga contenido de registro segund en w movwf leido; carga contenido de w a registro leido call decimal; convierte en decimal contenido de leido y lo carga en registros centena-decena-unidad movlw 090h movwf dcent movlw 0CBh; direccion del LCD a visualizar segundos-decenas movwf ddece movlw 0CCh; direccion del LCD a visualizar segundos-unidades movwf dunid call mostrar; muestra segundos en LCD movf minut,0; va a mostrar los minutos-carga contenido del registro minut en w movwf leido; carga contenido de w a registro leido call decimal movlw 0C6h movwf dcent movlw 0C7h movwf ddece movlw 0C8h movwf dunid call mostrar return ;-----Fin subrutina mostminseg--------------- ;--------Subrutina de calibración de timer------- tcalib movlw 09Ch; carga literal 0ffh en w movwf tempo1; mueve contenido de w a tempo1 tcalib2 call retardo decfsz tempo1,1; decrementa tempo1 y guarda resultado en tempo1- salta la intruccion siguiente si temp5 es igual a cero goto tcalib2 return ;--------Fin subrutina de calibración de timer------- ;---Subrutina listamenu--------------------- listamenu movlw 01h call instruc; borrar pantalla movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc movlw "0"; este es el primer caracter del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw ")"; call escrib movlw 82h; call instruc movlw "S"; call escrib movlw 83h; call instruc movlw "+"; call escrib movlw 84h; call instruc movlw "T"; call escrib movlw 86h; call instruc movlw "1"; call escrib movlw 87h; call instruc movlw ")"; call escrib movlw 88h; call instruc movlw "T"; call escrib movlw 89h; call instruc movlw "m"; call escrib movlw 8Eh; call instruc movlw ">"; call escrib return ;---------Fin subrutina listamenu------------ ;---Subrutina esctimer--------------------- esctimer movlw 01h call instruc; borrar pantalla movlw 80h; se indica posicion de memoria del LCD en que quiere escibir el dato call instruc call espera movlw "T"; este es el primer caracter del mensaje - al estar entre comillas se le indica al compilador que el dato requerido s el valo ASCII del caracter call escrib ;repito con el resto de los caracteres movlw 81h; call instruc movlw "I"; call escrib movlw 82h; call instruc movlw "M"; call escrib movlw 83h; call instruc movlw "E"; call escrib movlw 84h; call instruc movlw "R"; call escrib movlw 87h; call instruc movlw "p"; call escrib movlw 0C9h; call instruc movlw "m"; call escrib movlw 0CDh; call instruc movlw "s"; call escrib return ;---------Fin subrutina esctimer------------ ;--------FIN SUBRUTINAS-------- ;------INICIO programa principal----- inicio bsf status,5 ;se posiciona en banco1 movlw 00h movwf trisb; en este caso seteo todo el portb como salida ; recordar que 0 es salida y 1 es entrada al definir puertos movlw b'0011111' movwf trisa; se establece que los pines RA2 y RA4 de porta se trataran como entradas digitales ;- mientras que RA0/AN0 RA1/AN1 y RA3/AN3 serán entradas que luego seran definidas ;como entradas analógicas del conversor bcf status,5 ; se posiciona en banco 0 ;-------inicializacion del LCD-------- movlw 02h; carga w con literal 02h RB1=1 o sea E=1 habilito LCD call instruc; enviaremos este valor al portb y por lo tanto al LCD ;------------otra instruccion----------- movlw 28h; carga w con literal 28h ;la intrucc asociada dice: interfase de datos de 4 bits y se va a usar 2 lineas - corresponde a la intruccion ACTIVAR FUNCION call instruc; enviaremos este valor al portb y por lo tanto al LCD ;------------otra instruccion----------- movlw 06h; carga w con literal 06h ;la intrucc asociada dice: dato fijo en pantalla- corresponde a la intruccion SELECCIONAR MODO call instruc; enviaremos este valor al portb y por lo tanto al LCD ;------------otra instruccion----------- movlw 0Ch; carga w con literal 0Ch ;la intrucc asociada dice: encienda la pantalla y desactive el cursor- corresponde a la intruccion ENCENDER O APAGAR PANTALLA call instruc; enviaremos este valor al portb y por lo tanto al LCD ;------------otra instruccion----------- movlw 01h; carga w con literal 01h ;la intrucc asociada dice: BORRAR PANTALLA call instruc; enviaremos este valor al portb y por lo tanto al LCD ;----fin inicializacion del LCD----- call copyright ;call midiendo; escribe mensaje midiendo call espera ;call varios ;---Se arma (cargandose en los registros reservados) la tabla de conversión-- ;se cargan valores -de 50db a 105db-------------------------- tabla movlw d'50' movwf d1 movlw d'51' movwf d2 movlw d'52' movwf d3 movlw d'53' movwf d4 movlw d'55' movwf d5 movlw d'56' movwf d6 movlw d'57' movwf d7 movlw d'57' movwf d8 movlw d'58' movwf d9 movlw d'59' movwf d10 movlw d'60' movwf d11 movlw d'61' movwf d12 movlw d'62' movwf d13 movlw d'63' movwf d14 movlw d'63' movwf d15 movlw d'64' movwf d16 movlw d'64' movwf d17 movlw d'64' movwf d18 movlw d'64' movwf d19 movlw d'65' movwf d20 movlw d'65' movwf d21 movlw d'65' movwf d22 movlw d'65' movwf d23 movlw d'65' movwf d24 movlw d'65' movwf d25 movlw d'65' movwf d26 movlw d'66' movwf d27 movlw d'66' movwf d28 movlw d'66' movwf d29 movlw d'66' movwf d30 movlw d'66' movwf d31 movlw d'67' movwf d32 movlw d'67' movwf d33 movlw d'67' movwf d34 movlw d'67' movwf d35 movlw d'67' movwf d36 movlw d'67' movwf d37 movlw d'67' movwf d38 movlw d'68' movwf d39 movlw d'68' movwf d40 movlw d'68' movwf d41 movlw d'68' movwf d42 movlw d'68' movwf d43 movlw d'68' movwf d44 movlw d'68' movwf d45 movlw d'69' movwf d46 movlw d'69' movwf d47 movlw d'69' movwf d48 movlw d'69' movwf d49 movlw d'69' movwf d50 movlw d'69' movwf d51 movlw d'70' movwf d52 movlw d'70' movwf d53 movlw d'70' movwf d54 movlw d'71' movwf d55 movlw d'72' movwf d56 movlw d'73' movwf d57 movlw d'74' movwf d58 movlw d'97' movwf d59 movlw d'98' movwf d60 movlw d'99' movwf d61 movlw d'100' movwf d62 movlw d'101' movwf d63 movlw d'102' movwf d64 movlw d'103' movwf d65 movlw d'104' movwf d66 movlw d'105' movwf d67 ;-----Fin carga de valores en la tabla ------------------------- clrf alarm; pone en cero registro de sonar alarma ;----bloque principal--- ;primera lectura e inicializacion del conversor call leercv; realiza lectura inicial de salida del LM386 clrf promedio clrf aux2 clrf np bcf portb,2; asegura bit 2 de portb en 0 eleccion call menu ;---Rutina selectora------ ;Pensada para opciones 0-1-2-3 estando disponibles en version 15 solo la 0 y1 movf opc,0; carga opc -registro que guarda la opcion elegida- en w xorlw d'0'; hace xor entre decimal 0 y w btfsc status,2; salta siguiente instrucción si el bit 2 de status es 0 - o sea si no se eligio opcion0 goto opcion0; se eligio opcion0 (opcion normal) xorlw d'1'; btfsc status,2; salta si no se eligio opcion1 goto opcion1; se eligio opcion1 ;---------------fin rutina selectora---------------- ;Comienza listado de opciones ;---------opción 1----------------------------------- ;La opción 1 corresponde a funcionamiento como timer opcion1 call beep2 call beep call timer call sonisalida goto eleccion ;---------Fin opción 1----------------------------------- ;---------opción 0----------------------------------- ;la opción 0 es la opcion normal- sonometro + termometro opcion0 call calibra call midiendo call varios medir call temperatura ;muestra de l valor de temperatura call decimal; va a convertir el contenido de leido a decimal y lo carga en registros centena-decena-unidad ;(aqui leido ya no contiene el valor original) movlw 090h; carga en w dirección de centenas-LO MANDO FUERA DEL DISPLAY para evitar mostrar centenas movwf dcent; carga registro dcent con dirección movlw 08Dh; carga en w dirección de decenas movwf ddece; carga registro ddece con dirección movlw 08Eh; carga en w dirección de unidades movwf dunid; carga registro dunid con dirección call mostrar; muestra contenido de centena-decena-unidad en el display- temperatura ;----- fin de medir y mostrar temperatura---- call tecla2; llama subrutina para verificar si se presionó la tecla de establecer alarma (RA4) btfsc bandera,2; prueba si bit2 de bandera es 0-si lo es salta siguiente instrucción- bit2=1 alarma activada call tempalarm call tecla1; llama subrutina para verificar si se presionó la tecla de cambio de escala (RA2) call escala; verifica la escala seleccionada- seteando la entrada del conversor a mostrar call leercv2; realiza lectura de salida del LM386- queda guardada en leido movf leido,0; carga leido en w movwf leido2; guarda leido en leido2 para promediar sucesivamente call splinstantaneo call promednp; llama subrutina de promediar sucesivamente call covdb; llama a subrutina que hace pasaje a db call decimal; va a convertir el valor promedio que se encuentra almacenado en leido movlw 0CDh; carga en w dirección de centenas movwf dcent; carga registro dcent con dirección movlw 0CEh; carga en w dirección de decenas movwf ddece; carga registro ddece con dirección movlw 0CFh; carga en w dirección de unidades movwf dunid; carga registro dunid con dirección call mostrar; va a mostrar en las posiciones prefijadas del LCD el valor promedio goto medir ;---fin programa principal----------- end