ENUNCIADO:
La figura muestra un PIC16F84 al que estan conectados un convertidor analogico-digital ADC0801, y dos displays de 7 segmentos TDS11, mediante dos latch tipo D 74HC374:
Se desea muestrear la señal analogica a una frecuencia de 1 KHz y mostrar en los displays el valor de la conversion A/D en hexadecimal. Para la temporizacion debemos usar interrupciones.
Nota: el ADC no es mas que un conversor analogico-digital de 8 bits, que recibe una señal de entrada de tension entre 0V y Vcc y muestra una salida en funcion del valor de entrada. El 74HC374 no es mas que un conversor binario-BCD, para sacar el valor de entrada por el display de 7 segmentos. Podeis descargar la documentacion al final de esta entrada.
SOLUCION EN ENSAMBLADOR:
ENSAMBLADOR:
LIST p=16F84A
INCLUDE "P16F84A.INC"
WTEMP EQU 0x0C
VALOR EQU 0x0D
ORG 0x00
GOTO INICIO
ORG 0X04 ;El vector de interrupcion, que esta en la pos. de memoria 4
GOTO INTMR0
INICIO bcf STATUS,RP0 ;banco 0
CLRF PORTA
CLRF PORTB
movlw b'00000011'
movwf PORTA
bsf STATUS,RP0 ;banco 1
clrf TRISA ;salida
clrf TRISB ;salida
bsf TRISA,RA2 ;ra2=entrada
movlw b'00000001'
movwf OPTION_REG ;Prescaler 1:4
bcf STATUS,RP0 ;banco 0 (porque el tmr0 esta en este banco)
movlw 0x05 ;250*4=1000 ciclos de instruccion
;1 ciclo de instruccion=1 micro segundo
;Valor inicial del timer a 5 para que salte a los 10ms
movwf TMR0
movlw b'10100000'
movwf INTCON
LOOP
movlw VALOR
andlw 0x0F ;quitamos la parte alta del numero
call DISPLAY
movwf PORTB ;parte baja al bus
bsf PORTA,RA4 ;almacenamos en el latch el valor
bcf PORTA,RA4
swapf VALOR,W ;dejamos la parte alta del valor
andlw 0x0F
call DISPLAY
movwf PORTB ;parte baja al bus
bsf PORTA,RA3 ;almacenamos en el latch el valor
bcf PORTA,RA3
GOTO LOOP
DISPLAY
addwf PCL,F
retlw b'00111111' ;valor 0
retlw b'00000110' ;valor 1
retlw b'01011011' ;valor 2
retlw b'01001111' ;valor 3
retlw b'01100110' ;valor 4
retlw b'01101101' ;valor 5
retlw b'01111101' ;valor 6
retlw b'00000111' ;valor 7
retlw b'01111111' ;valor 8
retlw b'01100111' ;valor 9
retlw b'01110111' ;valor A
retlw b'01111100' ;valor B
retlw b'00111001' ;valor C
retlw b'01011110' ;valor D
retlw b'01111001' ;valor E
retlw b'01110001' ;valor F
INTMR0
movwf WTEMP ;Guardamos el W a un registro temporal (mover a registros generales)
bcf STATUS,RP0 ;banco 0
bcf PORTA,RA0 ;iniciamos conversion
bsf PORTA,RA0
CONV
BTFSC PORTA,RA2 ;mientras ra2 sea 1, no saltamos
GOTO CONV
BCF PORTA,RA1 ;iniciamos lectura
BSF STATUS,RP0 ;banco 1
COMF TRISB ;el comp hace el complementario (cambia unos por ceros y viceversa)
;puerto b como entrada (es otra forma de hacerlo)
bcf STATUS,RP0 ;BANCO 0
movlw PORTB
movwf VALOR
BSF PORTA,RA1 ;acabamos lectura
BSF STATUS,RP0 ;banco 1
COMF TRISB ;puerto b como salida
BCF STATUS,RP0 ;banco 0
movlw 0x05
movwf TMR0
bcf INTCON,T0IF
movlw WTEMP
RETFIE
end
SOLUCION EN C:
/*
Solucion en C
Compilador utilizado: XC8
*/
//podemos usar cualquiera de las dos cabeceras siguientes:
//#include <xc.h>
#include <pic16f84a.h>
//variables globales
unsigned char VALOR=0;
//rutina de servicio a la interrupcion
//un void no tiene retorno
void interrupt rsi()
{
//iniciamos la conversion
RA0=0;
RA0=1;
//bucle: esperamos a que acabe la conversion
while(RA2==1)
{
}
//iniciamos la lectura
RA1=0;
//pueto b como entrada
TRISB=0b11111111; //TRISB=0xFF; //TRISB=255;
VALOR=PORTB;
//finalizamos la lectura
RA1=1;
TRISB=0b00000000;
//reseteamos TMR0
TMR0=0x05;
T0IF=0;
//otra forma de hacer lo anterior:
//INTCONbits.T0IF=0;
return;
}
//rutina del display (entrada: dato; salida: char)
unsigned char display7s(unsigned dato)
{
unsigned char Result;
//aqui haremos cosas
switch(dato)
{
case 0: Result=0b00111111; break; //digito 0
case 1: Result=0b00000110; break; //digito 1
case 2: Result=0b01011011; break; // ;valor 2
case 3: Result=0b01001111; break; // ;valor 3
case 4: Result=0b01100110; break; // ;valor 4
case 5: Result=0b01101101; break; // ;valor 5
case 6: Result=0b01111101; break; // ;valor 6
case 7: Result=0b00000111; break; // ;valor 7
case 8: Result=0b01111111; break; // ;valor 8
case 9: Result=0b01100111; break; // ;valor 9
case 10: Result=0b01110111; break; // ;valor A
case 11: Result=0b01111100; break; // ;valor B
case 12: Result=0b00111001; break; // ;valor C
case 13: Result=0b01011110; break; // ;valor D
case 14: Result=0b01111001; break; // ;valor E
case 15: Result=0b01110001; break; // ;valor F
default: Result=0; break;
}
return Result;
}
//rutina principal
void main(void) {
//variables locales
unsigned char aux;
//configuramos el PIC
PORTA=0b00000011;
PORTB=0b00000000;
//a partir de aqui lo he hecho yo (no fiarse)
TRISA=0b00000100;
TRISB=0b00000000;
OPTION_REG=0b00000001; //otra forma: OPTION_REGbits.PS0=1
TMR0=0x05;
INTCON=0b10100000;
//loop
while(1)
{
aux=VALOR;
aux=aux&0x0F; //dejamos la parte baja del bit
PORTB=display7s(aux);
PORTAbits.RA4=1; //almacenamos en el latch el valor
PORTAbits.RA4=0;
//parte alta
aux=VALOR;
aux=aux>>4; //movemos los bits a la parte baja
aux=aux&0x0F; //dejamos la parte baja del bit
PORTB=display7s(aux);
PORTAbits.RA3=1; //almacenamos en el latch el valor
PORTAbits.RA3=0; //tambien vale RA3=0;
}
return;
}
//Fin del programa
Para un esquema de conexion, habria que conectarlo asi:
A primera vista, parece algo complicado de ver, ya que el simulador en el que lo he conectado tiene algunas limitaciones, pero basta con seguir el esquema del enunciado para ver como habria que conectarlo correctamente. Ademas, hay un pequeño detalle que hay que tener en cuenta a la hora de conectarlo y que a mi me dio muchos problemas. Para poder usar el pin RA4 como una salida, hay que conectarle una resistencia de pull-up (en este caso R2), ya que el PIC16F84 (o el PIC16F84A) no lo tiene incorporado por defecto.
¿ASSEMBLER O C?
Pues en mi opinion, la decision no es dificil. Para el 99% de los casos, lo recomendable seria usar C, ya que es mas rapido, facil y sirve para multitud de microcontroladores distintos. Sin embargo, si lo que quieres es aprovechar los recursos de un microcontrolador al 100%, no te queda mas remedio que programarlo en ensamblador, aunque esto no suele ser necesario casi nunca, siempre depende de lo que quieras hacer con el chip.
Enlaces de descarga de la documentacion y los programas:
https://drive.google.com/drive/folders/0B20kHfrc3NnpLWdHcDlza3JnQ3c?usp=sharing