Programación de Microcontroladores PIC16X84 [Diagramas de montaje + Programas]

Iniciado por Casidiablo, 2 Mayo 2006, 17:35 PM

0 Miembros y 1 Visitante están viendo este tema.

Casidiablo

Diagramas y SeudoEsquemas para implementar los Microcontroladores PIC16X84 en circuitos reales o protoboards + Programas en ASM y C

¡¡¡Put0 título tan largo que me he inventado xD!!! Nada, decir que obviamente los programas no los he inventado yo, sino que son la recopilación de los "ejemplos práticos" más usados. Los he sacado de unos cuantos libros cuyo nombre no me sé (en realidad son unas fotocopias que encontré por casualidad). Y aclarar que los dibujos los hice yo en Visio, y que talvez tengan uno que otro fallo, la verdad es que me costó un huevo hacer esos put0s dibujos; en fín, si encontrais algún fallo me lo comunicas por privado. Sino conoceis como es este rollo de los Microcontroladores PIC, podeis hecharle un vistazo a este post: Introducción a microcontroladores PIC [simulando nuestro programas en ASM y C] (no te demoras sino 20 o 30 minutillos leyéndolo).


Primer Ejemplo: Explorando interruptores y encendiendo luces.

SeudoEsquema de Montaje

Descripción: Lee el número binario introducido mediante 3 interruptores conectados a la puerta A, luego suma 2 unidades a ese valor y visualiza el resultado mediante 4 diodos led conectados a la puerta B.

Programa en Assembler:

;----------------------------------------------------------------------------
    LIST    P=16C84         ;Comando que indica el PIC usado
    RADIX   HEX             ;Los valores se representar n en hexadecimal
;----------------------------------------------------------------------------
    PUERTAA EQU     0X05    ;La etiqueta "PUERTAA" queda identificada con
                            ;la dirección 0x05, que si corresponde con el
                            ;banco 0 es el valor de PUERTAA y si es del
                            ;banco 1 con el de TRISA.
    PUERTAB EQU     0X06    ;Equivalencia de la etiqueta PUERTAB
    ESTADO  EQU     0X03    ;Estado corresponde con el valor 0x03.
    W       EQU     0       ;Identifica W con el valor 0.
;----------------------------------------------------------------------------
    ORG     0               ;Comando que indica al Ensamblador la
                            ;dirección de la memeoria donde se
                            ;situar  la instrución siguiente
;----------------------------------------------------------------------------
    bsf     ESTADO,5        ;Pone a 1 el bit 5 de ESTADO para direccionar
                            ;la p gina 1 de la memoria de datos.
    movlw   0xff            ;W <-- FF(Hex)
    movwf   PUERTAA         ;W --> TRISA
    movlw   0x00            ;W <-- 0
    movwf   PUERTAB         ;W --> TRISB (Las líneas de PB salidas)
    bcf     ESTADO,5        ;Pone a 0 el bit 5 de ESTADO pasando a
                            ;acceder al banco 0.
   
    inicio movf PUERTAA,W   ;W <-- PUERTAA. Se introduce el valor binario
                            ;de los interruptores.
    addlw   2               ;W <-- W + 2
    movwf   PUERTAB         ;W --> PUERTAB. El valor de W sale por las
                            ;líneas de PB a los led.
    goto    inicio          ;Salta a la instrucción precedida por la
                            ;etiqueta de inicio.
    END



Programa en C:

#INCLUDE <16C84.H>
void main(void)
{
    int valor;              /* Valor temporal */
    int * p_puertaa= 0x05;  /* Puntero a PuertaA */
    int * p_puertab= 0x06;  /* Puntero a PuertaB */
   
    SET_TRIS_A (0xff);      /* 0xff --> TRISA */
    SET_TRIS_B (0x00);      /* 0x00 --> TRISB */
    do
    {
        valor = * p_puertaa;/* PuertaA --> valor  */
        valor += 2;         /* se incrementa valor en 2 */
        *p_puertab = valor; /* valor --> puertaB */
    }while(true);          /* Bucle infinito */
}



Segundo Ejemplo: Más interruptores y diodos led.

Esquema de Montaje

Descripción: Muestra por cinco diodos led en la puerta B la entrada que proporcionan cinco interruptores en la puerta A.

Programa en Assembler:

    LIST    p=16c84    ; Se usa el PIC16C84
    RADIX   hex        ; Se emplea el sistema de numeración hexadecimal
   
; ZONA DE ETIQUETAS-----------------------------------------------------------------------
    W    EQU    0      ; Cuando el destino es W, d = 0
    F    EQU    1      ; Cuando el destino es el registro f, d = 1
    PUERTAA EQU 0x05   ; La Puerta A (datos) ocupa la dirección 5 del
                       ; banco 0 y el registro de configuración la
                       ; dirección 5 del banco 1
    PUERTAB EQU 0x06   ; La misma etiqueta para el registro de datos y el
                       ; de configuración de la Puerta B
    ESTADO  EQU 0x03   ; El registro Estado ocupa dirección 3 de los dos bancos

; COMIENZO DEL PROGRAMA -----------------------------------------------------------------

    ORG    0           ; El programa comienza en la dirección 0 (Vector Reset)
    goto   inicio      ; Se salta a la etiqueta "inicio"
    ORG 5              ; Se asigna la dirección 5 a la siguiente instrucción
   
    inicio bsf ESTADO,5 ; Pone a 1 el bit 5 de Estado. Acceso al banco 1.
    clrf    PUERTAB     ; Se configuran como salidas las líneas de la Puerta B
    movlw   0xff        ; El registro W se carga con unos
    movwf   PUERTAA     ; Se configuran como entradas las líneas de la Puerta A
    bcf     ESTADO,5    ; Pone a 0 el bit 5 de Estado. Acceso al banco 0.
    bucle movf PUERTAA,W; Carga el registro de datos de Puerta A en W
    comf    PUERTAA,W   ; Complementa a 1 la entrada y la deposita en W
    movwf   PUERTAB     ; El contenido de W se deposita en el registro de datos de
                        ; la Puerta B
    goto    bucle       ; Se crea un bucle cerrado e infinito
   
    END                 ; Fin del programa


Programa en C:

#include <16c84.h>
#byte   puertaa = 05   /* Posición de la puerta A */
#byte   puertab = 06      /* Posición de la puerta B */
void main( void )
{
    int temp;
    set_tris_a( 0xFF );     /* Puerta A configurada para entrada */
    set_tris_b( 0x00 );     /* Puerta B configurada para salida  */
    do
    {
        /* La variable temporal es necesaria porque    */
        temp = ~puertaa;    /* la complementación se traduce en dos pasos: */
        puertab = temp;     /* a) Copia de puertaa en temp                 */
    }
    /* b) Complementación de temp                  */
    /* De no hacerlo así los LED parpadearían      */
    while( TRUE );/* Repetir ininterrumpidamente       */
}



Tercer Ejemplo: Contando y visualizando.

Esquema de Montaje

Descripción: Hace un conteo desde 0 hasta 0x5f y muestra en las patitas RB.

Programa en Assembler:

;----------------------------------------------------------------------------
    LIST    P=16C84
    RADIX   HEX
;----------------------------------------------------------------------------

    W       EQU     0x00    ; Comienzo del campo de etiquetas.
    F       EQU     0x01
    PUERTAB EQU     0x06
    ESTADO  EQU     0x03
    CONTA   EQU     0x0C
   
;----------------------------------------------------------------------------

    ORG     0               ; El programa comienza en la dirección 0 y
    goto    inicio          ; salta a la dirección 5 para sobrepasar
    ORG     5               ; el vector de interrupción.

;----------------------------------------------------------------------------

    inicio  bsf     ESTADO,5    ; Seleciona el banco 1
        movlw   0x00            ; Se configura PuertaB como salida
        movwf   PUERTAB
        bcf     ESTADO,5        ; Selección del banco 0
       
;----------------------------------------------------------------------------

    clrf    CONTA           ; CONTA = 0
    bucle1  incf  CONTA,F   ; CONTA + 1 --> CONTA
        movf    CONTA,W         ; CONTA se carga en W
        movwf   PUERTAB         ; W se carga en el registro de datos PB
        movlw   0x5f            ; W <-- 0x5f
        subwf   CONTA,W         ; CONTA - W --> W
        btfss   ESTADO,2        ; Explora Z y si vale 1 se produce "brinco"
    goto    bucle1          ; Si Z = 0 se vuelve a bucle1
     
    bucle2  goto    bucle2  ; si Z = 1 se produce un bucle infinito
    end


Programa en C:

#include <16c84.h> /* Tipo de PIC a usar */
#byte puertab=0x06
#byte conta=0x0C
void main(void)
{
    set_tris_b(0x00);    /* Configura la PB como salida */
    for (conta=0;conta<=0x5f;++conta)    /* Bucle que incrementa CONTA de 0 */
        puertab=conta;                   /* a 0x5f */
}



Cuarto Ejemplo: Controlando el tiempo.

SeudoEsquema de Montaje

Descripción: Programa que ilustra cómo realizar una temporización sin emplear interrupciones.

Programa en Assembler:

    LIST     P=16C84
    RADIX    HEX
; ------------------------------------------------------------------------

    PUERTAA  EQU  0x06
    OPTION   EQU  0x01
    ESTADO   EQU  0x03
    TMR      EQU  0x01
   
; ------------------------------------------------------------------------
   
    ORG   0    ; Inicio del programa en
               ; dirección 0
               
; ------------------------------------------------------------------------

    bsf    ESTADO,5     ; Banco 1
    movlw  b 1101 0110  ; Valor a cargar en
                        ; OPTION
    movwf  OPTION
    movlw  0x00
    movwf  PUERTAB      ; La Puerta B salida
    bcf    ESTADO,5     ; Banco 0
    clrf   PUERTAB      ; Las líneas de salida
                        ; de PB a 0
                       
    parpa bsf PUERTAB,7 ; Enciende el led RB7 = 1
    call  retardo       ; Llamada a subrutina de
                        ; RETARDO
    bcf   PUERTAB,7     ; Apaga el led, RB7 = 0
    call  retardo
    goto  parpa
   
    retardo clrf TMR0   ; TMR0 = 0 y empieza su
                        ; incremento
                       
    explora btfss TMR0,4; TMR0<4> = 1?
    goto   explora      ; No ha llegado TMR0 a 16d
    return              ; Ha llegado TMR0 al
                        ; valor 16d  y retorna
                        ; al programa principal
                       
    END


Programa en C:

#include <16C84.H>
#use delay( clock = 1000000 )  /* Especifica reloj de 1 MHz */
#byte puertab = 06              /* Dirección de la puerta B  */
void main( void )
{
    set_tris_b( 0x00 );
    puertab = 0;
    do
    {
        delay_us( 8700 );    /* Crea un bucle de espera de 8700 microsegundos */
        bit_set(puertab,7);  /* Enciende el LED */
        delay_us(8700);      /* Espera */
        bit_clear(puertab,7);/* Apaga el LED */
    }while(true);            /* Repetir siempre */
}



Quinto Ejemplo: Manejando Interrupciones.

SeudoEsquema de Montaje

Descripción: Refleja el estado de dos interruptores situados en RA0 y RA1 en RB0 y RB1 mientras hace parpadear un diodo en la línea RB7.

Programa en Assembler:

;----------------------------------------------------------------------------
   
    LIST    P=16C84
    RADIX   HEX
   
;----------------------------------------------------------------------------

    W    EQU    0
    F    EQU    1
    TMR_OPT EQU 0x01   ; TMRO en banco 0 OPTION en banco 1
    ESTADO EQU  0x03
    PUERTAA EQU 0x05   ; PA en banco 0 TRISA en banco1
    PUERTAB EQU 0x06   ; PB en banco 0 TRISB en banco1
    INTCON EQU  0x0B   ;
    CONTA  EQU  0x10   ; Contador auxiliar

;----------------------------------------------------------------------------

    ORG    0        ; Vector de Reset
    goto   inicio
   
    ORG    4        ; Vector de Interrupción
    goto   inter    ; Salta a comienzo de rutina de interrupción
    ORG    5
   
    inicio bsf  ESTADO,5        ; Selección del banco 1
    clrf   PUERTAB              ; Configura PUERTA B como salida
   
    movlw   b'00000011'         ; Configura RA0, RA1 como entradas
    movwf   PUERTAA
   
    movlw   b'00000111'
    movwf   TMR_OPT
   
    bcf     ESTADO,5            ; Banco 0
   
    movlw   b'10100000'         ; Se permite interrupción del
    movwf   INTCON              ; TMR0 y la globla (GIE)
   
    movlw   0x10
    movwf   CONTA               ; Se carga CONTA con 16 decimal
   
    movlw   0x0c
    movwf   TMR_OPT             ; Se carga TMR0 con 12 decimal
   
    bucle   btfsc   PUERTAA,0   ; Explora RA0 y brinco si vale 0
        goto    ra0_1           ; salta a RA0_1
        bcf     PUERTAB,0       ; Si RA0 = 0 sa saca por RB0 un 0
        goto    ra1x            ; A explorar RA1
       
        ra0_1 bsf   PUERTAB,0   ; Si RA0 = 1 se saca por RB0 un 1
   
        ra1x  btfsc PUERTAA,1   ; Examina ra1  y brinco si es 0
        goto    ra1_1           ; Salta  si RA1 = 1
        bcf     PUERTAB,1       ; Si RA1 = 0, RB1 = 0
       
        goto    bucle2
        ra1_1   bsf  PUERTAB,1  ; Si RA1 = 1 , RB1 = 1
    bucle2  goto    bucle       ; Bucle indefinido, se sale por la interupción
   
;----------------------------------------------------------------------------

    inter   decfsz  CONTA,1     ; RSI. Decrementa CONTA y brinco si vale 0
    goto    seguir
   
    conta_0 movlw   0x10        ; Si CONTA = 0 se carga
        movwf   CONTA
       
        btfsc   PUERTAB,7       ; Si RB7 = 0, brinco
        goto    rb7_1
        bsf     PUERTAB,7       ; Si RB7 = 0, se invierte
        goto    seguir
       
    rb7_1   bcf     PUERTAB,7   ; Si RB7 = 1 , se invierte
   
    seguir  movlw   b'10100000' ; Se restaura INTCON por desactivar las
        movwf   INTCON          ; interrupciones el procesador
        movlw   0x0c
        movwf   TMR_OPT         ; Se recarga TMR0 con 12
        retfie
       
        end


Programa en C:

#include <16c84.h> /* Selección del PIC a usar */
#use delay(clock= 4000000) /* Reloj de 4 MHz */
#BYTE puertab = 6
#define maximo 16 /* Constante: maximo = 16 */
byte conta;
/*--------------------------------------------------------------------------*/
/* SERVICIO DE LA INTERRUPCIóN */
#INT_RTCC /* Interrupción por desvordamiento del timer*/
clock_isr()
{
    short valor;
    short novalor;
    valor = bit_test(puertab,7); /* El bit valor es igual al contenido */
                                    /* de RB7 */
                                   
    novalor = !valor;
    if (--conta==0)
    {
        output_bit (PIN_B7,novalor); /* Voltea RB7 */
        delay_us (5);
        conta = maximo;
    }
}

/* PROGRAMA PRINCIPAL */
main()
{
    short ra0,ra1;
   
    set_tris_b(0x00); /* Se inicializa PB */
    conta=maximo;
    set_rtcc(0); /* Se inicializa el timer a cero */
   
    setup_counters(rtcc_internal,rtcc_div_256);
   
    enable_interrupts(rtcc_zero); /* Se permite int del tmr0 */
   
    enable_interrupts(GLOBAL); /* Se activa GIE */
   
    /* Rutina de control de los leds e interruptores: */
    do
    {
        ra0 =  input(PIN_A0);
        ra1 =  input(PIN_A1);
       
        output_bit (PIN_B0,ra0);
        output_bit (PIN_B1,ra1);
    }
    while(true); /* Bucle infinito */
}



Séptimo Ejemplo: Proyecto para manejar un display de 7 segmentos.

SeudoEsquema de Montaje

Descripción: Programa que visualiza un número del 1 al 7 en un display de siete segmentos en la puerta B dependiendo del valor binario de tres interruptores situados en la puerta A.

Programa en Assembler:

    LIST    P=16C84
    RADIX HEX
   
    w EQU 0
    f EQU 1
    PCL EQU 02
    PUERTAA EQU   05
    PUERTAB EQU   06
    ESTADO  EQU   03
    VALOR EQU 12 ; Registro auxiliar
   
; RUTINA PRINCIPAL: Lectura de los interruptores y c lculo del valor a visualizar

    ORG   0
    goto  inicio
    ORG   5               ; Para saltar el Vector de
                          ; Interrupción
   
    inicio bsf ESTADO,5   ; Selección del banco 1
        clrw
        movwf  PUERTAB    ; Puerta B salida
        movlw  0xff
        movwf  PUERTAA    ; puerta A entrada
        bcf ESTADO,5      ; Selección banco 0
        explora  movf PUERTAA,w  ; Se cargan los
                                 ; interruptores en W
        movwf VALOR     ; Se usa un registro auxiliar
        comf    VALOR,f   ; Invertir los niveles de interuptores
        clrw
        btfss   VALOR,0   ; Si RA0 = 1, brinca
        goto    bit_1     ; Salta a explorar el bit_1
        addlw   0x01      ; Si RA0 =1, se suma
        bit_1 btfss VALOR,1; Si RA1 = 1, brinca
        goto    bit_2     ; Salta a explorar el bit_2
        addlw   0x02      ; Si RA1 = 1, se suman 2
        bit_2 btfss VALOR,2; Si RA2 = 1, brinca
        goto    visual    ; Salta al módulo del display
        addlw   0x04      ; Si RA2 0 1, se suman 4
        visual  call  display ; Salta al módulo del display
       
; DISPLAY: Rutina de visualización del acumulador en el display de 7 segmentos

    movwf   PUERTAB       ; Al retornar de la subrutina
                          ; el valor de W se saca por la
                          ; Puerta B
    bucle  goto  bucle    ; bucle infinito
   
; TABLA DE CONVERSION---------------------------------------------------------

    display  addwf  PCL,f  ; pcl + W -> W
                           ; El pcl se incrementa con el
                           ; valor de W proporcionando un
                           ; salto
    retlw   0x3F           ; Retorna con el valor del
                           ; código del 0
    retlw   0x06           ; Retorna con el código del 1
    retlw   0x5b           ; Retorna con el código del 2
    retlw   0x4f           ; Retorna con el código del 3
    retlw   0x66           ; Retorna con el código del 4
    retlw   0x6d           ; Retorna con el código del 5
    retlw   0x7d           ; Retorna con el código del 6
    retlw   0x07           ; Retorna con el código del 7
   
    END


Programa en C:

#include <16C84.H>
#byte puertaa = 05  /* Posición de la puerta A */
#byte puertab = 06  /* Posición de la puerta B */
void main( void )
{
    int temp = 0, tabla[8]={ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07 };
    int indice = 0;
    set_tris_a( 0xFF );   /* Puerta A configurada para entrada */
    set_tris_b( 0x00 );   /* Puerta B configurada para salida  */
    temp = ~puertaa;      /* Se complementa la entrada de PA   */
    if ( bit_test( temp, 0 ) ) indice += 1;
    if ( bit_test( temp, 1 ) ) indice += 2;
    if ( bit_test( temp, 2 ) ) indice += 4;
    puertab = tabla[indice];
}



Ejemplos básicos de programación de Microcontroladores PIC16X84 sin esquemas ni diagramas; enunciados de los ejemplos:


  • Control de un dispositivo desde dos puntos: Se desea controlar una lámpara, en este caso un diodo LED desde dos interruptores, de forma que cuando los dos interruptores están abiertos el LED está apagado. A partir de esta situación, cada vez que cambie el estado de un interruptor, el estado del LED bascula  (si está apagado se enciende y viceversa)
  • Semáforo programabe: Se simula un semáforo con 3 diodos LED. Se dispone de 2 interruptores que según la combinación que adopten originan una secuencia de encendido de las luces del semáforo.
  • Dado electrónico: Este programa simula el juego del dado. Un dado típico tiene 6 caras, en cada una de las cuales viene dibujado un número del 1 al 6. Cada vez que se presiona un pulsador se produce un número aleatorio entre 1 y 6, el cual se visualiza en un display de 7 segmentos.
  • Temporizador programable: Con 3 microrruptores se selecciona un valor entre el 0 y el 7 (binario), que representa un tiempo en segundos y que ser  visualizado por el display de 7 segmentos. Durante el tiempo que dura la temporización un LED rojo permanece activado, así como un zumbador. Al finalizar se desactivan ambos elementos y el display se pone a 0.
  • Alarma: Se tienen 3 detectores digitales, cada uno de los cuales provocar la activación de un LED, diferente en cada caso. Uno de los detectores ser  un optoacoplador y los otros 2 se simularán mediante 2 microrruptores. El programa consiste en poner en marcha un zumbador cuando la alarma salte por causa de la activación de cualquiera de los detectores. También se enciende el LED correspondiente al detector. La alarma sólo funcionará cuando el microrruptor I1 de conexión esté a nivel alto.
  • Ejemplo tomado de Internet: (Autor: David Tait, david.tait@man.ac.uk) Este programa ilumina una serie de leds en secuencia principio-fin-principio (algo así como las luces del "El Coche Fantástico).
  • Manejo del WatchDog (perro guardián): El objetivo de este programa es mostrar en la práctica el funcionamiento del Watchdog en el PIC 16c84. El programa entra en un bucle infinito del que sale tras cumplirse la temporización asiganada al watchdog, que en este caso ser n 36 ms, es decir 2 veces la temporización nominal.



En un futuro post talvez coloque un pequeño glosario de las instrucciones de Assembler para esta gama de microcontroladores, para los que no entienden mucho los códigos; por lo demás espero que les sea de ayuda ;) Y anexo también el archivo donde tengo los (seudo)diagramas en formato *.vsd (Visio), por si lo necesitan o quisieran modificar algún put0 dibujito de esos.

Saludos!!!

correo900

Muy buen post sobre los PIC16x84 me lo guardo que esta interesante el tema.

Gracias por tu aportacion.

Saludos.

Meta

Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/