jueves, 4 de abril de 2013

HCS08 - Motorola Freescale - Contador 0 a 99 en 2 Display 7 Segmentos

Para ayudar a varios compatriotas en mi Universidad me he dispuesto a crear esta entrada.. bla bla bla

A lo bueno.

NOTA: Se seguirá usando para programar el microcontrolador el debugger ICSP tan usado en anteriores entradas (BDM).

Descripción del Proyecto.

Crear una cuenta de 0 a 99, la cual se incrementará en una unidad cada segundo, esta cuenta será en sistema decimal y los resultados de la misma serán mostrados en dos display de 7 segmentos, uno por digito.
Se usaran dos transistores 2N3906 como conmutadores para activar cada uno de los display de 7 conectando el común de estos al transistor los cuales por medio de un pulso en su Base activaran o desactivaran el display a conveniencia.
Se usan también dos Buffers de corriente CD4050 para que la corriente demandada por cada display se cargue sobre estos y no sobre los microcontroladores y que este ultimo solo tenga la acción de mandar pulsos lógicos de voltaje.


Contador digital

                Un contador digital es básicamente un circuito electrónico que muestra un cambio cada cierto periodo de tiempo establecido, este periodo de tiempo es común que sea ajustable.
Estos cambios se pueden manifestar de diferentes maneras de acuerdo a lo que se desee lograr, como por ejemplo, mostrar una cuenta de números en cualquier tipo interfaz visual, o activar cierto relé que a su vez crear más cambios.
También son usados como una manera sencilla de realizar acciones cada cierto tiempo.
En nuestro caso, nuestro contador mostrara una cuenta de números decimales del 0 al 99 mostrado en dos display de 7 segmentos, esta cuenta se incrementara en intervalos de una unidad cada segundo que pase.


Display de 7 segmentos

Los Display de 7 segmentos son básicamente un arreglo de leds ordenados de tal forma que encendiendo unos cuantos de estos puedes formar números y algunas letras, en otros símbolos.

Hay dos distintos, ya sea cátodo común o ánodo común, esto debido a que los leds dentro de los mismo tienen todos interconectados a un mismo punto el cátodo o el ánodo.
Por tanto conectando este punto común a una fuente de voltaje (para el caso del ánodo común) se puede encender cada led interno mandando un estado lógico bajo o a tierra (para el caso del cátodo común) y mandándole un pulso lógico alto.


Transistor PNP 2N3906

El transistor es un dispositivo semiconductor que cumple varias funciones, entre ellas están las de amplificador, oscilador, conmutador o rectificador. En este caso lo usaremos de conmutador para crear la acción de barrido en los display de 7 segmentos.







Esquematicos



Descarga: pdf

CODIGO
;*******************************************************************
;* This stationery serves as the framework for a user application. *
;* For a more comprehensive program that demonstrates the more     *
;* advanced functionality of this processor, please see the        *
;* demonstration applications, located in the examples             *
;* subdirectory of the "Freescale CodeWarrior for HC08" program    *
;* directory.                                                      *
;*******************************************************************

; Include derivative-specific definitions
            INCLUDE 'derivative.inc'
;
; export symbols
;
            XDEF _Startup
            ABSENTRY _Startup

;
; variable/data section
;
            ORG    RAMStart         ; Insert your data definition here
ExampleVar: DS.B   1
contador:    equ  $90
unidades:   equ   $92
unidadesA:  equ   $93          
decenas:    equ   $94
decenasA:   equ   $95
tope:       equ   $96

;
; code section
;
            ORG    ROMStart

_Startup:
            LDHX   #RAMEnd+1        ; initialize the stack pointer
            TXS
            CLI                     ; enable interrupts

PROG_PORTS:  
            MOV   #$FF,PTBDD         ;puerto B salida
            MOV   #$FF,PTCDD         ;declaramos puerto C como salida            
            MOV   #$64,RTCMOD        ;declaramos timer a un segundo, con tope el 100=$64
            MOV   #%1111,RTCSC
            
            MOV   #$00,contador       ;iniciamos el contador con cero
            MOV   #$00,unidades       ;inicializamos unidades y decenas
            MOV   #$00,decenas
            
                        ;cargamos el valor de ajuste a disp 7 segm en las memorias
            MOV   #111111,$80      ;ajuste del 0
            MOV   #000110,$81      ;ajuste del 1
            MOV   #%01011011,$82
            MOV   #%01001111,$83
            MOV   #%01100110,$84
            MOV   #%01101101,$85
            MOV   #%01111101,$86
            MOV   #000111,$87
            MOV   #%01111111,$88
            MOV   #%01100111,$89      ;ajuste del 9
            
main:
            feed_watchdog
            BSR   checa_cuenta        ;vamos a la subrutina que lleva la cuenta en unidades y decenas
            BSR   ajusta_unidades             ;subrutina que ajusta el valor de unidades y decenas para desplegarlo en el disp 7 segm
            BSR   ajusta_decenas
            LDA   unidadesA           ;cargamos unidades y decenas ajustadas y las mostramos en el display
            STA   PTBD
            MOV   #%10,PTCD
            BSR   retardo
            LDA   decenasA
            STA   PTBD
            MOV   #%01,PTCD
            BSR   retardo
            LDA   contador            ;checamos si se paso del 99
            CBEQA #$64,hacercero 
            BRA   main
;subrutina que regresa a cero todo
;-------------------
hacercero:
            MOV   #$00,unidades
            MOV   #$00,unidadesA
            MOV   #$00,decenas
            MOV   #$00,decenasA
            MOV   #$00,contador
            BRA   main


            
;--------------------------------
            
;--------------Rutina checa cuenta
checa_cuenta:
                LDA   RTCCNT
                CMP   contador
                BNE   incrementa_cuenta             ;si no es el mismo numero, es decir, ya cambio (ya paso el tiempo programado)
                RTS                                 ;si es el mismo, regresamos
                
incrementa_cuenta:
                LDA   RTCCNT                        ;como no son iguales, los hacemos iguales
                STA   contador
                INC   unidades                      ;si las unidades completa una decena
                LDA   unidades                      ;regresamos a cero unidades y decenas +1
                CMP   #$A
                BEQ   una_decena_mas
                RTS                
una_decena_mas:
                MOV   #$00,unidades
                INC   decenas
                RTS
;--------------termian rutina checa cuenta            
;---------------------*******Subrutina de retardo                
retardo:       
            LDHX  #$0000
RET1:        
            feed_watchdog
            AIX   #$01
            CPHX  #$FF            ;Se incrementa este valor para hacer un retardo mas largo
            BNE   RET1
            RTS
;-----------------------****Termian el retardo

;.---------------------------Subrutinas de ajuste            
ajusta_unidades:
                LDHX    #$80                    ;apuntamos a la memoria $80, que es donde empiezan los valores de ajuste
                MOV     #$80,tope               ;colocamos $80 en la memoria que servira de tope
                LDA     unidades
                ADD     tope                    ;cargamos las unidades y las sumamos a tope obteniendo asi ($80+unidades) la direccion del numero para ajustar
                STA     tope                
ciclo_unidades:                             
                feed_watchdog                   ;recorremos desde la memoria $80 hasta que llegemos a la memoria tope($80+unidades)
                CPX     tope  
                BEQ     salir_unidades
                INCX
                BRA     ciclo_unidades               
salir_unidades:                                
                LDA   ,X
                STA   unidadesA                 ;el valor de la memoria tope la guardamos en unidadesA el cual sera el valor ajustado de la unidad
                RTS
                
ajusta_decenas:
                LDHX    #$80                    ;misma explicacion que para unidades pero con decenas
                MOV     #$80,tope
                LDA     decenas
                ADD     tope
                STA     tope                
ciclo_decenas:
                feed_watchdog
                CPX     tope  
                BEQ     salir_decenas
                INCX
                BRA     ciclo_decenas               
salir_decenas:                                
                LDA   ,X
                STA   decenasA        
                RTS            
;--------------Terminan las subrutinas de ajuste            
            

;**************************************************************
;* spurious - Spurious Interrupt Service Routine.             *
;*             (unwanted interrupt)                           *
;**************************************************************
spurious:                           ; placed here so that security value
            NOP                     ; does not change all the time.
            RTI

;**************************************************************
;*                 Interrupt Vectors                          *
;**************************************************************
            ORG   $FFFA

            DC.W  spurious          ;
            DC.W  spurious          ; SWI
            DC.W  _Startup          ; Reset





Descarga .asm: aqui
Descarga el proyecto para CodeWarrior: aqui



REVISION

Este codigo que coloco fue desarrollado hace mucho tiempo por mí, así que por el momento no recuerdo del todo sí es 100% funcional o si falta ajustar algo (tengo varias versiones del mismo proyecto y coloqué aquí la mas reciente).

Pido a cualquier persona que se atreva a probarlo a comentar su funcionalidad.

tchao

3 comentarios:

  1. Sabes cómo podría hacer un retardo de 100mseg??

    ResponderEliminar
  2. Tienes que crear un ciclo que se repita N veces y calcular el tiempo de ejecucion por ciclo de tal forma que N * (tiempo_por_ciclo) = 100ms.
    No es facil, ocuparias ver el set de instrucciones y ver cuanto se tarda por instruccion y a partir de alli comenzar a calcular.

    Normalmente lo que se hace es incrementar y/o decrementar una variable en el cuerpo del ciclo.
    Vaya! Es basicamente tener ocupado al micro a lo idiota :)
    BTW nada recomendable.

    ResponderEliminar
  3. Que programa utilizas para hacer la simulación? muchas gracias!!!

    ResponderEliminar