Hola elreypic.
No sabia que la longitud de las antenas fuera tan critica, en cuanto pueda las pongo de 17 cm las dos ya que los modulos son de 434 Mhz, por cierto los hilos deben estar desnudos o sirven con la funda plastica.
Utilizo el pin digital de salida del receptor, el analogico lo dejo al aire no se si esta bien asi o es mejor fijarlo a un potencial ya sea '0' o '1'.
Codigo del emisor:
#pragma config=0X2f61
#pragma config reg2=0X0000
#pragma chip PIC16f88
#pragma interruptSaveCheck n
#pragma codepage 0
#pragma sharedAllocation
#pragma origin 4
static uns8 CUENTA; //variable para contar 0,5 seg
static uns8 BUCLE; //variable para controlar el flujo del programa
static uns8 CABECERA_1; //variables para guardar las cabeceras
static uns8 CABECERA_2;
static uns8 RESULTADO_1; //variables para guardar el resultado
static uns8 RESULTADO_2;
static uns16 INTER; //variable temporal donde guardo la parte alta del valor obtenido por el CAD
static uns16 RESUL;
static uns8 RESUL_1; //variable donde se guarda el valor del la temperatura
static uns8 COPIARESUL; //variable donde guardo una copia en binario de la temperatura obtenida por el CAD
//declaraciones de funciones
void retardo_10u(unsigned char i); //funciones de los retardos
void retardo_m(unsigned char i);
void envia_cadena (uns8 X,uns8 Y, uns8 A,uns8 B); //funcion que envia la cadena con las 2 cabeceras y el dato codificado en manchester
void envia_dato (uns8 DATO_1); //funcion que envia un dato en particular
uns8 manchester(uns8 DATO); //funcion que codifica un dato en manchester
interrupt inter (void) //rutina de atencion a la interrupcion
{
if (T0IF==1) //si se produce la interrupcion del timer 0
{ T0IF=0; //borro el flag
if(CUENTA==0){ //si la variable CUENTA llega a '0'
CUENTA=133; //pongo CUENTA a 133
switch(BUCLE){
case 0x00:{ //si la variable que controla el programa es '0'
T0IE=0; //deshabilito la inter del timer
ANSEL=0X10; //configuro el CAD en el orden que manda el datasheet, primero selecciono la entrada analogica
ADCON1=0X80; //justificado resultado del CAD a la derecha
ADCON0=0X20; //selecciono el canal de entrada analogico 4
ADCON0=0XE0; //selecciono el reloj de conversion interno
ADCON0=0XE1; //enciendo el CAD
ADIF=0; //borro el flag del CAD
ADIE=1; //habilito la interrupcion del CAD
PEIE=1; //habilito interrupciones generales
GIE=1;
retardo_10u(1); //retardo para respetar el tiempo de adquisicion necesario
GO=1; //arranco el CAD
T0IF=0; //borro el flag de interrupcion del timer 0
PORTB.5=!PORTB.5;
break;
}
case 0x01:{ //si la variable que controla el programa es '1'
//T0IE=0;
PORTB.0=0; //pongo la patila b.0 a '0'
PORTB.6=!PORTB.6;
BUCLE=0X02; //actualizo la variable de control del programa
break;
}
case 0x02:{ //si la variable que controla el programa es '2'
T0IE=0; //deshabilitamos la inter del timer 0
envia_cadena(CABECERA_1,CABECERA_2,RESULTADO_1,RESULTADO_2); //funcion que envia una cadena
BUCLE=0X00; //se pone la variable que controla el programa a '0'
TMR0=0; //se pone el timer 0 a '0'
T0IE=1; //deshabilito la inter del timer 0
break;
}
}
}
else{
CUENTA--; //decremento CUENTA
}
}
else {
ADIF=0; //borro el flag
ADIE=0; //deshabilito la inter del CAD
ADON=0; //apago el CAD
RESUL=ADRESL;
INTER=ADRESH*256;
RESUL=RESUL+INTER; //convierto valor del CAD a decimal
RESUL=RESUL*100;
RESUL=RESUL/205; //convierto el valor a grados
RESUL_1=RESUL; //hago dos copias del resultado
COPIARESUL=RESUL;
PORTB.0=1; //pongo la salida b.0 a '1'
RESULTADO_1=manchester(RESUL_1); //codifico la mitad del resultado en manchester y lo guardo en RESULTADO_1
COPIARESUL=COPIARESUL>>4; //desplazo el resultado 4 bits a la derecha
RESULTADO_2=manchester(COPIARESUL); //codifico la otra mitad del resultado en manchester y lo guardo en RESULTADO_2
TMR0=0; //pongo el timer 0 a '0'
T0IE=1; //deshabilito la ineterrupcion del timer 0
BUCLE=0X01; //pongo a '1' la variable de control del programa
}
}
#include "retardos.inc" //libreria que incorpora los retardos
void main (void)
{
TRISB=0X00; //configuro el puerto b como salida
TRISA=0X10; //configuro la entrada a4 como entrada
ANSEL=0X10; //selecciono la entrada a4 como entrada del CAD
OPTION_REG=0X03;
CUENTA=133; //inicializamos la variable cuenta para que cuente 0.5 seg
PORTB=0X00; //ponemos el puerto b a '0'
TMR0=0; //inicializa el temporizador
INTCON=0XE0; //configuramos y habilitamos las interrupciones
BUCLE=0X00; //inicializamos la variable de control del programa
CABECERA_1=0XAA; //inicializamos las variables que sirven de cabecera
CABECERA_2=0X55; //para el envio de un dato
RESULTADO_1=0X00;
RESULTADO_2=0X00; //inicializamos las variables
while(1);
}
uns8 manchester(uns8 DATO) //funcion que codifica un dato en manchester
{
uns8 i;
uns8 RESULTADO=0; //variable donde se guarda el resultado de la codificacion
for(i=0;i<4;i++){
RESULTADO=RESULTADO>>2; //desplazamos la variable RESULTADO dos bits para dar entrada a los bits nuevos
if(DATO.0==1){
RESULTADO.6=1; //guardamos los bits conforme a la conversion
RESULTADO.7=0;
}
else{
RESULTADO.6=0;
RESULTADO.7=1;}
DATO=DATO>>1; //desplazamos la variable DATO un bit para evaluar el siguiente bit a codificar
}
return RESULTADO; //devolvemos el dato codificado
}
void envia_cadena (uns8 X,uns8 Y,uns8 A,uns8 B) //funcion que envia la cadena formada por las cabeceras y el dato
{
PORTB.0=1; //iniciamos la transmision con un '1' de duracion de 50 mseg
retardo_m(50);
PORTB.0=0; //ponemos un '0' durante 5 mseg
retardo_m(5);
envia_dato(X); //se envian los cuatro datos que forman la cadena
envia_dato(Y);
envia_dato(A);
envia_dato(B);
PORTB.0=1; //una vez enviados los datos ponemos la salida a '1' lo que queda de medio segundo mas o menos 240 mseg
retardo_m(240);
PORTB.0=0; //ponemos la b.0 a '0'
}
void envia_dato (uns8 DATO_1) //funcion que envia un dato de los que forman la cadena
{
uns8 i;
PORTB.7=!PORTB.7;
PORTB.0=1; //bit de inicio durante 5 mseg
retardo_m(5);
for(i=0;i<8;i++){
if(DATO_1.0==1){ //van saliendo por la patillab.0 los bits correspondientes al dato
PORTB.0=1;}
else{
PORTB.0=0;}
DATO_1=DATO_1>>1; //desplazo la variable DATO_1 un bit para ir sacando el bit que corresponda
retardo_m(5);} //cadencia con la que salen los datos
PORTB.0=0; //bit de fin durante 5 mseg
retardo_m(5);
}
Te comento un poco como funciona. La salida que es la patilla portb.0 nunca esta fija a '0' o a '1' mas de 0.5 segundos, (no se si recuerdas que ya comentamos que al quedarse un '0' o un '1' fijo empezaba a enviar cosas sin sentido y asi de esta manera me aseguro que no envia nada que yo no quiera) y aprovecho los momentos en que esta a '1' para hacer la conversion del CAD y el envio de datos alternativamente. En el dibujo adjunto lo puedes ver mejor.
Codigo del receptor:
#pragma config=0X2161
#pragma chip PIC16f628a
#pragma interruptSaveCheck n
#pragma sharedAllocation
#pragma origin 4
uns8 BUCLE; //variable donde se trata el valor de salida
uns8 DATO[4]; //matriz donde se guardan las dos cabeceras y el dato dividido en 2 partes
//declaraciones de funciones
void retardo_m(unsigned char i); //funcion retardo milisengundos
uns8 recibir_bits(); //funcion para recibir individualmente los bits que forman un dato
uns8 recibir_dato(); //funcion para recibir los cuatro datos que forman la cadena
uns8 unir_manchester (uns8 X,uns8 Y); //funcion para obtener el dato a partir de los dos valores codificados en manchester
uns8 u_manchester (uns8 Z); //funcion para decodificar el valor codificado en manchester
interrupt inter (void)
{
if (INTF==1){ //si se detecta interrupcion externa
INTF=0; //borro el flag de la inter externa
retardo_m(52); //espero 52 mseg para estar dentro del '0' de sincronizacion
if(PORTB.0==0){ //si detecto el '0'
GIE=0; //deshabilito las interrupciones mientras recibo los datos
if(recibir_dato()){ //si la recepcion se completo bien
if(DATO[0]==0XAA&&DATO[1]==0X55){ //si las cabeceras son correctas
PORTB.7=!PORTB.7; //niego la salida b.7 para saber que se recibio un dato valido
BUCLE=unir_manchester(DATO[2],DATO[3]); //guardo en una variable temporal el valor de la temperatura recibido en dos variables codificadas en manchester
BUCLE=BUCLE-10; //resto 10 para poder visualizarlo en 5 leds
PORTA=BUCLE;} //saco el valor por el puerto a
else{
PORTB.6=!PORTB.6;} //si hubo un error en la recepcion de alguna de las cabeceras lo muestro en la salida b.6
}
else{
PORTB.5=!PORTB.5;} //si hubo un error durante la recepcion de uno de los datos lo muestro en la salida b.5
}
else{
PORTB.4=!PORTB.4;} //si no detecto el '0' de sincronizacion lo muestro en la salida b.4
INTF=0; //borro el flag de la inter externa
GIE=1;} //si todo funciono bien vuelvo a habilitar las interrupciones
}
#include "retardos.inc" //libreria que incorpora los retardos
void main (void)
{
TRISB=0X01; //configuro el puerto B, la pata b.1 como entrada
TRISA=0X00; //configuro el puerto A
INTEDG=1; //habilito la interrupcion externa por flanco de subida
INTCON=0XD0; //configuro y habilito las interrupciones
BUCLE=0X00;
DATO[0]=0x00;
DATO[1]=0x00;
DATO[2]=0x00;
DATO[3]=0x00; //inicializo las variables
PORTB=0X00; //pongo el puerto b a '0'
while(1);
}
uns8 recibir_dato() //funcion para recibir los 4 datos que hay dentro de una cadena
{
uns8 TEMP; //variable temporal para guardar el dato recibido
uns8 i; //variable para el bucle
for(i=0;i<4;i++){
retardo_m(5); //espero 5 mseg para colocarme en el bit de inicio de cada dato a recibir
if(PORTB.0==1){ //si es un '1'
TEMP=recibir_bits(); //guardo en TEMP los bits recibidos
DATO[i]=TEMP; //guardo en una posicion de la matriz el dato recibido
retardo_m(5); //espero 5 mseg para colocarme en el bit de final
if(PORTB.0==0){ //si es un '0' se leyo el dato bien
}
else{
return 0x00;}} //si el bit de fin no se corresponde con un '0' la funcion devuelve un '0'
else{
return 0x00;} //si el bit de inicio no se corresponde con un '1' la funcion devuelve un '1'
}
retardo_m(5); //espero 5 mseg para salir de la cadena
return 0x01; //devuelve un '1' si se recibieron los cuatro datos que van dentro de la cadena
}
uns8 recibir_bits() //funcion para recibir los 8 bits que forman un dato
{
uns8 i;
uns8 OCTETO; //variable para guardar los 8 bits recibidos
for(i=0;i<8;i++){
retardo_m(5); //espero 5 mseg para colocarme en el primer bit
OCTETO=OCTETO>>1; //desplazo los bits hacia la derecha para dejar paso al siguiente
if(PORTB.0==1){
OCTETO.7=1;} //si en la entrada b.0 hay un '1' lo guardo en el bit 7 de la variable
else{
OCTETO.7=0;} //si en la entrada b.0 hay un '0' lo guardo en el bir 7 de la variable
}
return OCTETO; //devuelvo el valor recibido
}
uns8 unir_manchester (uns8 X,uns8 Y) //funcion para unir los dos valores recibidos en manchester en uno solo de 8 bits
{
uns8 TEMP_1; //variables temporales para hacer la union
uns8 TEMP_2;
uns8 TEMP_3;
uns8 TEMP_4;
TEMP_1=u_manchester(X); //decodifico el primer valor manchester
TEMP_2=u_manchester(Y); //decodifico el segundo valor manchester
TEMP_3=TEMP_2<<4; //uno los dos valores
TEMP_4=TEMP_1|TEMP_3;
return TEMP_4; //devuelvo el valor obtenido
}
uns8 u_manchester (uns8 Z) //funcion para decodificar el valor en manchester
{
uns8 i;
switch(Z){
case 0xAA:
i=0x00;
break;
case 0xA9:
i=0x01;
break;
case 0xA6:
i=0x02;
break;
case 0xA5:
i=0x03;
break;
case 0x9A:
i=0x04;
break;
case 0x99:
i=0x05;
break;
case 0x96:
i=0x06;
break;
case 0x95:
i=0x07;
break;
case 0x6A:
i=0x08;
break;
case 0x69:
i=0x09;
break;
case 0x66:
i=0x0A;
break;
case 0x65:
i=0x0B;
break;
case 0x5A:
i=0x0C;
break;
case 0x59:
i=0x0D;
break;
case 0x56:
i=0x0E;
break;
case 0x55:
i=0x0F;
break;
}
return i; //devuelvo el valor decodificado
}
El receptor funciona de la siguiente manera. Aprovecho la interrupcion externa del pic receptor para detectar los flancos de subida de la señal enviada como te indico en el dibujo adjunto, o bien se trata del pulso en el que el emisor utiliza el cad (pulso A en el dibujo) y por lo tanto el pic receptor no detectara nada posterior al flaco en la patilla b.0, o bien se trata del pulso en el que el emisor envia los datos (pulso B en el dibujo) y por lo tanto tras un retardo de 50 mseg el pic receptor detecta los valores correctos para la sincronizacion y recibira primero las cabeceras y despues el dato.
Mejor echale un vistazo y te aclaro lo que no entiendas porque me esta saliendo un post muy pesado jajajaj.
Saludos.