; Valores de constantes:

LIST P=PIC16F84A #INCLUDE ; Pic a usar ; Lista de etiquetas de microchip ; Configuración opciones de hardware para la programación __CONFIG _CP_OFF

3 downloads 63 Views 160KB Size

Recommend Stories


Tablas y constantes físicas Ciencias Galilei CONSTANTES FUNDAMENTALES Y DERIVADAS
Tablas y constantes físicas Ciencias Galilei CONSTANTES FUNDAMENTALES Y DERIVADAS Velocidad de la luz c 3,00 · 108 m/s Cuadrado de la velocidad de

Informe de Tiendas Constantes. Agosto 2013
Informe de Tiendas Constantes Agosto 2013 Informe Tiendas Constantes Este estudio tiene como principal objetivo analizar qué está ocurriendo en los

Story Transcript

LIST P=PIC16F84A #INCLUDE

; Pic a usar ; Lista de etiquetas de microchip

; Configuración opciones de hardware para la programación __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC

; Valores de constantes: FRAC_INI

D'12'

SEGS_INI MINS_INI HORS_INI ADJMIN

D'196' D'196' D'232' D'9'

ADJHOR

D'34'

ADJDIA

D'6'

; Constante para inicio cuenta de fracciones de ; segundo ; Constante para inicio cuenta de segundos ; Constante para inicio cuenta de minutos ; Constante para inicio cuenta de horas ; Número de "frac_sec" que se necesita sumar cada ; minuto para ajustar el tiempo ; Número de "frac_sec" que se necesita restar cada ; hora para ajustar el tiempo ; Número de "frac_sec" que se necesita sumar cada ; 24 horas para ajustar el tiempo

;Ajustes: ; Un "frac_sec" es aproximadamente 1 / 244 s ; 1 MHz / 16 = 62.500 Hz ; 62.500 Hz / 256 = 244,140625 Hz ; T = 0,004096 s ; 0,004096 s * 244 = 0,999424 s; dif 1 segundo = -0,000576 s ; 1 "minuto" = 0,999424 s * 60 = 59,96544 s ; 60 s - 59,96544 s = 0,03456 s ; 0,03456 s / 0,004096 s = 8,4375 ; 1 "minutoadj" = 59,96544 s + (0,004096 s * 9) = 59,96544 s + 0,036864 s = 60,002304 s ; 1 "hora" = 60,002304 s * 60 = 3600,13824 s ; 3600 s - 3600,13824 s = -0,13824 s ; -0,13824 s / 0,004096 s = -33,75 s ; 1 "horaadj" = 3600,13824 s - (0,004096 s * 34) = ; = 3600,13824 s - 0,139264 s = 3599,998976 s ; 24 "horas" = 3599,998976 s * 24 = 86399,975424 s ; 86400 s - 86399,975424 s = 0,024576 s ; 0,024576 s / 0,004096 s = 6 ; 24 "horasadj" = 86399,975424 s + 0,004096 s * 6 = 86399,975424 s + 0,024576 s = 86400 s ; Activación de RB1-3 para las entradas de los pulsadores PULSADOR B'00001110' ; RB1, RB2 y RB3 ; Asignación de banderas. Los pulsadores activos proporcionan un "1" CHG H'03' ; Indica que se ha activado un pulsador o que es ; necesario actualizar los valores de la hora que tienen ; que mostrarse en los displays PSEG H'04' ; Pulsador A, modo segundero. PMIN H'05' ; Pulsador B, avance rápido minutos. PHOR H'06' ; Pulsador C, avance rápido horas. P_ON H'07' ; Un pulsador ha sido activado DSPOFF

B'11111111'

; Displays apagados

; Mapa de activación de segmentos para los displays (PORTB) ; a ; ========= ; | | ; f | | b ; | g | ; ========= ; | | ; e | | c ; | | ; ========= # p ; d ; gfedcbap CERO H'7E' ; 01111110 UNO H'0C' ; 00001100 DOS H'B6' ; 10110110 TRES H'9E' ; 10011110 CUATRO H'CC' ; 11001100 CINCO H'DA' ; 11011010 SEIS H'FA' ; 11111010 SIETE H'0E' ; 00001110 OCHO H'FE' ; 11111110 NUEVE H'DE' ; 11011110 SEGM_OFF equ H'00' ; Todos los segmentos apagados. Separador entre horas y minutos apagado (RB0).

; Posición de memoria de variables ; Las variables de tiempo comienzan con un número que permite contar y ajustar el tiempo ; Por ejemplo la variable "segundos" se inicia con 196 decimal, para que después de 60 ; incrementos de 1 segundo se produzca un 0 (196 + 60 = 256 -> 0) frac_sec H'0C' ; Fracciones de segundo (1/244) segundos H'0D' ; Segundos minutos H'0E' ; Minutos horas H'0F' ; Horas conta1 H'10' ; Variable 1 para bucle contador ; display H'11' ; Indicador de display que debe actualizarse digito1 H'12' ; Display unidad de minuto / unidad de segundo digito2 H'13' ; Display decena de minuto / decena de segundo digito3 H'14' ; Display unidad de hora digito4 H'15' ; Display decena de hora banderas H'16' ; Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6-PHOR, 7-P_ON

___________ DISPLAY DECENA MIN / DECENA SEG -> RA,2 -|1 \__/ 18|DISPLAY UNIDAD MIN / UNIDAD SEG -> RA,3 -|2 17|NC -|3 16F84A 16|MCLR/ -|4 15|GND -|5 14|PUNTO dp -> RB,0 -|6 13|PUL A (SEG) / SEGMENTO a -> RB,1 -|7 12|PUL B (MIN) / SEGMENTO b -> RB,2 -|8 11|PUL C (HOR) / SEGMENTO c -> RB,3 -|9________10|-

RA,1 RA,0 XT XT Vcc RB,7 RB,6 RB,5 RB,4

-> ->

SEGMENTO SEGMENTO SEGMENTO SEGMENTO

g f e d

PORTA, control displays 7 segmentos de cátodo común PORTB, segmetos de los displays, led separadores, pulsadores como entrada El pulsador A (conectado a RB1) muestra el segundero en tanto permanezca presionado. El pulsador B (conectado a RB2) avanza rápidamente los minutos. El pulsador C (conectado a RB3) avanza rápidamente las horas.

Configurar puertos como salidas, blanquear display

INICIO

RB Pull Up desconectadas TMR0 en modo temporizador (se utilizan los pulsos de reloj internos, Fosc/4) Preescaler 1:16

Configuración OPTION: OPTION_REG = 10000011

Bits PORTA como salidas Bits PORTB como salidas Puerto A apaga los displays Con Puerto B todos los segmentos apagados. Separador entre horas y minutos encendido (RB0).

Configuración PUERTOS: TRISA = 0000 0000 TRISB = 0000 0000 PORTA = DSPOFF (1111 1111) PORTB = 0000 0001

Inicialización de variables: TMR0 = 1 display = 1111 1110 (decena de hora) digito1 = “CERO” digito2 = “CERO” digito3 = “CERO” digito4 = SEGM_OFF banderas = 0000 0000 Variables de tiempo: frac_sec = FRAC_INI (12d) segundos = SEGS_INI (196d) minutos = MINS_INI (196d) horas = HORS_INI (232d)

PRINCIPAL

Pag. 2

Pone 01h en TMR0 Inicia display seleccionando decena de hora Los valores para digito1, digito2, digito3 y digito4 permitirán que desde el primer momento aparezcan las 0:00 en el display.

PRINCIPAL

TMR0 cuenta libremente para no perder ciclos de reloj escribiendo valores

TMR0_LLENO

Incremento de TMR0

TMR0 se va incrementando líbremente con la señal de reloj a 1.000.000 MHz / 16 = 62.500 Hz

Se comprueba el bit Z de STATUS

NO TMR0=0

TMR0 se ha desbordado y se han contado 256 * 16 = 4096 ciclos de reloj, (4,096 ms) La frecuencia es: 62.500 Hz / 256 = 244,140625 Hz

SI

Se añade 1 a frac_sec frac_sec comienza por 12, hasta desbordarse cuenta 244

frac_sec = frac_sec + 1

NO

SI

frac_sec = 0

Se activa separador horas-minutos (RB0) Restaura la variable “frac_sec” para la próxima vuelta

RB0 = 1 frac_sec = FRAC_INI (12d)

Comprueba variables pulsadores

frac_sec = 0, se ha contado “1 segundo” (0,999424 s)

COMPROBAR_PUL El programa pasa por aquí cada 4,096 ms, esto es unas 244 veces por segundo

No hay pulsadores activados NO

Incrementar segundos, minutos y horas Ajustes cada minuto, hora y 1/2 dia “CHG” se pone a 1

SI

NO

INC_HORA

NO

Se comprueba el estado de “CHG” por si se ha activado algún pulsador o es necesario actualizar los valores de la hora que tienen que mostrarse en los displays Se actualiza hora, displays y pulsadores cada 4,096 ms (244 veces por segundo)

SI

CHG = 1

PSEG = 0

Se ha activado un pulsador pero no es PSEG, debe ser PMIN o PHOR SI

Si está pulsado PSEG, (Pul A) se mostrarán los segundos en el display

Pag. 7

COMPROBAR_CHG

P_ON = 1

Puesta en hora PMIN (Pul B) avanza los minutos PHOR (Pul C) avanza las horas

PONER_RELOJ

Pag. 6

COMPROBAR_SEG

Si no se han activado pulsadores ni ha cambiado la hora se salta a DISPLAY_PUL, que principalmente refresca uno de los displays cada vez que se accede a ella y escanea pulsadores. SI

digito2 = 0 digito3 = 0 digito4 = 0 digito1 = second – SEGS_INI (196d)

PSEG = 1

NO

Se mostrarán los segundos en el Se guardan la hora y los display de minutos minutos para su tratamiento Se guarda temporalmente el número de segundos en “digito1” Resto de variables “digit” a 0 digito3 se utiliza temporalmente para almacenar la hora, (Si la hora es 255, digito3 sería 255 – 232 = 23 digito1 se utiliza temporalmente para almacenar los minutos

Pag. 4

Pag. 5

Pag. 3

Se comprueba si se activo el pulsador de segundos (Pul A) para mostrar los segundos en el display

DISPLAY_PUL

DIV_DIGITOS

CONVER_COD_7S

Se borran los bits de flag para actualizar su estado Escanea pulsadores, si alguno está activado se pone a 1 la bandera que le corresponda así como “P_ON” y “CHG” Muestra los digitos correspondientes a los segundos o a los minutos y horas en el display que corresponda. Cada display se actualiza cada 244,14 Hz / 4 = 61,04 Hz.

OBTENER_H_M

digito3 = horas – HORS_INI (232d) digit 1 = minutos – MINS_INI (196d)

Divide los segundos o los minutos y las horas en digitos independientes, ejemplo, [14] lo pasa a [1]-[4]

Convierte cada digito (digito1, digito2, digito3 y digito4) en valores para los segmentos del display

Se borran los bits de flag para actualizar su estado Escanea pulsadores, si alguno está pulsado se pone a 1 el pulsador que le correspoda así como "P_ON" y "CHG" Muestra los digitos correspondientes a los segundos o a los minutos y horas en el display que corresponda.

DISPLAY_PUL

banderas = 0000 0000 PORTA = DSPOFF (1111 1111) w = SEGM_OFF XOR PORTB w = w AND B'11111110' PORTB = w XOR PORTB TRISB = PULSADOR (0000 1110)

Se borran los bits de flag para actualizar su estado Apagar los segmentos respetando separador horas-minutos (RB0) Se apagan los displays Se configuran los bits 1, 2 y 3 de PORTB como entrada Se almacena el estado de los pulsadores en var

COMPROBAR_PSEG

RB1 = 1

SI

w = SEGM_OFF XOR PORTB w = w AND B'11111110' PORTB = w XOR PORTB

CHG = 1 PSEG= 1 P_ON = 1

Este código copia los bits del literal SEGM_OFF que se quieran en PORTB, Se copiaran aquellos bits de SEGM_OFF cuya posición coincida con un 1 en la máscara que se utiliza con la función AND y se respetaran los valores de los bits PORTB que coincidan con un 0 en la máscara. En este caso SEGM_OFF = 00H y en la operación AND se utiliza B'11111110' con lo que en PORTB se respetará el valor de RB0 y se pondrán a cero el resto de bits.

NO

COMPROBAR_PMIN

RB2 = 1

SI

En nuestro caso se podría simplificarse el proceso, eliminando la primera XOR pero entonces no se podría trabajar con otros posibles valores de SEGM_OFF

CHG = 1 PMIN= 1 P_ON = 1

Ejemplos:

NO

Si PORTB es 1000 1110 w = SEGM_OFF XOR PORTB: 0000 0000 1000 1110 --------------1000 1110

COMPROBAR_PHOR

RB3 = 1

SI

CHG = 1 PHOR= 1 P_ON = 1

w = w AND B'11111110': 1000 1110 1111 1110 -------------1000 1110

NO

PORTB = w XOR PORTB 1000 1110 1000 1110 -------------0000 0000

ACTIVAR_SEGM Puerto B como salida

TRISB = 0000 0000

Se determina que display debe actualizarse, es decir, que dato debe presentarse en el puerto B y se establece el siguiente display Display es XXXX XXX0

SI

w = digito4

w = SEGM_OFF XOR PORTB: 0000 0000 1000 1111 --------------1000 1111

w = digito3

w = w AND B'11111110': 1000 1111 1111 1110 -------------1000 1110

w = digito2

PORTB = w XOR PORTB 1000 1110 1000 1111 -------------0000 0001

NO Display es XXXX XX0X

SI

Si PORTB es 1000 1111

NO Display es XXXX X0XX

SI

NO Display es XXXX 0XXX

SI

w = digito1

NO

Se entregar el valor de w en el puerto B respetando el valor de RB0

w = w XOR PORTB w = w AND B'11111110' PORTB = w XOR PORTB

Bit 7 de frac_sec = 0

NO

RB0 = 0

Se apagan los puntos de separación. Se activó en INICIO y se activa cada vez que frac_sec se hace 0.

SI

PORTA = display

Se habilita el display correspondiente Cada display se “enciende” con una cadencia de 244 Hz / 4 = 61 Hz

Rota display a siguiente posición

En la variable display se va desplazando un cero a la izquierda. Sólo se tendrán en cuenta los 4 bits menos significativos

PRINCIPAL

Pag. 2

Para rotar el display a la próxima posición se utiliza el siguiente código: rlf display,F ; Rota display 1 bit a la próxima posición bsf display,0 ; Asegura un 1 en la posición más baja de display (luego se hará 0 si es necesario) btfss display,4 ; Comprueba si el último display fué actualizado bcf display,0 ; Si lo fué, se vuelve a habilitar el primer display La variable display va cambiando: 1111 1101 1111 1011 1111 0111 1110 1110 1101 1101 1011 1011 0111 0111 1110 1110 Sólo valen los 4 bits menos significativos

DIV_DIGITOS

Divide los segundos o los minutos y las horas en digitos independientes, ejemplo, [14] lo pasa a [1]-[4]

digito4 = 0 digito2 = 0 conta1 = 2 FSR = digito1

Se ponen a cero las posiciones de las decenas para el caso de que no se incrementen Bucle para convertir cada número (segundos o minutos y horas) Dirección de digito1 en FSR para usar INDF La primera vez, FSR = digito1 (minutos o segundos) y la segunda vez FSR = digito3 (horas)

Se vuelve a comprobar si es necesario sumar uno a la decena cada vez que ésta se ha incrementado

Este LOOP se utiliza primero para los minutos o los segundos y después para las horas

INC_DECENAS LOOP

Averiguar cuantas “decenas” hay en el número. El número menos diez en cada bucle.

INDF = INDF - 10

Incf FSR,F Incf INDF,F Decf FSR,F

SI

CARRY = 1

Se comprueba "CARRY", que se pone a 1 si en la resta no se ha producido llevada Si C = 1 se añadirá 1 a la posición de las decenas

NO

INDF = 10 + INDF

Este LOOP se utiliza para las horas después de trabajar con los minutos o los segundos

C = 0, no se incrementan las decenas y se suma 10 para restaurar las unidades

LOOP2

FSR = digito3

PROX_NUM

Próximo número: Primero ha sido segundos o minutos y luego horas

conta1 = conta1 -1

NO

conta1 = 0 SI

CONVER_COD_7S

Pag. 5

El puntero apunta a la primera posición de las decenas Se añade 1 a las decenas Se restaura el valor de INDF para la próxima resta hasta que se termine

Convierte cada dígito a código 7 segmentos para los displays

CONVER_COD_7S

Coloca la dirección del primer digito (digito1) en FSR Prepara la variable conta1 para el bucle de los 4 displays

FSR = digito1 conta1 = 4

PROX_DIGITO

Obtener el valor de la variable "digito" actual

w = INDF

Pag. 8

LLamar a la rutina de conversión a código 7 segmentos

CODIGO_7S

Colocar en la variable "digito" actual el código 7 segmentos devuelto Incremente INDF para el próximo "digito" Se resta 1 a conta1

INDF = w FSR = FSR + 1 conta1 = conta1 - 1

NO

Permitir que conta1 de sólo 4 vueltas

conta1 = 0 SI

BORRAR_CERO

¿digito4 = “0”?

Si hay un cero en el display de las decenas de hora no se muestra (borrado de los ceros a la izquierda)

NO

SI digito4 = SEGM_OFF Si está pulsado PSEG no se muestra nada en el display de la posición de la unidad de hora. Contando con BORRAR_CERO, esto significa que sólo se mostrarán los segundos.

BORRAR_CERO_SEG

PSEG = 1 NO

DISPLAY_PUL

SI

digito3 = SEGM_OFF

Pag. 3

Puesta en hora de horas y minutos

PONER_RELOJ

Inicia los segundos cuando se pone el reloj en hora

segundos = SEGS_INI (196d)

PONER_MINUTOS Comprobar si se ha pulsado PMIN (Pulsador minutos) PMIN = 1

NO

SI

Avance rápido del tiempo cuando se ajustan minutos frac_sec = 175 Incrementar los minutos

frac_sec = 175d minutos = minutos + 1

minutos = 0

NO

SI

Iniciar minutos si al incrementar se han desbordado

minutos = MINS_INI

PONER_HORAS

Comprobar si se ha pulsado PHOR (Pulsador horas)

PHOR = 1

NO

SI

Avance rápido del tiempo cuando se ajustan horas frac_sec = 127d Incrementar las horas

frac_sec = 127d horas = horas + 1

NO horas = 0 SI

horas = HORS_INI (232d)

OBTENER_H_M

Pag. 2

Incrementar segundos, minutos y horas Ajustes cada minuto, hora y 24 horas

INC_HORA

CHG = 1

Se especifica que se ha producido un cambio

segundos = segundos + 1

Como ha pasado un segundo se incrementa “segundos”

segundos = 0

NO

SI

segundos = SEGS_INI (196d) frac_sec = frac_sec – ADJMIN (9d) minutos = minutos + 1

minutos = 0

Se ha desbordado "segundos" y se reestablece el valor inicial de “segundos” para la próxima vuelta Se resta 9 a “frac_sec” cada minuto para los ajustes de tiempo El minuto será 9 “frac_sec” más largo. Se añade 1 minuto

NO

SI

minutos = MINS_INI (196d) frac_sec = frac_sec + ADJHOR (34d) horas = horas + 1

horas = 0

Se reestablece el valor inicial de “minutos” para la próxima vuelta Se suma 34 “frac_sec” a cada hora para los ajustes de tiempo La hora será 34 “frac_sec” más corta Se añade 1 hora

NO

SI

horas = HORS_INI (232d) frac_sec = frac_sec – ADJDIA (6d)

COMPROBAR_CHG

Se reestablece el valor inicial de “horas” para la próxima vuelta Se resta 6 a “frac_sec” cada 24 horas para los ajustes de tiempo Cada 24 horas se añadirán 6 "frac_sec"

Pag. 2

SUBRUTINAS

CODIGO_7S

addwf retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw

PCL,F CERO UNO DOS TRES CUATRO CINCO SEIS SIETE OCHO NUEVE

Devuelve el código 7 segmentos

Devuelve en el acumulador el valor de la constante CERO a NUEVE según el valor que se hubiese colocado en w

Get in touch

Social

© Copyright 2013 - 2024 MYDOKUMENT.COM - All rights reserved.