Mira
Para capturar las tramas puedes usar el sgte codigo (basado en redraven:
http://picmania.garcia-cuervo.com/Proyectos_AUX_Botones.htm).
Mi experiencia me dice que un mando sony envia tramas de 12 bits para la mayoria de las teclas. Sin embargo tambien implementa tramas de 15 y 20 bits....de modo que se aconseja capturar las tramas de todos los botones...Para ello se puede utilizar la interrupcion externa por RB0 usando ambos flancos (rising/falling)..asi se puede obtener los tiempos en que la señal se mantuvo en HIGH como asi tambien cuando estubo en LOW...al momento de producirse la interrupción, se debe capturar el valor de TMR0 y resetearlo nuevamente, para que comience a incrementarse y capturar el tiempo en el próximo flanco....es sencillo de implementar....
Se usa TMR0 con DIV16 para adecuar los tiempos y los valores maximos del TMR0....si consideramos que SIRC estipula 600us para un 0, y 1200 us para un 1, y 600us de tiempo entre acda pulso...vemos que div16 es suficiente....ahora, el receptor infrarojo (yo he usado el IRM8601) responde con pulsos de entre 400/800 us.....asi que hay un margen sobre el cual se maneja el TMR0....este codigo me ha funcionado bien..capturé las tramas del mando de mi equipo de audio sony genezzi...un mandop RM-SC3.....
Pienso que si se desea utilizar funciones relacionadas con cierttos botones, no es necesario conocer el codigo sirc...sino mas bien capturas las tramas y ordenarlas en un buffer en modo LSB/MSB first según se desee...y luego comparar con el valor guardado en la eeprom...y listo...
El programa captura los tiempo HIGH y LOW y los almacena en 2 buffer, tambien cuenta el numero de interrupciones...luego los muestra por RS232 al PC.....
Para saber si es un 1 o un 0...basta con multiplicar el valor del TMR0 capturado por 16us y ya sabras de que se trata...
Generalmente, un 0 da un valor de 30 a 45 del TMR0, y el doble para un 1, osea entre 65/90...para el star bit da entre 130/145....recordar que el receptor tiene un margen de 400/800us, y segun eso el valor de TMR0 varia....
Para que el codigo sirva debes usar un transistor npn emisor comun salida colector....de lo contrario cambiar la asignacion en los buffer..
Suerte..
#include <16F648A.h>
#device *=16 // Full RAM Pointer
#FUSES NOWDT // Watch Dog Timer
#FUSES PUT // Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES BROWNOUT // Reset when brownout detected
#FUSES NOMCLR // Master Clear pin enabled
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES INTRC_IO // Internal RC Osc, no CLKOUT
#FUSES NOCPD // No EE protection
#use delay(clock=4000000,RESTART_WDT)
#use rs232(baud=19200,parity=n,xmit=PIN_B2,rcv=PIN_B1,bits=8)
char Command=0;
char Keypress=0;
int i=0; //Contador genérico
int uTimeUp=0;
int uTimeDown=0;
int TimesUp[72]; //almacena valor del TMR0 cuando RB0=1
int TimesDown[72]; //almacena valor del TMR0 cuando RB0=0
int status=0;
//Selecciona el flanco a monitorear
int flanco=1; //Por defecto el de subida
long int n_int=0; // Contador del número de interrupciones ocurridas
void Transmission(void); //declara la funcion Transmision()
void clear_buffer(void);
#int_rda
void serial_isr() {
Keypress=0;
if(kbhit()){
Keypress=getc();
if(Keypress!=0){
Command=Keypress;
}
}
}
#int_EXT
EXT_isr() {
++n_int; // Autoincremento del contador de interrupciones
//clear_interrupt(int_ext); // Limpia el FLAG indicador de
// interrupción externa
switch(flanco){ //
// Flanco de bajada
case 0: TimesUp[uTimeUp++]=GET_RTCC(); // Obtiene el tiempo del pulso Alto 1.
flanco=1;
ext_int_edge(L_TO_H); // Próximo flanco que se espera, L_TO_H
set_timer0(0); // Reset del contador TMR0
break;
// Flanco de subida
case 1: TimesDown[uTimeDown++]=GET_RTCC(); // Obtiene el tiempo del pulso bajo 0.
flanco=0;
ext_int_edge(H_TO_L); // Próximo flanco que se espera, H_TO_L
set_timer0(0); // Reset del TMR0 para contar el largo del pulso 1
break;
}
//enable_interrupts(INT_EXT);
//}
}
void main()
{
setup_counters(RTCC_INTERNAL,RTCC_DIV_16); //TMR0 se incrementa cada 16us
//de modo que nunca se desborda
//TMR0 se incrementa cada 16us=0,016ms
//2,4ms/0,016ms=150
set_tris_b(0b11111011); //B1/B0=entrada,B2=salida
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//disable_interrupts(INT_RTCC); // Deshabilita int por TMR0
//delay_ms(3000);
ext_int_edge(L_TO_H); //Para capturar el start bit
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
flanco=1;
clear_buffer(); //limpia ambos buffer
printf("\n\rPresione el Mando ...\r\n\n");
set_rtcc(0);
do{ // Bucle do/while, se ejecuta permanentemente
if(Command!=0){
Command=0;
Transmission();
}
} while (TRUE); //Bucle infinito
}
void clear_buffer(void){
for(i=0;i<72;i++){
TimesUp[i]='\0'; // Limpia ambos buffers con NULL
TimesDown[i]='\0';
}
}
void Transmission(void){
printf("\n\rResultados:\n\n\r");
printf("Total Interrupciones: %2Lu\r\n\n",n_int);
printf("\n\r# Down Table: Up Table:\n\n\r");
for(i=0;i<72;i++){
printf("%2u Valor: %3u Valor: %3u\n\r",i,TimesDown[i],TimesUp[i]);
}
clear_buffer();
ext_int_edge(L_TO_H); //Para capturar el start bit. Reconfigura en caso de error.
flanco=1;
n_int=0;
printf("\n\rPresione el Mando ...\r\n");
status=input(PIN_B0);
printf("RB0=%2u\n\r",status);
}