Infrarrojo PIC12F629

Hola compañeros, estoy empezando a programar el pequeñin PIC 12F629 para que reciba una señal infraroja de un Telemando implemente el protocolo RC5 de Philips, por lo tanto el pic recibirá secuencias de tipo RC5.como recptor IR uso el TSOP1736 cuya salida va conectada a un puerto de entrada del PIC 12F629. El pic tiene que tener 3 puertos como salidas, uno para mandar la suma de los 5 comandos recibidos por el puerto de entrada en manera serie (15 bits ) para meter a la entrada de un PLL cuya frecuencia del PLL va de 512Khz a 32000Khz para ello como se puede ver en la hoja de características del PLL SAA1057 pag. 6 se usa el Data word A para seleccionar la frecuencia que será lo unico que hay que hacer en el PLL además de meterle la señal de reloj y la de enable desde el PIC. Es decir un puerto de salida del pic hará de enable se pondrá a '1' antes de la la trx al PLL y otro puerto sacará una señal de reloj para que en cada flanco de subida del reloj que le metamos al PLL tiene que estar el dato previamente cargado. Por lo tanto: El PIC recibirá 5 comandos del telemando. Primero uno, después otro ... hasta 5 que serán los cinco comandos que indicarán la frecuencia que se le pasa al PLL. Por ejemplo. Si pulso el boton 2, después el 1, después el 0, otro 0 y otro 0 quiere decir que tenemos que sacar por el puerto de salida para el PLL el valor en binario de 21000KHz o lo que es lo mismo 21MHz. Si por ejemplo metenos: 0, 0, 8, 0, 0 = 800Khz. Así mismo tiene que haber una tecla del telemando por ejemplo Volumen + y Volumen - que se usarán para lo sigueinte: Volumen + se pulsará siempre después de recibir en el PIC los 5 comandos y quiere decir que se puede transmitir el valor al PLL. Volumen - se podrá utilizar en cualquier momento para indicar "reset" y ponerse a la espera del primer comando. Importante es controlar el Toogle del protocolo RC5, el bit de toggle se utiliza para saber si se sigue pulsando el mismo botón o se pulsa otro botón o el mismo que se tenía pulsado pero previamente se soltó (me lío un poco no :), es decir es por si pulsamos la tecla 2 por ejemplo y sin darnos cuenta se transmiten dos '2' y eso no puede ser).

El valor del "Address" del protocolo RC5 no se tiene en cuenta, ya que no lo vamos a utilizar. Por lo tanto yo lo que hago es tener en cuenta los dos primeros bits que son de control, el tercero que es el toggle y después creo un retardo para empezar a muestrear el primer bit del comando del "bit 9 -bit 14". Esto se puede ver en un trama de RC5.

Os muestro el código que tengo hecho por si le sirve de ayuda a a alguien y por si hay quién sepa un poquito de esto y me pueda ayudar.

;**********************************************
;**********************************************
;** Realización de un receptor de IR **
;** con un PIC 12F629 de Microchip **
;** **
;**********************************************
;** Filename: IR.asm 2010 **
;** Date: --------- **
;** ** *
;**
;**********************************************
;**********************************************

list p=12F629 ; Directiva para definir el procesador
#include <p12F629.INC> ; Registros especificas del procesador

__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON &_INTRC_OSC_NOCLKOUT & _MCLRE_OFF

; _MCLRE_ON: Reset externo DESACTIVADO.
; _CP_OFF: Protección del código DESACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _IntRC_OSC: Oscilador interno de 4MHz.(Las instrucciones de programa son procesadas a 1MHz = 1Microseg por instrucción)

;DEFINICIÓN DE VARIABLES
;3 bits control
;5 bits dirección
;6 bits comando

;Frecuencia introducida en KHz:
uni_KHz EQU 0x20
dec_KHz EQU 0x21
cen_KHz EQU 0x22
uni_MHz EQU 0x23
dec_MHz EQU 0x24
Rotaciones EQU 0x25
ENTER EQU 0x26 ;Variable pulsador ENTER
BORRAR EQU 0x27 ;Variable pulsador "borrado"
Delay0 EQU 0x28
Delay1 EQU 0x29
Delay2 EQU 0x2A
Contador EQU 0x2B ;Para cojer los 6 bits del comando
Toggle EQU 0x2C
Temp EQU 0x2D

;********** Inicialización del microcontrolador y variables **********
; I/O: GP3 como entrada y GP0, GP1 y GP2

org 0x000
goto inicio
org 0x005

inicio
bcf STATUS,RP0 ;Nos aseguramos de estar en banco 0
clrf GPIO
movlw 07h ;111
movwf CMCON ;GP0/1/2 para I/O
bsf STATUS,RP0 ;cambiamos a banco 1

bsf STATUS,RP0
call 0x3FF ;Leer el valor de calibracion
movwf OSCCAL ;mover el valor al registro de calibracion

movlw B'00001000' ;Configuramos GP0, GP1, GP2, GP4 y GP5 como salidas '1' y GP3 como "entrada"
movwf TRISIO

bcf STATUS,RP0

movlw B'00110110' ;Es el valor del comando de la tecla 'STOP' para indicar que queremos borrar
movwf BORRAR ;Cargamos el valor en el registro BORRAR
movlw B'00110111' ;Es el valor del comando de la tecla 'RECORDING' para indicar que queremos transferir
movwf ENTER ;la freq al PLL
clrf Temp
clrf GPIO ;Limpiamos los puertos I/O

;********** Fin de la Inicialización *********************************

;El primer boton que utilizamos del telemando se utilizará para almacenar
;el primer valor dl Toggle y poder controlar posteriormente si se dejo de
;pulsar un botón o si "sigue pulsado" el cual se tendrá en cuenta ua sola vez.

LEER_Toggle
btfsc GPIO,3 ;Espera el primer dato de control, si es '0' salta una instrucción
goto LEER_Toggle ;Sino sigue esperando el primer dato de control
call DELAY_1_4 ;Retraso de 1/4 de bit para muestrear bien el bit __
btfsc GPIO,3 ;Para comprobar si primer start bit es '1' --> __|
goto LEER_Toggle
call DELAY_1_2 ;Esperamos por medio bit para comprobar si ahora está a '1'
btfss GPIO,3 ;Si está a '1'-> ok primer bit de control miramos ahora si
goto LEER_Toggle ;hay un '0' despues de este uno para seguir mirando el 2º
call DELAY_1_2 ;bit de control
btfsc GPIO,3 ;Si es cero esperamos otro 1/2 periodo para ver si se pone a '1'
goto LEER_Toggle
call DELAY_1_2 ;Estoy en la cima del 2º bit de control (si es '1'--> primeros 2 bits ok)
btfss GPIO,3
goto LEER_Toggle
call DELAY_1_2 ;Ahora comprobamos el valor del Toggle, para poder controlar los rebotes
btfss GPIO,3
goto MAIN ;Vamos al MAIN y el Toggle sigue con su valor de Inicio B'00000000'
bsf Toggle,0


;Ahora comienza nuestro MAIN
MAIN
call LEER_Control ;(1)
call DELAY_6 ;(2) esperamo 6 períodos para ponernos justo en el bit MSB del comando
movlw D'6' ;ya que el código de Dirección no nos interesa
movwf Contador ;Cargamos el contador con '6' para leer los 6 bits del comando
bcf STATUS,C ;Pone a '0' el biestable 'C' del registro de estado para usar con el RLF
clrf uni_KHz ;Borramos los registros donde se almacena la frecuencia para el PLL
clrf dec_KHz
clrf cen_KHz
clrf uni_MHz
clrf dec_MHz
clrf Temp
call LEER_ComandoDecMHz
call LEER_Control
call DELAY_6
movlw D'6'
movwf Contador
bcf STATUS,C
call LEER_ComandoUniMHz
call LEER_Control
call DELAY_6
movlw D'6'
movwf Contador
bcf STATUS,C
call LEER_ComandoCenKHz
call LEER_Control
call DELAY_6
movlw D'6'
movwf Contador
bcf STATUS,C
call LEER_ComandoDecKHz
call LEER_Control
call DELAY_6
movlw D'6'
movwf Contador
bcf STATUS,C
call LEER_ComandoUniKHz
call LEER_Control
call DELAY_6
movlw D'6'
movwf Contador
bcf STATUS,C
call LEER_ComandoENTER

LEER_Control ;(1)
btfsc GPIO,3 ;Espera el primer dato de control, si es '0' salta una instrucción
goto LEER_Control ;Sino sigue esperando el primer dato de control
call DELAY_1_4 ;Retraso de 1/4 de bit para muestrear bien el bit __
btfsc GPIO,3 ;Para comprobar si primer start bit es '1' --> __|
goto LEER_Control
call DELAY_1_2 ;Esperamos por medio bit para comprobar si ahora está a '1'
btfss GPIO,3 ;Si está a '1'-> ok primer bit de control miramos ahora si
goto LEER_Control ;hay un '0' despues de este uno para seguir mirando el 2º
call DELAY_1_2 ;bit de control
btfsc GPIO,3 ;Si es cero esperamos otro 1/2 periodo para ver si se pone a '1'
goto LEER_Control
call DELAY_1_2 ;Estoy en la cima del 2º bit de control (si es '1'--> primeros 2 bits ok)
btfss GPIO,3
goto LEER_Control
call DELAY_1_2 ;Ahora comprobamos el valor del Toggle, para poder controlar los rebotes
btfss GPIO,3 ;Miramos el valor del Toggle actual, para saber si sigue pulsado el mismo botón o no
goto Cambio1
movlw B'00000001'
xorwf Toggle,1 ;Transfiero el resultado al 'Toggle' para modificar el Toggle posteriormente
btfsc Toggle,0 ;Si la XOR vale '1' quiere decir que el Toggle era '0' -->Ok. Entonces pongo
goto Cambio2 ;Toggle a '1' y leo los bits del comando
movlw B'00000001' ;Si la XOR vale '0' quiere decir que el Toggle era'1' -->NO. Siguemos con Toggle
movwf Toggle ;a valor 1 y pasamos a LEER_Control ya que no se soltó el botón del telemando
goto LEER_Control
Cambio1 ;En caso de que el bit actual de Toggle sea '0'
movlw B'00000000'
xorwf Toggle,1 ;Pasamos el resultado de la XOR al Toggle
btfsc Toggle,0 ;Si el biestale '0' del Toggle vale '1' quiere decir que el Toggle actual es distinto al anterior -->OK
goto Cambio3
movlw B'00000000'
movwf Toggle
goto LEER_Control ;Empiezo a ver los siguientes bits de Control a ver si cambia el Toggle.
Cambio2 ;En este caso el Toggle actual '1' es distinto al anterior que era '0'
movlw B'00000001' ;Almaceno el valor del Toggle actual '0' para comprobar en la siguiente secuencia del RC5
movwf Toggle
retlw 0 ;Paso a leer los bits del Comando
Cambio3 ;Para poner el valor del Toggle actual '1'
movlw B'00000000'
movwf Toggle
retlw 0 ;Paso a leer los bits de Comando

LEER_ComandoDecMHz
rlf dec_MHz,1 ;Rotamos izquierda y guardamos el valor en dec_MHz. Tenemos el biestable 'C' a '0'
btfsc GPIO,3 ;Leemos el primer bit del comando MSB, el 2º, el 3º, etc...
bsf dec_MHz,0 ;Si en el puerto GP3 tenemos un '1' le metemos un 1 al dec_MHZ en el primer bit
call DELAY_1 ;Espermaos '1' bit para ler el siguiente
decfsz Contador,1 ;Decrementamos el Contador y saltamos '1' si es '0'
goto LEER_ComandoDecMHz ;Para leer el siguiente bit
movf dec_MHz,0 ;Pasamos el valor almacenado en dec_MHz al 'W' para comprobar si es 'BORRAR' ó 'ENTER'
subwf BORRAR,0 ;Restamos el contenido del registro BORRAR al 'W' si 'Z=1' quiere decir que son iguales
btfsc STATUS,2 ;Comprobamos el valor de 'Z' en el STATUS para saber si son iguales --> Z=1
goto MAIN ;Si Z=1 quiere decir que se pulso el botón BORRAR y empezamos todo otra vez
movf dec_MHz,0
subwf ENTER,0
btfsc STATUS,2 ;Si Z=1 quiere decir que se pulso el botón ENTER y empezamos todo otra vez
goto MAIN
retlw 0 ;En caso de que Z=0 entonces pasamos a capturar las UniMHZ

;Se debe introducir la frecuencia en KHz y debe ser para AM >512 KHz
LEER_ComandoUniMHz
rlf uni_MHz,1
btfsc GPIO,3
bsf uni_MHz,0
call DELAY_1
decfsz Contador,1
goto LEER_ComandoUniMHz
movf uni_MHz,0
subwf BORRAR,0
btfsc STATUS,2
goto MAIN
movf uni_MHz,0
subwf ENTER,0
btfsc STATUS,2
goto MAIN
retlw 0

LEER_ComandoCenKHz
rlf cen_KHz,1
btfsc GPIO,3
bsf cen_KHz,0
call DELAY_1
decfsz Contador,1
goto LEER_ComandoCenKHz
movf cen_KHz,0
subwf BORRAR,0
btfsc STATUS,2
goto MAIN
movf cen_KHz,0
subwf ENTER,0
btfsc STATUS,2
goto MAIN
retlw 0
LEER_ComandoDecKHz
rlf dec_KHz,1
btfsc GPIO,3
bsf dec_KHz,0
call DELAY_1
decfsz Contador,1
goto LEER_ComandoDecKHz
movf dec_KHz,0
subwf BORRAR,0
btfsc STATUS,2
goto MAIN
movf dec_KHz,0
subwf ENTER,0
btfsc STATUS,2
goto MAIN
retlw 0
LEER_ComandoUniKHz
rlf uni_KHz,1
btfsc GPIO,3
bsf uni_KHz,0
call DELAY_1
decfsz Contador,1
goto LEER_ComandoUniKHz
movf uni_KHz,0
subwf BORRAR,0
btfsc STATUS,2
goto MAIN
movf uni_KHz,0
subwf ENTER,0
btfsc STATUS,2
goto MAIN
retlw 0
LEER_ComandoENTER
rlf Temp,1
btfsc GPIO,3
bsf Temp,0
call DELAY_1
decfsz Contador,1
goto LEER_ComandoENTER
movf Temp,0
subwf BORRAR,0
btfsc STATUS,2
goto MAIN
movf Temp,0
subwf ENTER,0
btfss STATUS,2 ;Si Z=1 es que eran iguales por lo que pasamos a trx la freq al PLL
goto MAIN ;sino se pulsa ENTER volvemos al MAIN para empezar otra vez o bien porque se
;goto Trx_Freq ;pulsó 'BORRAR' o cualquier otro botón

;******TRANSMITIMOS LA FRECUENCIA AL PLL********

Trx_Freq
bsf GPIO,0 ;Pongo a '1' esta sailda que será el ENABLE de entrada al PLL
call DELAY_5uS ;El 'tTlead' debe de ser como mínimo 0.5 uS esto está OK porque cada instrucción tarda 1 uS
bsf GPIO,1 ;Señal de RELOJ.El 'tCLBlead' debe ser como minimo de 1 us. 5 uS para el tiempo de establecimiento 'tCLBlag'
call DELAY_5uS ;Señal para el reloj de entrada al PLL. Debe ser 5 uS alto y 5 uS bajo como mínimo (anchos de pulso)
bcf GPIO,1 ;Pone a '0' la salida de reloj
bcf GPIO,2 ;Trx primeramente un '0' para indicar que queremos "DATA WORD A" para indicar frq al PLL
call DELAY_3uS ;Para tener el reloj 5 uS a nivel bajo "ancho mínimo permitido"
bsf GPIO,1
call DELAY_5uS
bcf GPIO,1
movlw .4 ;Para pasar los 4 bits menos significativos de cada dígito de frecuencia
movwf Rotaciones
Otra1 rrf uni_KHz,1
btfsc STATUS,C
bsf GPIO,2 ;Si 'C=1' pongo la salida a '1'
bsf GPIO,1 ;Aqui sea como sea 'C' ponemos a '1' el reloj para muestrear el puerto GP2
call DELAY_3uS
bcf GPIO,1 ;Ponemos a'0' el reloj para cuando sea de muestrear el siguiente bit
bcf GPIO,2 ;Ponemos a '0' datos por si el siguiente fuera un '0'
decfsz Rotaciones,1
goto Otra1
movlw .4
movwf Rotaciones
Otra2 rrf dec_KHz,1
btfsc STATUS,C
bsf GPIO,2 ;Si 'C=1' pongo la salida a '1'
bsf GPIO,1 ;Aqui sea como sea 'C' ponemos a '1' el reloj para muestrear el puerto GP2
call DELAY_3uS
bcf GPIO,1 ;Ponemos a'0' el reloj para cuando sea de muestrear el siguiente bit
bcf GPIO,2 ;Ponemos a '0' datos por si el siguiente fuera un '0'
decfsz Rotaciones,1
goto Otra2
movlw .4
movwf Rotaciones
Otra3 rrf cen_KHz,1
btfsc STATUS,C
bsf GPIO,2 ;Si 'C=1' pongo la salida a '1'
bsf GPIO,1 ;Aqui sea como sea 'C' ponemos a '1' el reloj para muestrear el puerto GP2
call DELAY_3uS
bcf GPIO,1 ;Ponemos a'0' el reloj para cuando sea de muestrear el siguiente bit
bcf GPIO,2 ;Ponemos a '0' datos por si el siguiente fuera un '0'
decfsz Rotaciones,1
goto Otra3
movlw .4
movwf Rotaciones
Otra4 rrf uni_MHz,1
btfsc STATUS,C
bsf GPIO,2 ;Si 'C=1' pongo la salida a '1'
bsf GPIO,1 ;Aqui sea como sea 'C' ponemos a '1' el reloj para muestrear el puerto GP2
call DELAY_3uS
bcf GPIO,1 ;Ponemos a'0' el reloj para cuando sea de muestrear el siguiente bit
bcf GPIO,2 ;Ponemos a '0' datos por si el siguiente fuera un '0'
decfsz Rotaciones,1
goto Otra4
movlw .4
movwf Rotaciones
Otra5 rrf dec_MHz,1
btfsc STATUS,C
bsf GPIO,2 ;Si 'C=1' pongo la salida a '1'
bsf GPIO,1 ;Aqui sea como sea 'C' ponemos a '1' el reloj para muestrear el puerto GP2
call DELAY_3uS
bcf GPIO,1 ;Ponemos a'0' el reloj para cuando sea de muestrear el siguiente bit
bcf GPIO,2 ;Ponemos a '0' datos por si el siguiente fuera un '0'
decfsz Rotaciones,1
goto Otra5
bcf GPIO,0
goto MAIN

DELAY_3uS
nop
retlw 0

DELAY_5uS
nop
nop
retlw 0


;446 uS (Es la cuarta parte del tiempo de un bit)
DELAY_1_4
movlw .109 ; ;Número de repeticiones
movwf Delay0 ;Metemos 110 en el registro Delay0
Etiq1 clrwdt ;Para que no se reinicie automáticamente el WDTE
decfsz Delay0,1 ;Decrementa y si es '0' salta una instrucción
goto Etiq1 ;Seguimos decrementando
retlw 0 ;(r_2) ;Vuelvo a "LEER"

DELAY_1_2 ;(3), (4), (5) Llamamos dos veces a DELAY1_4
call DELAY_1_4
call DELAY_1_4
retlw 0

DELAY_1
call DELAY_1_2
call DELAY_1_2
retlw 0

DELAY_6
call DELAY_1
call DELAY_1
call DELAY_1
call DELAY_1
call DELAY_1
call DELAY_1
retlw 0
END

Un saludo y muchas gracias,

Joaquín
 
Hola Quino29,muy interesante tu código,y también la aplicación para el control de un PLL,dime tu ya has logrado que funcione? te lo pregunto y te lo digo a modo de recomendación pues en algunos tutoriales he leído que para aplicaciones con señales de control IR,es muy importante los tiempos y suele ocurrir que el OSC Interno del PIC tiene cierta tolerancia,por lo que se utilizan cristales externos para el PIC,otro detalle que te menciono es que tu código debe tener antes de END la siguiente instrucción:

;-------------------------------------------------------------------------;
; Valor de Calibración ;
;-------------------------------------------------------------------------;
ORG 0x3FF
RETLW 0x30
END ; fin de directivas de programa


cuando grabas el PIC el programa te preguntará si deseas reemplazar el valor de fábrica por el valor del código,tu le dices "NO" y el clock estará +- 2% de 4.000Mhz.
Saludos
Americo8888
 
Hola Quino29,muy interesante tu código,y también la aplicación para el control de un PLL,dime tu ya has logrado que funcione? te lo pregunto y te lo digo a modo de recomendación pues en algunos tutoriales he leído que para aplicaciones con señales de control IR,es muy importante los tiempos y suele ocurrir que el OSC Interno del PIC tiene cierta tolerancia,por lo que se utilizan cristales externos para el PIC,otro detalle que te menciono es que tu código debe tener antes de END la siguiente instrucción:

;-------------------------------------------------------------------------;
; Valor de Calibración ;
;-------------------------------------------------------------------------;
ORG 0x3FF
RETLW 0x30
END ; fin de directivas de programa


cuando grabas el PIC el programa te preguntará si deseas reemplazar el valor de fábrica por el valor del código,tu le dices "NO" y el clock estará +- 2% de 4.000Mhz.
Saludos
Americo8888


Antes de nada muchas gracias por tus observaciones. Lo del reloj interno del PIC ya lo pense seriamente ya que como tu bien dices el reloj interno presenta una tolerancia y los tiempos para muestrear una trama RC5 son cortos por lo que puede que no sea lo suficientemente preciso el reloj interno. Después lo que me cometas respecto a las dos líneas de código antes del END, ahí discrepo ya que estuve leyendo en este mismo foro que no es necesario ya que al inicio al llamar a la posición 0x3FF ya coge el valor de fábrica. De todas formas si crees que estas completamente seguro sería una prueba que podría hacer.

Muchísimas gracias y espero recibir más opiniones constructivas para conseguir realizar esto.
 
Atrás
Arriba