Reporte - Villegas990/LabMicros_2Prac GitHub Wiki
Contador con velocidad variable
Descripción El estudiante implementará un sistema basado en microcontrolador. Dicho sistema irá incrementado un contador cada cierto tiempo. Dicho tiempo podrá ser modificado por el usuario mediante el uso de 2 push-buttons, uno para aumentar la velocidad y otro para disminuirla. El contador deberá ser mostrado en un display de 7 segmentos e indicar mediante 5 leds la velocidad seleccionada. Objetivo Familiarizarse con el uso y programación de ‘delays” para generar retrasos en la ejecución de algún sistema. Material
Protoboard PIC18F4550 2 push buttom Display de 7 segmentos Resistencia de 1KΩ 5 leds
Desarrollo La primera parte que desarrollamos fue el contador de 9-0, donde nuestro numero esta guardado en la variable TEMP. En cuyo caso que nuestro numero ya sea 0, este se ira a la subrutina TURN_NINE donde tomara el valor de 10; teniendo TEMP un valor diferente a 0 este se restara para que sea decodificado y una vez decodificado ser mandara a nuestro display los números del 9 al 0.
BASE: MOVF TEMP,W ; BZ TURN_NINE ; DECF TEMP ; CALL DECODE ;
DECODE: MOVLW 0x00 ; SUBWF TEMP,0 ; BZ D_ZERO ; MOVLW 0x01 ; SUBWF TEMP,0 ; BZ D_ONE ; MOVLW 0x02 ; SUBWF TEMP,0 ; BZ D_TWO ; MOVLW 0x03 ; SUBWF TEMP,0 ; BZ D_THREE ; MOVLW 0x04 ; SUBWF TEMP,0 ; BZ D_FOUR ; MOVLW 0x05 ; SUBWF TEMP,0 ; BZ D_FIVE ; MOVLW 0x06 ; SUBWF TEMP,0 ; BZ D_SIX ; MOVLW 0x07 ; SUBWF TEMP,0 ; BZ D_SEVEN ; MOVLW 0x08 ; SUBWF TEMP,0 ; BZ D_EIGHT ;. MOVLW 0x09 ; SUBWF TEMP,0 ; BZ D_NINE ; RETURN;
D_ZERO: MOVLW b'01111110' ;//0 MOVWF PORTD ; RETURN; D_ONE: MOVLW b'00110000' ;//1 MOVWF PORTD ; RETURN ; D_TWO: MOVLW b'01101101' ;//2 MOVWF PORTD ; RETURN ; D_THREE: MOVLW b'01111001' ;//3 MOVWF PORTD ; RETURN ; D_FOUR: MOVLW b'00110011' ;//4 MOVWF PORTD ; RETURN ; D_FIVE: MOVLW b'01011011' ;//5 MOVWF PORTD ; RETURN; D_SIX: MOVLW b'01011111' ;//6 MOVWF PORTD ; RETURN ; D_SEVEN: MOVLW b'01110000' ;//7 MOVWF PORTD ; RETURN ; D_EIGHT: MOVLW b'01111111' ;//8 MOVWF PORTD ; RETURN; D_NINE: MOVLW b'01111011' ;//9 MOVWF PORTD ; RETURN ;
TURN_NINE: MOVLW d'10' ; MOVWF TEMP ; GOTO BASE ;
Para los delays usamos una lógica de un ciclo usando la instrucción DECFSZ y llamadas a partes del código con GOTO, el ciclo tiene la lógica n*(3*x)*x, ya que cada instrucción dura un microsegundo, ocupamos que se hagan 1000000 de instrucciones para que dure un segundo por lo que n tendrá el valor de 6 y x el valor de 236; donde se haría 1002528 instrucciones acercándose al segundo. Para visualizar en que velocidad estamos pusimos 5 leds en el puerto C y mandamos un 1 a su respectivo led.
DELAY_1S: MOVLW b'00100000' MOVWF PORTC MOVLW d'6' ; MOVWF TM1 ; MOVLW D'236' ; T3: MOVWF TM2 ; T2: MOVWF TM3 ; T1: DECFSZ TM3 ; GOTO T1 ; DECFSZ TM2 ; GOTO T2 ; DECFSZ TM1 ; GOTO T3 ; RETURN ;
Una vez teniendo el delay de un segundo lo único que se hacia es que se implementaba la mismo logica de codigo, solo cambiamos nuestra n y x para que nos del valor correcto. En el caso del delay de 5 segundos solo cambiamos el valor de n a '30' y x que3da en 236, para que sea hagan 5 veces mas instrucciones por lo que duraría 5 veces mas el segundo, dándonos los 5 segundos.
DELAY_5S: MOVLW b'01000000' MOVWF PORTC MOVLW d'30' ; MOVWF TM1 ; MOVLW D'236' ; T35: MOVWF TM2 ; T25: MOVWF TM3 ; T15: DECFSZ TM3 ; GOTO T15 ; DECFSZ TM2 ; GOTO T25 ; DECFSZ TM1 ; GOTO T35 ; MOVLW b'00000000' MOVWF PORTC RETURN ;
Para el delay de 10 segundos, ocupamos que sea el doble de 5 segundos por que n valdrá 60, x se mantiene en 236.
DELAY_10S: MOVLW b'10000000' MOVWF PORTC MOVLW d'60' ; MOVWF TM1 ; MOVLW D'236' ; T310: MOVWF TM2 ; T210: MOVWF TM3 ; T110: DECFSZ TM3 ; GOTO T110 ; DECFSZ TM2 ; GOTO T210 ; DECFSZ TM1 ; GOTO T310 ; RETURN ;
Para los delays pequeños, en el caso del delay de .5 segundos; usamos la logica de los delays anteriores. Por lo que si queremos la mitad del tiempo nuestra n tendra la mitad del valor que tiene en el delay de un segundo; en este caso n vale 3 y x aun se mantiene en 236.
DELAY_500mS: MOVLW b'00000010' MOVWF PORTC MOVLW d'3' ; MOVWF TM1 ; MOVLW D'236' ; T305: MOVWF TM2 ; T205: MOVWF TM3 ; T105: DECFSZ TM3 ; GOTO T105 ; DECFSZ TM2 ; GOTO T205 ; DECFSZ TM1 ; GOTO T305 ; RETURN ;
En el caso del delay de .1 segundos, si seguíamos la misma lógica que los delays anteriores, n valdría .6 y x valdría 236; pero para evitar usar números decimales n lo dejamos el valor de 6 y despejando nos da que x debe valer 75 para que el delay tarde .1 segundos.
DELAY_100mS: MOVLW b'00000001' MOVWF PORTC MOVLW d'6' ; MOVWF TM1 ; MOVLW D'75' ; T301: MOVWF TM2 ; T201: MOVWF TM3 ; T101: DECFSZ TM3 ; GOTO T101 ; DECFSZ TM2 ; GOTO T201 ; DECFSZ TM1 ; GOTO T301 ; RETURN ;
Para poder cambiar de velocidad, creamos una variable llamada IDX, IDX tomara valores del 0 al 4, para la velocidad mas rápida (la de .1 segundos) IDX tomara el valor de 0; y mientras se incremente IDX mas se incrementara el tiempo de espera. Por ende; nuestra velocidad mas lenta IDX tendrá el valor de 4.
El reto que tuvimos fue el de evitar que IDX tuviera un valor mayor a 4 y menor a 0; por que lo que creamos dos subrutinas; una para subir la velocidad y otra para bajarla; para la subrutina DEC_VEL; IDX no puede pasar de 4 por lo que mandamos un 4 a W y restamos ese 4 a IDX; de esta manera podemos usar la instrucción BZ que nos mandara a la subrutina INC_VEL evitando así que nuestro IDX sea mayor a 4; en caso de no tener un 4 nuestra IDX podrá aumentar en caso de estar presionado el botón.
DEC_VEL: MOVLW 0x04 SUBWF IDX,0 BZ INC_VEL BTFSC PORTB,RB7 INCF IDX RETURN
En caso de la subrutina INC_VEL; usamos la misma lógica solo mandando un 0 ahora a w para evitar que IDX tenga un valor menor a 0.
INC_VEL: MOVLW 0x00 SUBWF IDX,0 BZ DEC_VEL BTFSC PORTB,RB6 DECF IDX RETURN
Una vez teniendo nuestras subrutinas que cambiaran el valor de nuestra IDX, creamos la subrutina con la que IDX llamara al delay que queramos implementar; para esto decidimos usar la instruccion BZ para que mandar a llamar el delay dependiendo del valor de IDX.
VEL_TABLE: MOVLW 0x00 SUBWF IDX,0 BZ DELAY_100mS MOVLW 0x01 SUBWF IDX,0 BZ DELAY_500mS MOVLW 0x02 SUBWF IDX,0 BZ DELAY_1S MOVLW 0x03 SUBWF IDX,0 BZ DELAY_5S MOVLW 0x04 SUBWF IDX,0 BZ DELAY_10S RETURN
Por ultimo modificamos nuestra base; usando la instruccion BTSFC checamos que cuando nuestros botones en RB7(para decrementar la velocidad) y en RB6(Para aumentar la velocidad); llamen a sus respectivas subrutinas que les permite modificar el valor de IDX y asi llamar a la subrtuina VEL_TABLE para que se implemente el delay correcta antes de que nuestro display cambie de numero.
BASE: MOVF TEMP,W ; BZ TURN_NINE ; DECF TEMP ; BTFSC PORTB,RB7 CALL DEC_VEL BTFSC PORTB,RB6 CALL INC_VEL CALL VEL_TABLE CALL DECODE ; GOTO BASE ;infinite loop
Preguntas y resultados
1. ¿Generaste los retrasos de forma individual? ¿Qué harías si tuvieras que hacer 100 diferentes retrasos? Si pudimos generar los retrasos de forma indivual, por lo que si tuviéramos que implementar 100 diferentes retrasos no tendríamos ningún problema ya que nuestra IDX puede llegar a tener un valor aun mayor que 100; y solo tendríamos que crear las subrutinas correspondientes.
2. Un problema que tuvimos es la hora de implementar la practica en físico; nuestro cristal de 4Mhz estaba descompuesto, por lo que tuvimos que usar un cristal interno del microcontralador y los delays son mas lentos.
Video de la implementacion fisica. https://www.youtube.com/watch?v=aPtAVMhDwII