TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: kain589 en 26 de Febrero de 2009, 21:19:23
-
Saludos! Estoy intentando realizar un programa que descifre el protocolo RC5, quiero realizar la gestion del codigo por interrupciones para poder hacer cosas con el pic.
El protocolo, que trabaja a 36khz, esta formado por 14 bits, los 2 primeros de start, el 3º de toogle, le siguen 5 bits de direccion y, por ultimo,6 bits de comando. Cuando se envia un "0" logico, se codifica como 889us con la emision del tren de pulsos a 36khz, y despues 889us en ausencia de señal;cuando se envia un "1" logico, se codifica como 889us con ausencia de señal, y despues 889us con emision del tren de pulsos a 36khz.En total, cada envio emplea 1778us
Para la captacion de la señal se emplea un Tsop, el cual si no me equivoco, presenta una salida negada; es decir, cuando existe la señal a 36 khz pone su salida a "0", y en ausencia de la señal pone su salida a "1".
La idea es activar la interrupcion externa, en el flanco de bajada, asi con el 1º bit de start se entrara en la interrucion. Una vez que estamos en la interrupcion, se comprueba que la entrada esta a "0" (al ser inversa la salida del tsop) y posteriormente se configura el micro para que se genere una interrupcion del timer0 cada 1778us y se desactiva la interrupcion externa.
El generar interrupciones cada 1778us se debe a que cuando se produzca el flanco de bajada que genera la interrupcion externa, estaremos en la segunda mitad del bit de start (es decir la parte del cero de parte del tsop); a partir de este momento generando la interrupcion cada 1778us estaremos todas las veces en la 2 parte del bit, al ser 14 bit aunque los retardos de las rutinas se vayan acumulando no deberian sobrepasar los 889us de que disponemos en esta mitad(Ademas uso un pic de la serie 18 a 48 mhz, ya que quiero poder conectarlo al usb).
En la rutina del timer0, se vuelve a iniciar el valor del timer0 y se almacena el bit de entrada. Se comprueba el 2 bit de start, por ahora el bit de toogle y los bits de direccion no hago nada con ellos; y se almacenan los de comando. Al llegar al ultimo bit, se vuelve a activar la interrupcion externa.
El problema ahora mismo es que no consigo pasar a la parte del timer, y no veo porqué. Antes si me entraba, pero he modificado cosas y no sé porque no entra ahora. De todas formas cuando me entraba en la 2 parte del programa, las interrupciones del timer0, me leia todos los comandos como FF (todos los bits a 1)
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
//Version:3.0
//Negar tsop: Se niega tsop, y cambia tipo interrupcion
//Faltaba iniciar temporizador en rutina timer0
#include ".\include\usb_cdc.h"
//Definimos entradas salidas
#byte PORTB = 0x06
//#bit Tsop = PORTB.0
//Definimos constantes
#define tempo 44198//65536-(10668*2)
//Variables
int1 Error;//indica error en recepcion
int8 ContadorBit;//Cuenta nºbit recibido
int8 Direccion;//Para direccion en RC5
int8 Comando; //Para comando en RC5
//INTERRUPCIONES
/*Interrupcion externa0, en la subida.
Indica que se inicia la recepcion de la trama.Se comprueba bit de start y se
configura el timer0 para que genere interrupcion cada 889us*/
#int_EXT
void EXT_isr()
{
// desactimos la interrupcion externa
disable_interrupts(INT_EXT);
printf(usb_cdc_putc, "\r\nExt");
if(input(!PIN_B0))//Bit de entrada igual a 1, bit de start
{
// ponemos el offset al timer para ajustar el tiempo
set_timer0(tempo);
// activamos la interrupcion del timer
enable_interrupts(INT_TIMER0);
}
else
{
//Esperamos y activamos interrupcion externa
delay_ms(50);
enable_interrupts(INT_ext);
}
}
#INT_TIMER0
void TIMER_isr()
{
// desactivamos la interrupcion, este periodo de tiempo se desprecia
disable_interrupts(INT_TIMER0);
//ponemos el offset al timer para ajustar el tiempo
set_timer0(tempo);
//Incrementamos contador de bits
ContadorBit++;
// Verifica si es 2 bit de start
If (ContadorBit==1)
{//Hacer con un if y tsop complementado
if(input(!PIN_B0))
{
printf(usb_cdc_putc, "\r\nstart2");
}
else
{//Hubo error
printf(usb_cdc_putc, "\r\nHubo error");
//Se inicia contador
ContadorBit=0;
//Se desactiva int del timer0, y activa int-ext, para nueva recepcion
disable_interrupts(INT_TIMER0);
enable_interrupts(INT_ext);
}
}
//Rutina para toogle por hacer
/*Rutina recepcion direccion,son 5 bits no necesaria por ahora
If (ContadorBit>3 && ContadorBit<8)
{
//codigo
}
*/
If(ContadorBit>7 && ContadorBit<13)
{//Rutina comando, multiplicax2 y suma tsop, igual a ir cargando bit a bit
comando=comando*2+(input(PIN_B0));
}
//Activamos la interrupcion del timer, hasta fin de trama
enable_interrupts(INT_TIMER0);
//Final de la trama
If (ContadorBit==13)
{//Se envia comando recibido por usb
printf(usb_cdc_putc, "\r\nComando recibido: ");
printf(usb_cdc_putc, "%x",comando);
//SE inicia contador y comando
comando=0;
ContadorBit=0;
//Se desactiva int del timer0, y activa int-ext, para nueva recepcion
disable_interrupts(INT_TIMER0);
enable_interrupts(INT_ext);
}
}
void main()
{
//Configuraciones compilador
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//Programa
// Desactivamos las interrupciones que usaremos
disable_interrupts(INT_EXT);
disable_interrupts(INT_TIMER0);
// activamos la global
enable_interrupts(GLOBAL);
// configuramos el timer 0 para tener un overflow cada 1778 us a 48Mhz, es decir conteo cada 1us = Fosc/4
setup_timer_0(RTCC_INTERNAL);
//Define flanco de subida (Para la activacion de la interrupcion )
ext_int_edge(INT_EXT,H_TO_L);
enable_interrupts(INT_ext);
//Activación usb y conexion por parte del host
delay_ms(300);
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}
//Configuracion usb por parte del host
usb_task();
if (usb_enumerated()) {
do
{
}while (TRUE);
}
}
Aqui les pongo el codigo, por si alguien ve los erroes o tiene sugerencias.Gracias de antemano.
-
hola!, hace poco armé un receptor para protocolo RC5, con un PIC16F84A
Te dejo el código, espero que te sirva.
Saludos!
#include <16F84A.h>
#fuses XT,NOWDT,NOPROTECT,PUT
#use delay (clock=4000000)
#use fast_io(b)
#define IR_IN (!input(PIN_B4))
int8 bit[14], i, error, state=0;
#int_rb
void RC5Decoder() {
error=0;
while(IR_IN==0);
bit[0] = 1;
set_timer0(0);
while(get_timer0()<111);
for(i=1;i<14;i++) {
set_timer0(0);
while(get_timer0()<222);
if(IR_IN==0) {
set_timer0(0);
while(get_timer0()<222);
if(IR_IN==1) bit[i]=1; else error=1;
}else {
set_timer0(0);
while(get_timer0()<222);
if(IR_IN==0) bit[i]=0; else error=1;
}
}
state=1;
disable_interrupts(INT_RB);
}
void main() {
set_tris_a(0);
set_tris_b(0x10);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
ext_int_edge(H_TO_L);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
delay_ms(500);
while(1) {
if(state==1) {
if(error==0) { //muestro los primeros 10bits
output_bit(PIN_A2,bit[0]);
output_bit(PIN_A3,bit[1]);
output_bit(PIN_B0,bit[2]);
output_bit(PIN_B1,bit[3]);
output_bit(PIN_B2,bit[4]);
output_bit(PIN_A1,bit[5]);
output_bit(PIN_A0,bit[6]);
output_bit(PIN_B7,bit[7]);
output_bit(PIN_B6,bit[8]);
output_bit(PIN_B5,bit[9]);
delay_ms(250);
output_bit(PIN_A2,0);
output_bit(PIN_A3,0);
output_bit(PIN_B0,0);
output_bit(PIN_B1,0);
output_bit(PIN_B2,0);
output_bit(PIN_A1,0);
output_bit(PIN_A0,0);
output_bit(PIN_B7,0);
output_bit(PIN_B6,0);
output_bit(PIN_B5,0);
state=0;
}else { // prendo todos los LEDS, avisando que hubo un error en la recepcion.
output_bit(PIN_A2,1);
output_bit(PIN_A3,1);
output_bit(PIN_B0,1);
output_bit(PIN_B1,1);
output_bit(PIN_B2,1);
output_bit(PIN_A1,1);
output_bit(PIN_A0,1);
output_bit(PIN_B7,1);
output_bit(PIN_B6,1);
output_bit(PIN_B5,1);
delay_ms(250);
output_bit(PIN_A2,0);
output_bit(PIN_A3,0);
output_bit(PIN_B0,0);
output_bit(PIN_B1,0);
output_bit(PIN_B2,0);
output_bit(PIN_A1,0);
output_bit(PIN_A0,0);
output_bit(PIN_B7,0);
output_bit(PIN_B6,0);
output_bit(PIN_B5,0);
}
enable_interrupts(INT_RB);
}
}
}
-
Gracias por tu ayuda chacruna, pero lo que intento es "aligerar" la rutina de interrupcion por la entrada externa, que entre-salga en poco tiempo y despues se produzcan las interrupciones periodicas del timer0 para poder hacer otras cosas mientras con el pic.