Vous êtes sur la page 1sur 56

Programa 1 para realizar un Semáforo

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

;Autor: LONELY113

; http://lonely113.blogspot.com

;Programa de control de 2 semaforos

;Salidas: Puerto B (RB0-RB5)

; RB0=Verde1, RB1=Ambar1, RB2=Rojo1

; RB3=Verde2, RB4=Ambar2, RB5=Rojo2

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

include "p16f84a.inc"

list P=16f84a

__CONFIG _WDT_OFF & _XT_OSC

TIME equ 0x0C

COUNT1 equ 0x0D

COUNT2 equ 0x0E

COUNT3 equ 0x0F

org 0x00 ; Inicio de programa

bsf STATUS,5 ; Inicio configiracion E/S

clrf PORTB ; Puerto B como salida

bcf STATUS,5 ; Fin configuracion E/S

movlw 0x21 ; b'000100001'


movwf PORTB ; RB0=Verde1 y RB5=Rojo2

BEGIN: call COUNTER ; Llama a subrutina COUNTER

movlw 0x00 ; 0 segundos

subwf TIME,0

btfsc STATUS,2 ; Si TIME =0 segundos saltar a FIRST

goto FIRST

movlw 0x19 ; 25 segundos

subwf TIME,0

btfsc STATUS,2 ; Si TIME=25 segundos saltar a SECOND

goto SECOND

movlw 0x1E ; 30 segundos

subwf TIME,0

btfsc STATUS,2 ; Si TIME=30 segundos saltar a THIRD

goto THIRD

movlw 0x37 ; 55 segundos

subwf TIME,0

btfsc STATUS,2 ; Si TIME=55 segundos saltar a FOURTH

goto FOURTH

goto FINISH

FIRST: movlw 0x21 ; b'000100001'

movwf PORTB ; RB0=Verde1 y RB5=Rojo2

goto FINISH

SECOND: movlw 0x22 ; b'000100010'

movwf PORTB ; RB1=Ambar1 y RB5=Rojo2

goto FINISH

THIRD: movlw 0x0C ; b'00001100'


movwf PORTB ; RB2=Rojo1 y RB3=Verde2

goto FINISH

FOURTH: movlw 0x14 ; b'00010100'

movwf PORTB ; RB2=Rojo1 y RB4=Ambar2

goto FINISH

FINISH: goto BEGIN

;Subrutinas

COUNTER movlw 0xFA ; Subrutina para que TIME

movwf COUNT1 ; se incremente cada 1 segundo

movlw 0xC8 ; calibrado para cristal de 10 MHz

movwf COUNT2 ; modificar COUNT1, COUNT2 y COUNT3

movlw 0x12 ; para otras frecuencias

movwf COUNT3

LOOP: decfsz COUNT1,1

goto LOOP

movlw 0xFA

movwf COUNT1

decfsz COUNT2,1

goto LOOP

movlw 0xFA

movwf COUNT1

movlw 0xC8

movwf COUNT2

decfsz COUNT3,1
goto LOOP

incf TIME,1

movlw 0x3C ; 60 segundos entonces reiniciar TIME

subwf TIME,0

btfsc STATUS,2

clrf TIME

return

end ; Fin de programa


2Programa para iluminar leds secuencuencialmente
;---------------------------------------------------------

;Autor: LONELY113

; http://lonely113.blogspot.com

;Programa para iluminar leds secuencuencialmente

;La luz se desplaza de RB0 a RB7 y viceversa

;Salidas: PUERTOB

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

include "p16f84a.inc"

list P=16f84a

__CONFIG _WDT_OFF & _XT_OSC

COUNT1 equ 0x0C

COUNT2 equ 0x0D

COUNT3 equ 0x0E

TIMES equ 0x0F

org 0x00 ; Inicio de programa

bsf STATUS,5 ; Inicio de configuracion E/S

clrf PORTA

clrf PORTB ; Puerto B como salida

bcf STATUS,5 ; Fin configuracion E/S

clrf PORTB
bcf STATUS,0

bsf PORTB,0 ; PORTB=00000001

call DELAY ; Llamada a subrutina DELAY

BEGIN: movlw 0x07

movwf TIMES

LEFT: rlf PORTB,1 ; Rota 7 veces a la izquierda

call DELAY

decfsz TIMES

goto LEFT

movlw 0x07

movwf TIMES

RIGHT: rrf PORTB,1 ; Rota 7 veces a la derecha

call DELAY

decfsz TIMES

goto RIGHT

goto BEGIN ; Bucle infinito

;Subrutinas

DELAY movlw 0xFF ; Subrutina de retardo

movwf COUNT1 ; 256x256=65536 cuentas

movwf COUNT2

movlw 0x20

movwf COUNT3

LOOP: decfsz COUNT1,1 ; Decrementa COUNT1

goto LOOP ; Salta si COUNT1=0


movlw 0xFF

movwf COUNT1 ; COUNT1=FF

decfsz COUNT2,1 ; Decrementa COUNT2

goto LOOP ; Salta se COUNT2=0

movlw 0xFF

movwf COUNT1

movwf COUNT2

decfsz COUNT3,1

goto LOOP

return ; Retorno de subrutina

end ; Fin de programa


Puerto B: Enciende y apaga bits, Enciende MSB, Enciende LSB, Corrimiento
Izq.-Der.

processor 16f877

include<p16f877.inc>

;Variables para el DELAY

valor1 equ h'21'

valor2 equ h'22'

valor3 equ h'23'

;Definición de variables a utilizar para

;comparar las entradas a través del puerto A

v0 equ h'24'

v1 equ h'25'

v2 equ h'26'

v3 equ h'27'

org 0h

goto INICIO

org 05h

INICIO:
clrf PORTA ;Limpia el puerto A

bsf STATUS,RP0

bcf STATUS,RP1 ;Cambio al Banco 1

movlw h'0'

movwf TRISB ;Configura Puerto B como salida

clrf PORTB ;Limpia el Puerto B

movlw 06h ;Configura puertos A y E como digitales

movwf ADCON1

movlw 3fh

movwf TRISA ;Configura el Puerto A como entrada

bcf STATUS,RP0 ;Regresa al Banco 0

CICLO:

movlw h'0'

movwf v0

movfw PORTA ;Mueve lo que hay en PORTA a W

xorwf v0,w ;Verifica si la entrada es $00

btfsc STATUS,Z ;z=0?

goto ENCAPG ;NO, entonces v0=W

;SI, entonves v0!=W

movlw h'1'

movwf v1
movfw PORTA

xorwf v1,w ;Verifica si la entrada es $01

btfsc STATUS,Z

goto MSB

movlw h'2'

movwf v2

movfw PORTA

xorwf v2,w ;Verifica si la entrada es $02

btfsc STATUS,Z

goto LSB

movlw h'3'

movwf v3

movfw PORTA

xorwf v3,w ;Verifica si la entrada es $03

btfsc STATUS,Z

goto DERIZQ

clrf PORTB

goto CICLO

ENCAPG: ;Rutina que enciende y apaga los


movlw h'00' ;bits del puerto B

movwf PORTB

call retardo

movlw h'FF'

movwf PORTB

call retardo

goto CICLO

MSB: ;Enciende MSB

movlw h'F0'

movwf PORTB

call retardo

goto CICLO

LSB: ;Enciende LSB

movlw h'0F'

movwf PORTB

call retardo

goto CICLO

DERIZQ: ;Realiza corrimiento a la derecha y

movlw h'80' ;luego a la izquierda

movwf PORTB

call retardo
DER2:

rrf PORTB,1

call retardo

btfss PORTB,0

goto DER2

movlw h'01'

movwf PORTB

call retardo

IZQ2:

rlf PORTB,1

call retardo

btfss PORTB,7

goto IZQ2

goto CICLO

retardo

movlw 40h ;Rutina que genera un DELAY

movwf valor1

tres movlw 50h

movwf valor2

dos movlw 60h


movwf valor3

uno decfsz valor3

goto uno

decfsz valor2

goto dos

decfsz valor1

goto tres

return

end
Programa Contador de 00-99 con pic 16f877

processor 16f877

include<P16f877.inc>

;Variables para el DELAY

valor1 equ h'21'

valor2 equ h'22'

valor3 equ h'23'

;Definición de números en base al Dispaly Cátodo C.

; HEXADECIMAL SEGEMENTOS BINARIO

CERO EQU h'7E' ; ,7,6,5,4,3,2, ,: 01111110B

UNO EQU h'48' ; ,7, , ,4, , , : 01001000B

DOS EQU h'3D' ; , ,6,5,4,3, ,1: 00111101B

TRES EQU h'6D' ; ,7,6, ,4,3, ,1: 01101101B

CUATRO EQU h'4B' ; ,7, , ,4, ,2,1: 01001011B

CINCO EQU h'67' ; ,7,6, , ,3,2,1: 01100111B

SEIS EQU h'77' ; ,7,6,5, ,3,2,1: 01110111B

SIETE EQU h'4E' ; ,7, , ,4,3,2,,: 01001110B

OCHO EQU h'7F' ; ,7,6,5,4,3,2,1: 01111111B

NUEVE EQU h'6F' ; ,7,6, ,4,3,2,1: 01101111B

;Variable contador
contador equ h'24'

org 0h

goto INICIO

org 05h

INICIO:

clrf PORTB

clrf PORTD ;Limpia puertos B y D

bsf STATUS,RP0

bcf STATUS,RP1 ;Cambio al Banco 1

movlw h'0'

movwf TRISB ;Configura Puerto B como salida

movwf TRISD ;Configura Puerto C como salida

bcf STATUS,RP0 ;Regresa al Banco 0

START:

clrf contador ;Inicializa contador de decenas

clrf PORTD

LOOP:

movlw CERO ;Ciclo que muestra las unidades

movwf PORTB

call RETARDO
movlw UNO

movwf PORTB

call RETARDO

movlw DOS

movwf PORTB

call RETARDO

movlw TRES

movwf PORTB

call RETARDO

movlw CUATRO

movwf PORTB

call RETARDO

movlw CINCO

movwf PORTB

call RETARDO

movlw SEIS

movwf PORTB

call RETARDO

movlw SIETE

movwf PORTB

call RETARDO

movlw OCHO
movwf PORTB

call RETARDO

movlw NUEVE

movwf PORTB

call RETARDO

incf contador,1 ;Incrementa contador de decenas

;Verifica si contador=10

movlw h'A'

xorwf contador,w

btfsc STATUS,Z ;z=0?

goto START ;NO, entonces contador=10, reinicia.

;SI, entonces contador!=10, sigue

;el conteo

UNIDADES

movlw h'1'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=1;

goto PRINT1

movlw h'2'
xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=2;

goto PRINT2

movlw h'3'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=3;

goto PRINT3

movlw h'4'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=4;

goto PRINT4

movlw h'5'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=5;

goto PRINT5

movlw h'6'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=6;


goto PRINT6

movlw h'7'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=7;

goto PRINT7

movlw h'8'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=8;

goto PRINT8

movlw h'9'

xorwf contador,w

btfsc STATUS,Z ;Verifica si contador=9;

goto PRINT9

;Muestra Decenas en el Display

PRINT1:

movlw UNO

movwf PORTD

goto LOOP

PRINT2:
movlw DOS

movwf PORTD

goto LOOP

PRINT3:

movlw TRES

movwf PORTD

goto LOOP

PRINT4:

movlw CUATRO

movwf PORTD

goto LOOP

PRINT5:

movlw CINCO

movwf PORTD

goto LOOP

PRINT6:

movlw SEIS

movwf PORTD

goto LOOP

PRINT7:

movlw SIETE

movwf PORTD
goto LOOP

PRINT8:

movlw OCHO

movwf PORTD

goto LOOP

PRINT9:

movlw NUEVE

movwf PORTD

goto LOOP

RETARDO

movlw h'60' ;Rutina que genera un DELAY

movwf valor1

tres movlw h'50'

movwf valor2

dos movlw h'60'

movwf valor3

uno decfsz valor3

goto uno

decfsz valor2

goto dos

decfsz valor1
goto tres

return

end
3 Programa para el control de un Teclado matricial 4x4

;---------------------------------------------------------
;Autor: LONELY113
; http://lonely113.blogspot.com
;
;Programa para control de teclado matricial 4x4
;Adicionalmente muestra la tecla pulsada en un display
;Para teclado: Salida: RB0-RB3
; Entradas: RB4-RB7
;Para Display: Salidas: RB1-RB7 (7 segmentos)
; RA0 (Habilitacion catodo comun)
;---------------------------------------------------------
include "p16f84a.inc"
LIST P=16f84a

__CONFIG _WDT_OFF & _XT_OSC

KEY EQU 0x0C


DISP EQU 0x0D
COUNT EQU 0x0E

org 0x00 ; Inicio de programa


BEGIN: bsf STATUS,5; Inicio configuracion E/S
clrf PORTA ; Puerto A como salida
movlw 0xF0
movwf PORTB
bcf STATUS,5; Fin configuracion E/S
bsf PORTA,0
KEY_V: bcf STATUS,5; Fin configuracion E/S
clrf PORTB
bsf PORTB,0 ; Enviar bit 1 a la primera fila
VERIF1: btfss PORTB,4 ; Verificar tecla pulsada en columna 1
goto VERIF2
movlw 0x01 ; Si se pulsa tecla KEY=KEY+1
addwf KEY,1
goto CON2 ; Terminar verificacion
VERIF2: btfss PORTB,5 ; Verificar tecla pulsada en columna 2
goto VERIF3
movlw 0x02 ; Si se pulsa tecla KEY=KEY+2
addwf KEY,1
goto CON2 ; Terminar verificacion
VERIF3: btfss PORTB,6 ; Verificar tecla pulsada en columna 3
goto VERIF4
movlw 0x03 ; Si se pulsa tecla KEY=KEY+3
addwf KEY,1
goto CON2 ; Terminar verificacion
VERIF4: btfss PORTB,7 ; Verificar tecla pulsada en columna 4
goto CON1
movlw 0x04 ; Si se pulsa tecla KEY=KEY+4
addwf KEY,1
goto CON2 ; Terminar verificacion
CON1: incf COUNT,1 ; COUNT almacena filas ya verificadas
movlw 0x04
subwf COUNT,0
btfss STATUS,2
goto CON3
clrf KEY ; Si COUNT=4 (todas las filas verificadas)
clrf COUNT ; borrar COUNT y BORRAR KEY
goto DISPL
CON3: rlf PORTB ; Envia bit 1 a la siguiente fila
movlw 0x04 ; Si no se detecta tecla pulsada en una fila
addwf KEY,1 ; KEY=KEY+4
goto VERIF1
CON2: movf KEY,0 ; KEY almacena la tecla pulsada (1-16 decimal)
movwf DISP
clrf KEY
clrf COUNT
DISPL: bsf STATUS,5; Inicio configuracion E/S
clrf PORTB ; PortB como salida
bcf STATUS,5; Fin configuracion E/S
movf DISP,0
call CONV
movwf PORTB ; Mostrar tecla pulsada en display
bcf PORTA,0 ; Habilitar display
nop
bsf PORTA,0 ; Deshabilitar display
bsf STATUS,5; Inicio configuracion E/S
movlw 0xF0 ; RB0-RB3 salidas y RB4-RB7 entradas
movwf PORTB ; Fin configuracion E/S
goto KEY_V

;Subroutines
CONV: addwf PCL,1 ;Convierte hexadecimal a 7 segmentos
retlw 0x00 ;" "
retlw 0x0C ;1 tecla 1
retlw 0xB6 ;2 tecla 2
retlw 0x9E ;3 tecla 3
retlw 0xE2 ;F tecla 4
retlw 0xCC ;4 tecla 5
retlw 0xDA ;5 tecla 6
retlw 0xFA ;6 tecla 7
retlw 0xF2 ;E tecla 8
retlw 0x0E ;7 tecla 9
retlw 0xFE ;8 tecla 10
retlw 0xDE ;9 tecla 11
retlw 0xBC ;D tecla 12
retlw 0xEE ;A tecla 13
retlw 0x7E ;0 tecla 14
retlw 0xF8 ;B tecla 15
retlw 0x72 ;C tecla 16

end ; Fin de programa


4 Programa para control de LCD 2x16

;----------------------------------------------------------
;Autor: LONELY113
; http://lonely113.blogspot.com
;
;Programa para control de LCD con controlador Hitachi 44780
;2x16 lineas
;Configuracion de pines:
;RA0: RS (Pin 4)
;RA1: R/W (Pin 5)
;RA2: E (Pin 6)
;RB0-RB7: D0-D7 (Pines 7-14)
;----------------------------------------------------------
include "p16f84a.inc"
LIST P=16f84a

__CONFIG _WDT_OFF & _XT_OSC


COUNT1 equ 0x0C
COUNT2 equ 0x0D
CURSOR equ 0x0E

org 0x00 ; Inicio de Programa


BEGIN: bsf STATUS,5; Inicio configuracion E/S
clrf PORTB ; Puerto B como salida
clrf PORTA ; Puerto A como salida
bcf STATUS,5; Fin configuracion E/S
clrf PORTA
call DELAY
START: call INI ; Inicializacion de LCD
movlw 0x01 ; b'00000001' Clear display
call REG
movlw 0x06 ; b'00000110' Incrementa cursor I/D=1
call REG ; y visualizacion modo normal S=0
movlw 0x0C ; b'00001100' Display ON D=1
call REG ; Cursor OFF C=0 y Parpadeo OFF B=0
movlw 0x80 ; Direccion inicio de almacenamiento
call REG ; de datos (Linea 1 comienza en 80h)
clrf CURSOR ; CURSOR almacena #caracter a enviar
ROW1: movf CURSOR,0
call CONV
call DAT ; Enviar a memoria de datos
incf CURSOR,1
movlw 0x09
subwf CURSOR,0; Enviar datos hasta que CURSOR=9
btfss STATUS,2
goto ROW1
movlw 0xC0 ; Direccion inicio de almacenamiento
call REG ; de datos (Linea 2 comienza en C0h)
ROW2: movf CURSOR,0
call CONV
call DAT ; Enviar a memoria de datos
incf CURSOR,1
movlw 0x15
subwf CURSOR,0; Enviar datos hasta que CURSOR=15
btfss STATUS,2
goto ROW2
ILOOP: nop ; Bucle infinito cuando se termine de
goto ILOOP ; enviar todos los datos
;Subrutinas

;BUSY: Subrutina para no enviar datos al LCD cuando


; esta ocupado
BUSY bsf PORTA,1 ; R/W=1 (Lectura de LCD)
bsf STATUS,5
movlw 0xFF
movwf PORTB ; RB7 como entrada (BF:Busy Flag)
bcf STATUS,5
bsf PORTA,2 ; E=1 (Habilitar LCD)
nop
LCD_BU: btfsc PORTB,7 ; Verificar si LCD esta ocupado
goto LCD_BU ; Bucle mientras BF=1
bcf PORTA,2 ; E=0 (Deshabilitar LCD)
bsf STATUS,5
clrf PORTB ; Puerto B como salida
bcf STATUS,5
bcf PORTA,1 ; R/W=0 (Escritura de LCD)
return

;Subrutina para enviar datos a Registro de control


REG bcf PORTA,0 ; Seleccion de reg. de control
movwf PORTB ; Preparar envio de datos
call BUSY ; Verificar si LCD esta ocupado
bsf PORTA,2 ; E=1 (Habilitar LCD)
nop ; Almacena dato en reg. control
bcf PORTA,2 ; E=0 (Deshabilitar LCD)
return

;Subrutina para enviar datos a memoria de datos


DAT bcf PORTA,0 ; Seleccion de reg. de control
movwf PORTB ; Preparar envio de datos
call BUSY ; Verificar si LCD esta ocupado
bsf PORTA,0 ; Seleccion de reg. de datos
bsf PORTA,2 ; E=1 (Habilitar LCD)
nop ; Almacena dato en memoria
bcf PORTA,2 ; E=0 (Deshabilitar LCD)
return

;Subrutina de inicializacion de LCD


INI movlw 0x38 ; b'00111000'
call REG ; DL=1, N=1, F=0
call DELAY ; linea de 8 bits, 2 lineas
return ; caracter 5x7 puntos

;Subrutina de retardo para que LCD complete operaciones


DELAY movlw 0xFF
movwf COUNT2
clrf COUNT1
LOOP: decfsz COUNT1,1
goto LOOP
decfsz COUNT2,1
goto LOOP
return

;Subrutina que devuelve en W el codigo ascii de caracter


;a enviar a LCD
CONV addwf PCL,1
retlw 'l'
retlw 'o'
retlw 'n'
retlw 'e'
retlw 'l'
retlw 'y'
retlw '1'
retlw '1'
retlw '3'
retlw 'b'
retlw 'l'
retlw 'o'
retlw 'g'
retlw 's'
retlw 'p'
retlw 'o'
retlw 't'
retlw '.'
retlw 'c'
retlw 'o'
retlw 'm'
return

end ;Fin de programa


Teclado 4x4 para pic 16f877a
processor 16f877

include<P16f877.inc>

;Declaración de VARIABLES

;Guarda el número de tecla pulsada

numTecla equ h'30'

;Para el DELAY (Estabilización de la Señal ENABLE-LCD)

cont1 equ 0x31


cont2 equ 0x32

;Contador de caractéres

caracter equ h'33'

org 0h ;Vector de RESET

goto INICIO ;Etiqueta de inico

org 05h ;Inicio del programa

INICIO:

clrf PORTB ; Limpia PORTB

clrf PORTC ; Limpia PORTC

clrf PORTD ; Limpia PORTD

bsf STATUS,RP0 ; Selecciona banco 1

movlw 0xF0 ; PortB0-3 Salidas

movwf TRISB ; PortB4-7 Entradas

clrf TRISC ; PortC0-1 Salidas

clrf TRISD ; PortD0-7 Salidas

bcf OPTION_REG,7 ; Habilita Resistencias de

; polarización en entradas

bcf STATUS,RP0 ; Selecciona banco 0

;Inicio

START:

clrf caracter

call INICIA_LCD ;Configura el LCD


goto NEW_SCAN ;Comienza el SCAN del TECLADO

;Rutina para inicializar el lcd

INICIA_LCD:

bcf PORTC,0 ; RS=0 MODO INSTRUCCION

movlw 0x01 ; 0x01 limpia la pantalla en el LCD

movwf PORTD

call COMANDO ; Se da de alta el comando

movlw 0x0C ; Selecciona la primera línea

movwf PORTD

call COMANDO ; Se da de alta el comando

movlw 0x3C ; Se configura el cursor

movwf PORTD

call COMANDO ; Se da de alta el comando

bsf PORTC, 0 ; Rs=1 MODO DATO

return

;Rutina para enviar un dato

ENVIA:

bsf PORTC, 0 ; RS=1 MODO DATO

call COMANDO ; Se da de alta el comando

return

;Subrutina para enviar INST. ó DATOS

COMANDO:
bsf PORTC, 1 ; Pone la señal ENABLE en 1

call DELAY ; Espera estabilizar la señal

call DELAY ; Espera estabilizar la señal

bcf PORTC, 1 ; ENABLE=0

call DELAY ; Espera estabilizar la señal

return

;Configuración Lineal 2 LCD

LINEA2:

bcf PORTC,0 ; RS=0 MODO INSTRUCCION

movlw 0xC0 ; Selecciona línea 2 pantalla en el LCD

movwf PORTD

call COMANDO ; Se da de alta el comando

goto NEW_SCAN

; Rutina de retardo

; Para estabilizar la señal de ENABLE

DELAY:

movlw 0xFF

movwf cont2

loop1:

movlw 0xFF

movwf cont1

loop2:

decfsz cont1,1
goto loop2

decfsz cont2,1

goto loop1

return

;Escaneo del teclado

NEW_SCAN:

clrf numTecla ; Borra el contenido de numTecla

incf numTecla,1 ; Inicializa numTecla

movlw b'00001110' ; Pone a 0 la primera Fila ( PB0 )

movwf PORTB

Nop ; Espera estabilizar la señal

;Rutina que verifíca el estado de las columnas

CHK_COL:

;Verifica si se ha presionado alguna tecla

btfss PORTB,4 ; Columna 1=0?

goto TECLA_ON ; Sale si se ha pulsado una tecla

incf numTecla,1 ; Incrementa número de tecla

btfss PORTB,5 ; Columna 2=0?

goto TECLA_ON ; Sale si se ha pulsado una tecla

incf numTecla,1 ; Incrementa número de tecla

btfss PORTB,6 ; Columna 3=0?

goto TECLA_ON ; Sale si se ha pulsado una tecla


incf numTecla,1 ; Incrementa número de tecla

btfss PORTB,7 ; Columna 4=0?

goto TECLA_ON ; Sale si se ha pulsado una tecla

incf numTecla,1 ; Incrementa número de tecla

;Verifica si se ha recorrido todo el teclado

movlw d'17' ; Número total de teclas + 1

xorwf numTecla,w ; Realiza d'17' XOR numTecla

btfsc STATUS,Z ; Verifica el estado de Z

goto NEW_SCAN ; Z=1?, Son iguales (full Scan)

; Z=0?, Son diferentes,

NEXT_COL:

bsf STATUS,C ; Enciende el carry para poner en "1" la FILA

; recorrida

rlf PORTB,1 ; Realiza corrimiento a la izquierda, pone a

; cero la siguiente FILA

goto CHK_COL ; Escanea la sig. COLUMNA

;Rutina que procesa la tecla capturada

TECLA_ON:

;Rutinas que esperan a que se deje de presionar la tecla

;Esto para evitar ECO

Espera1

btfss PORTB,4 ;Si no se suelta la tecla de la COL 1

goto Espera1 ;vuelve a esperar.


Espera2

btfss PORTB,5 ;Si no se suelta la tecla de la COL 2

goto Espera2 ;vuelve a esperar.

Espera3

btfss PORTB,6 ;Si no se suelta la tecla de la COL 3

goto Espera3 ;vuelve a esperar.

Espera4

btfss PORTB,7 ;Si no se suelta la tecla de la COL 4

goto Espera4 ;vuelve a esperar.

;Una vez que dejó de presionar la tecla

movf numTecla,w ; Pone en W el valor de numTecla

call CONV_TECLA ; Llama a la rutina de conversión

movwf PORTD ; Manda la conversión al puerto D

call ENVIA ; Manda Datos al LCD

incf caracter,1 ; Incrementa contador de caracteres

;Verifica si se ha llenado la línea 1 de caracteres

movlw d'16' ; Nómero de caracteres

xorwf caracter,w ; Realiza d'16' XOR caracter

btfsc STATUS,Z ; Verifica el estado de Z

goto LINEA2 ; z=1, Línea 1 llena

;Verifica si se ha llenado la línea 2 de caracteres

movlw d'32' ; N˙mero de teclas

xorwf caracter,w ; Realiza d'32' XOR caracter

btfsc STATUS,Z ; Verifica el estado de Z


goto START ; z=1, Línea 2 llena, reinicia

goto NEW_SCAN ; Realiza nuevo scan

;Rutina de conversión que retorna el valor en ASCII de

;numTecla en W

CONV_TECLA

addwf PCL,1

nop ;Linea 0 (no se utiliza)

retlw '1' ;Tecla #1=1

retlw '2' ;Tecla #2=2

retlw '3' ;Tecla #3=3

retlw 'A' ;Tecla #4=A

retlw '4' ;Tecla #5=4

retlw '5' ;Tecla #6=5

retlw '6' ;Tecla #7=6

retlw 'B' ;Tecla #8=B

retlw '7' ;Tecla #9=7

retlw '8' ;Tecla #10=8

retlw '9' ;Tecla #11=9

retlw 'C' ;Tecla #12=C

retlw 'F' ;Tecla #13=F

retlw '0' ;Tecla #14=0

retlw 'E' ;Tecla #15=E

retlw 'D' ;Tecla #16=D

end
PROGRAMA PARA CONTROLAR LCD CON PIC PROCESSOR 16F877
include <P16F877.INC>

;Variables para DELAY

val1 equ 0x30

val2 equ 0x31

org 0 ;Vector de RESET


goto INICIO

org 5 ;Inicio del Programa

;Configuración de puertos

INICIO:

clrf PORTB ;Limpia PORTB

clrf PORTD ;Limpia PORTD

bsf STATUS, RP0

bcf STATUS, RP1 ;Selecciona el banco 1

clrf TRISB ;Configura PORTB como salida

clrf TRISD ;Configura PORTD como salida

bcf STATUS,RP0 ;Regresa al banco 0

START_LCD:

call INICIA_LCD ;Configura el LCD

call M1 ;Muestra Mensaje

call LINEA2 ;Configura linea 2

call M2 ;Muestra Mensaje

goto START_LCD

;Mensaje a enviar

M1:

movlw 'H' ;Mueve 'H' a W

movwf PORTB ;Mueve lo que hay en W a PORTB

call ENVIA ;Imprime en LCD

movlw 'e'
movwf PORTB

call ENVIA

movlw 'l'

movwf PORTB

call ENVIA

movlw 'l'

movwf PORTB

call ENVIA

movlw 'o'

movwf PORTB

call ENVIA

movlw ' '

movwf PORTB

call ENVIA

movlw 'W'

movwf PORTB

call ENVIA

movlw 'o'

movwf PORTB

call ENVIA

movlw 'r'

movwf PORTB

call ENVIA

movlw 'l'

movwf PORTB

call ENVIA
movlw 'd'

movwf PORTB

call ENVIA

movlw '!'

movwf PORTB

call ENVIA

return

M2:

movlw 'I' ;Mueve 'I' a W

movwf PORTB ;Mueve lo que hay en W a PORTB

call ENVIA ;Imprime en LCD

movlw 'm'

movwf PORTB

call ENVIA

movlw ' '

movwf PORTB

call ENVIA

movlw 'O'

movwf PORTB

call ENVIA

movlw 'p'

movwf PORTB

call ENVIA

movlw 'e'

movwf PORTB

call ENVIA
movlw 'n'

movwf PORTB

call ENVIA

movlw 'B'

movwf PORTB

call ENVIA

movlw 'o'

movwf PORTB

call ENVIA

movlw 'x'

movwf PORTB

call ENVIA

movlw 'e'

movwf PORTB

call ENVIA

movlw 'r'

movwf PORTB

call ENVIA

return

;Subrutina para inicializar el lcd

INICIA_LCD:

bcf PORTD,0 ; RS=0 MODO INSTRUCCION

movlw 0x01 ; El comando 0x01 limpia la pantalla en el LCD

movwf PORTB

call COMANDO ; Se da de alta el comando


movlw 0x0C ; Selecciona la primera línea

movwf PORTB

call COMANDO ; Se da de alta el comando

movlw 0x3C ; Se configura el cursor

movwf PORTB

call COMANDO ; Se da de alta el comando

bsf PORTD, 0 ; Rs=1 MODO DATO

return

;Subrutina para enviar comandos

COMANDO:

bsf PORTD,1 ; Pone ENABLE en 1

call DELAY ; Tiempo de espera

call DELAY

bcf PORTD, 1 ; ENABLE=0

call DELAY

return

;Subrutina para enviar un dato

ENVIA:

bsf PORTD,0 ; RS=1 MODO DATO

call COMANDO ; Se da de alta el comando

return

;Configuración Líneal 2 LCD

LINEA2:
bcf PORTD, 0 ; RS=0 MODO INSTRUCCION

movlw 0xc0 ; Selecciona línea 2 en el LCD

movwf PORTB

call COMANDO ; Se da de alta el comando

return

; Subrutina de retardo

DELAY:

movlw 0xFF

movwf val2

ciclo:

movlw 0xFF

movwf val1

ciclo2:

decfsz val1,1

goto ciclo2

decfsz val2,1

goto ciclo

return

END
Programa con sensor de temperatura LM 35 y LCD

con pic 16f877


processor 16f877

include<p16f877.inc>

;Variable para el DELAY del ADC

val equ h'20'


;Variables para el DELAY del ENABLE LCD

val2 equ 0x30

val1 equ 0x31

;Variables para separar el resultado de ADC

; en valor BCD

Unidades equ 0x32

Decenas equ 0x33

Centenas equ 0x34

Resto equ 0x35

org 0h

goto INICIO

org 05h

INICIO:

clrf PORTA ;Limpia el puerto A

clrf PORTB ;Limpia el puerto B

clrf PORTC ;Limpia el puerto C

clrf PORTD ;Limpia el puerto D

bsf STATUS,RP0

bcf STATUS,RP1 ;Cambio al banco 1

;Configuración de puertos C-D para el LCD

clrf TRISC ;Configura PORTC como salida

clrf TRISD ;Configura PORTD como salida


;Configuración del puerto A para ADC

movlw 00h

movwf ADCON1 ;Configura puerto A y E como analógicos

movlw 3fh

movwf TRISA ;Configura el puerto A como entrada

movlw h'0'

;Configuración del puerto B para mostrar el resultado ADC

movwf TRISB ;Configura puerto B como salida

bcf STATUS,RP0 ;Regresa al banco 0

;Inicio del programa

START

call START_LCD ;Inicializa LCD

goto START_ADC ;Comienza la lectura del Conv. A/D

;Inicia LCD

START_LCD:

bcf PORTC,0 ; RS=0 MODO INSTRUCCION

movlw 0x01 ; 0x01 limpia la pantalla en el LCD

movwf PORTD

call COMANDO ; Se da de alta el comando

movlw 0x0C ; Selecciona la primera línea

movwf PORTD

call COMANDO ; Se da de alta el comando


movlw 0x3C ; Se configura el cursor

movwf PORTD

call COMANDO ; Se da de alta el comando

bsf PORTC, 0 ; Rs=1 MODO DATO

return

;Rutina para enviar un dato

ENVIA:

bsf PORTC, 0 ; RS=1 MODO DATO

call COMANDO ; Se da de alta el comando

return

;Rutina para enviar comandos

COMANDO:

bsf PORTC, 1 ; Pone la señal ENABLE en 1

call DELAY2 ; Tiempo de espera

call DELAY2

bcf PORTC, 1 ; ENABLE=0

call DELAY2

return

;Rutina para limpar pantalla LCD

ERASE_LCD

bcf PORTC,0 ; RS=0 MODO INSTRUCCION

movlw 0x01 ; 0x01 limpia la pantalla en el LCD

movwf PORTD
call COMANDO ; Se da de alta el comando

bsf PORTC, 0 ; Rs=1 MODO DATO

return

;Configuración Convertidor A/D

START_ADC

movlw b'11000001' ;Configuración ADCON0

movwf ADCON0 ;ADCS1=1 ADCS0=1 CHS2=0 CHS1=0

;CHS0=0 GO/DONE=0 - ADON=1

CICLO: bsf ADCON0,2 ;Conversión en progreso GO=1

call DELAY1 ;Espera que termine la conversión

ESPERA btfsc ADCON0,2 ;Pregunta por DONE=0?(Terminó conversión)

goto ESPERA ;No, vuelve a preguntar

movf ADRESH,0 ;Si

movwf PORTB ;Muestra el resultado en PORTB

;Rutina que muestra temperatura

PRINT_TEMP

call ERASE_LCD ;Limpia LCD

movlw 'T'

movwf PORTD

call ENVIA

movlw '='

movwf PORTD

call ENVIA
call READ_TEMP ;Llamada a rutina que obtine el

;valor de la temperatura a partir

;del resultado del Conv a/D

movf Centenas,W ;Imprime el dígito de las centenas

movwf PORTD

call ENVIA

movf Decenas,W ;Imprime el dígito de las decenas

movwf PORTD

call ENVIA

movf Unidades,W ;Imprime el dígito de las unidades

movwf PORTD

call ENVIA

movlw ' '

movwf PORTD

call ENVIA

movlw h'DF' ;Imprime el simbolo "°"

movwf PORTD

call ENVIA

movlw 'C'

movwf PORTD

call ENVIA

goto CICLO ;Repite el ciclo de lectura ADC


;Rutina que obtine el valor de la temperatura

;a partir del resultado del Conv a/D

READ_TEMP:

clrf Centenas

clrf Decenas

clrf Unidades

movf ADRESH,W

addwf ADRESH,W ;Dupilca el valor de ADRESH para

; obtener un valor de temperatura real aprox

movwf Resto ;Guarda el valor de ADRESH en Resto

; Comienza el proceso de obtención de valores BCD

;para Centenas, Decenas y unidades atraves de restas

;sucesivas.

CENTENAS1

movlw d'100' ;W=d'100'

subwf Resto,W ;Resto - d'100' (W)

btfss STATUS,C ;Resto menor que d'100'?

goto DECENAS1 ;SI

movwf Resto ;NO, Salva el resto

incf Centenas,1 ;Incrementa el contador de centenas BCD

goto CENTENAS1 ;Realiza otra resta

DECENAS1

movlw d'10' ;W=d'10'

subwf Resto,W ;Resto - d'10' (W)


btfss STATUS,C ;Resto menor que d'10'?

goto UNIDADES1 ;Si

movwf Resto ;No, Salva el resto

incf Decenas,1 ;Incrementa el contador de centenas BCD

goto DECENAS1 ;Realiza otra resta

UNIDADES1

movf Resto,W ;El resto son la Unidades BCD

movwf Unidades

;clrf Resto

;Rutina que obtiene el equivalente en ASCII

OBTEN_ASCII

movlw h'30'

iorwf Unidades,f

iorwf Decenas,f

iorwf Centenas,f

return

;Rutina que genera un Delay de 20 microSeg aprox.

;para el Conv. A/D

DELAY1:

movlw h'30'

movwf val

Loop decfsz val,1

goto Loop

return
;Subrutina de retardo para ENABLE_LCD

DELAY2:

movlw 0xFF

movwf val1

Loop1:

movlw 0xFF

movwf val2

Loop2:

decfsz val2,1

goto Loop2

decfsz val1,1

goto Loop1

return

end
hola a todos soy nuevo en el foro, pero me parese grandioso todo esto, nota
un nivel alto a nivel de usuario, espero poder aportar algun cosita que sepa y
tengan dudas como tambien poder solisitar su ayuda en mas de una vez.
bueno estoy aqui por que e echo un pequeño codigo en CCS C para el pic
16f877a donde manejo un teclado matrisial 4x4, pero el punto es que me
quedo muy robusto y no se como hacer que quede mas presentable y que no
tenga que consumir tanto tiempo en leer lineas, si me pudieran ayudar a
mejorarlo seria de gran ayuda. por otra parte no puedo ocupar el puerto A por
que lo tengo configurado para otras cosas, el B lo tengo para el manejo de una
LCD 20x4 y parte del puerto C estoy ocupando los 2 CCP por ende me esta
quedando solo el puerto D libre y el C en parte, bueno les dejo el para ver si
me pueden echar una manito. antemano gracias.

#include <16F877a.h>
#device adc=10
#FUSES NOWDT, HS, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay (clock=20000000) //Fosc=20Mhz
#define use_portb_lcd TRUE //definir salida del puerto B para la lcd
#include<lcd.c> //libreria manejo lcd
#use standard_io(D)

int i,j,x;
char Teclas[4][4]={{'1','2','3','A'}
{'4','5','6','B'}
{'7','8','9','C'}
{'D','0','E','F'}};
void main(){
lcd_init(); //inicializa lcd

while(TRUE){
i++;
switch( i )
{
case 1:
output_high(PIN_D4);
output_high(PIN_D5);
output_high(PIN_D6);
output_low(PIN_D7);

break;
case 2:
output_high(PIN_D4);
output_high(PIN_D5);
output_low(PIN_D6);
output_high(PIN_D7);

break;
case 3:
output_high(PIN_D4);
output_low(PIN_D5);
output_high(PIN_D6);
output_high(PIN_D7);

break;
case 4:
output_low(PIN_D4);
output_high(PIN_D5);
output_high(PIN_D6);
output_high(PIN_D7);

break;
case 5:
break;
default:
}
if(i==5){i=0;}
if(!input(PIN_D0)){j=0;x=i;}
if(!input(PIN_D1)){j=1;x=i;}
if(!input(PIN_D2)){j=2;x=i;}
if(!input(PIN_D3)){j=3;x=i;}
printf(lcd_putc,"tecla:%c",Teclas[j][x]); //...presentacion
lcd_gotoxy(1,1);
}}

No creo que sea necesario usar un mismo puerto para los 2. Yo cambiaría el
LCD al puerto D, y aprovecharía la interrupción por cambio de estado en RB4-
RB7 para detectar la pulsación de alguna tecla.

#use fast_io(b)

char Teclas[17]={'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'D','0','E','F',' '};

char Tecla;

void main(){
set_tris_b(0xF0);
output_b(0x00);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

#int_RB
void RB_isr(void)
{
Tecla=TestTeclado(); //Testea la Tecla Pulsada.-
printf("Tecla=%c",Tecla);
output_b(0x00); // Se puede usar interrupción por RB4-RB7, y con esto
queda
// en espera de una proxima interrupcion.-
}

int TestTeclado(void){
int i,j,Filas;
Filas=0x0E; //xxxx1110.
output_b(Filas);
i=0;
for(j=0;j<4;j++){
if(input(PIN_B4)==0){break;}
i++;
if(input(PIN_B5)==0){break;}
i++;
if(input(PIN_B6)==0){break;}
i++;
if(input(PIN_B7)==0){break;}
i++;
//rotate_left(&Filas,1);
shift_left(&Filas,1,1);
output_b(Filas); //Trasladamos el 0 a siguiente Pin.
}
return(Teclas[i]);