#include <16F88.h>
#include "PIC16F88E.h" // Librería modificada para el el nRF24L01 con el PIC 16F88.
#fuses XT //Oscilador a cristal standar
#fuses NOWDT //sin WatchDog Timer
#fuses NOPROTECT //sin proteccion de memoria de programa
#fuses PUT //sin PowerUp Timer
#fuses NOBROWNOUT //sin brownout
#fuses NOLVP //sin programación en baja tensión
#use delay(clock=4000000)
#byte porta=0x05 // Dirección de los puertos A, B, C, D y E.
#byte portb=0x06
int8 ret2;
int8 ret1;
int8 data1;
int8 cont=0XFF;
#int_ext // Interrupción RB0/INT del módulo RF.
void int_RB0()
{
ret1 = RF_RECEIVE();
if ( (ret1 == 0) || (ret1 == 1) )
{
do
{
data1=RF_DATA[0]; // Data1 contendrá el valor que le llege del emisor, a través de RF_DATA[0].
#asm
BTFSS data1,0
BCF PORTB,6
BTFSC data1,0
BSF PORTB,6
BTFSS data1,1
BCF PORTB,7
BTFSC data1,1
BSF PORTB,7
//BTFSS data1,2
//BCF PORTB,3
// BTFSC data1,2
//BSF PORTB,3
#endasm
data1=RF_DATA[1];
data1=RF_DATA[2];
data1=RF_DATA[3];
data1=RF_DATA[4];
data1=RF_DATA[5];
data1=RF_DATA[6];
data1=RF_DATA[7];
ret1 = RF_RECEIVE();
} while ( (ret1 == 0) || (ret1 == 1) ); // Tanto si existe entrada múltiple o simple de datos los lee.
}
}
void main()
{
RF_CONFIG_SPI(); // Configurar módulo SPI del PIC.
RF_CONFIG(0x40,0x01); // Configurar módulo RF canal y dirección de recepción de datos para este PIC.
RF_ON(); // Activar el módulo RF.
RF_INT_EN(); // Habilitar interrupción RB0/INT.
delay_ms(5); // Dejamos como mínimo 2.5ms antes de comenzar a enviar.
set_tris_a(0b101011); // Dejo RA5 como salida para evitar poner la resistencia de polarización.
set_tris_b(0b00000011);
while(true)
{
delay_ms(2000);
#asm
btfss PORTA,0
bcf cont,0
BTFSC PORTA,0
BSF cont,0
btfss PORTA,1
bcf cont,1
BTFSC PORTA,1
BSF cont,1
btfss PORTA,3
bcf cont,2
BTFSC PORTA,3
BSF cont,2
#endasm
RF_DATA[0] = cont; // El contenido del contador lo cargo en RF_DATA[0] para ser enviado., se pueden enviar hasta 8 bytes desde data 0 hasta data 7
RF_DATA[1] = cont;
RF_DATA[2] = cont;
RF_DATA[3] = cont;
RF_DATA[4] = cont;
RF_DATA[5] = cont;
RF_DATA[6] = cont;
RF_DATA[7] = cont;
RF_DIR=0x08; // Dirección del receptor.
ret2=RF_SEND(); // Envía el dato.Ret 2 nos devuelve el estado del proceso (envio)
delay_ms(50); // Una pausa en cada incremento.
if(ret2==0) //se ha enviado y ha recibido ACK
{
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
}
else if(ret2==1) // se ha enviado pero no ha recibido el ACK
{
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
}
else // no ha podido ser enviado
{
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
#asm
bsf PORTB,5
#ENDASM
delay_ms(300);
#ASM
BCF PORTB,5
#ENDASM
delay_ms(300);
}
}
}
// PORTB
#define RF_IRQ PIN_B0
#define RF_IRQ_TRIS TRISB,0
// PORTC
#define RF_CS PIN_A2
#define RF_CE PIN_B3
#define SCK PIN_B4
#define SDI PIN_B1
#define SDO PIN_B2
#define RF_CS_TRIS TRISA,2
#define RF_CE_TRIS TRISB,3
#define SCK_TRIS TRISB,4
#define SDI_TRIS TRISB,1
#define SDO_TRIS TRISB,2
//*****************
//* VARIABLES *
//*****************
#BYTE TRISA = 0x85 // Dirección de los TRIS.
#BYTE TRISB = 0x86
#BYTE INTCON = 0x10B // Registro de interrupciones. Sólo es importante el bit 7, GIE=interrupciones globales.
//Variables internas
static int1 interRF;
static int16 noRF;
static int1 RCVNW=0;
static int8 DATA_N_SND=0;
static int8 DATA_N_RCV=0;
//Variables configurables
static int8 RF_DATA[8];
static int8 RF_DIR;
//**************
//* CÓDIGO *
//**************
//*****************************************************
//* RF_CONFIG_SPI() *
//*****************************************************
//*Descripción: La función configura el módulo SPI del*
//*microcontrolador.En ella se especifica como salida *
//*SDO y como entrada SDI entre otros parámetros del *
//*protocolo SPI. *
//*****************************************************
//*Variables de entrada: *
//*Variables de salida: *
//*****************************************************
void RF_CONFIG_SPI()
{
//Configuración I/O.
bit_clear(SCK_TRIS);
bit_set(SDI_TRIS);
bit_clear(SDO_TRIS);
//Configuración módulo comunicaciones.
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4|SPI_SAMPLE_AT_END);
}
//*****************************************************
//*****************************************************
//* RF_INT_EN() *
//*****************************************************
//*Descripción:Se encarga de habilitar la interrupción*
//*externa (RB0) utilizada por el módulo de RF en la *
//*recepción de datos. *
//*****************************************************
//*Variables de entrada: *
//*Variables de salida: *
//*****************************************************
void RF_INT_EN()
{
//Habilitar interrupciones externas con flanco de
//bajada.
disable_interrupts(global);
enable_interrupts(int_ext);
ext_int_edge( H_TO_L );
bit_set(RF_IRQ_TRIS);
enable_interrupts(global);
}
//*****************************************************
//*****************************************************
//* RF_CONFIG(int canal, int dir) *
//*****************************************************
//*Descripción:Esta función se encarga de configurar *
//*el transceptor habilitando su propia dirección de *
//*escucha y el canal entre otros parámetros. *
//*****************************************************
//*Variables de entrada:- Canal *
//* - Direccion *
//*Variables de salida: *
//*****************************************************
void RF_CONFIG(int canal, int dir)
{
bit_clear(RF_CS_TRIS);
bit_set(RF_IRQ_TRIS);
bit_clear(RF_CE_TRIS);
output_low(RF_CE);
// TX_ADDR (0xFF)
//Configuración de la dirección de envío aleatoria.
//En la función de enviar se configura la dirección
//deseada por el usuario.
output_low(RF_CS);
spi_write(0x30);
spi_write(0xFF);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
output_high(RF_CS);
// RX_ADDR_P0 (0xFF) ACK
//Configuración de la direccióndel Pipe0 para la
//recepción de ACK.
output_low(RF_CS);
spi_write(0x2A);
spi_write(0xFF);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
output_high(RF_CS);
// RX_ADDR_P1 (dir)
//Configuración de la direccióndel Pipe1 para la
//recepción de tramas.
output_low(RF_CS);
spi_write(0x2B);
spi_write(dir);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
output_high(RF_CS);
// RX_ADDR_P2 (0x00) BROADCAST
//Configuración de la direccióndel Pipe2 para la
//recepción de tramas
output_low(RF_CS);
spi_write(0x2C);
spi_write(0x00);
output_high(RF_CS);
// EN_AA
//Habilitar AutoAck en los Pipe0,Pipe1 y Pipe2.
output_low(RF_CS);
spi_write(0x21);
spi_write(0x07);
output_high(RF_CS);
// EN_RXADDR
//Habilitar los Pipe0,Pipe1 y Pipe2.
output_low(RF_CS);
spi_write(0x22);
spi_write(0x07);
output_high(RF_CS);
// SETUP_AW
//Configuración de la longitud de las direcciones.
//Direcciones de 5 bytes.
output_low(RF_CS);
spi_write(0x23);
spi_write(0x03);
output_high(RF_CS);
//SETUP_RETR
//Configuración de las retrasmisiones en la transmisión.
//Diez retransmisiones cada 336us.
output_low(RF_CS);
spi_write(0x24);
spi_write(0x0A);
output_high(RF_CS);
//RF_CH
//Configuración del canal.
//Canal elegido por el usuario (0x01 - 0x7F).
output_low(RF_CS);
spi_write(0x25);
spi_write(canal);
output_high(RF_CS);
//RF_SETUP
//Configuración aspectos RF. *******************************************************************************************
//Ganancia máxima de LNA, 0dBm potencia de salida y 1Mbps de velocidad. ************************************************
output_low(RF_CS);
spi_write(0x26);
spi_write(0x07); // Lo he cambiado a 1Mbps. Originalmente era "0x0F" ----> (2Mbps).
output_high(RF_CS);
//STATUS
//Reseteo del registro STATUS
output_low(RF_CS);
spi_write(0x27);
spi_write(0x70);
output_high(RF_CS);
//RX_PW_P0
//Nº de bytes en Pipe0.
//1 byte (ACK).
output_low(RF_CS);
spi_write(0x31);
spi_write(0x01);
output_high(RF_CS);
//RX_PW_P1
//Nº de bytes en Pipe1.
//10 byte (Direccion emisor y trama).
output_low(RF_CS);
spi_write(0x32);
spi_write(0x0A);
output_high(RF_CS);
//RX_PW_P2
//Nº de bytes en Pipe2.
//10 byte (Direccion emisor y trama).
output_low(RF_CS);
spi_write(0x33);
spi_write(0x0A);
output_high(RF_CS);
}
//*****************************************************
//*****************************************************
//* RF_ON() *
//*****************************************************
//*Descripción:Esta rutina activa el módulo de *
//*radiofrecuencia en modo escucha para poder recibir *
//*datos enviados a su dirección. *
//*****************************************************
//*Variables de entrada: *
//*Variables de salida: *
//*****************************************************
void RF_ON()
{
}
//*****************************************************
//*****************************************************
//* RF_OFF() *
//*****************************************************
//*Descripción:Este procedimiento desactiva el módulo *
//*de radiofrecuencia. *
//*****************************************************
//*Variables de entrada: *
//*Variables de salida: *
//*****************************************************
void RF_OFF()
{
output_low(RF_CE);
// CONFIG
//Se desactiva el modulo
output_low(RF_CS);
spi_write(0x20);
spi_write(0x0C);
output_high(RF_CS);
}
//*****************************************************
//*****************************************************
//* RF_SEND() *
//*****************************************************
//*Descripción:Esta función envía 8 Bytes de datos a *
//*la dirección indicada informando de la correcta *
//*recepción en el destinatario. *
//*****************************************************
//*Variables de entrada:- RF_DATA[] *
//* - RF_DIR
//*Variables de salida: - *
//*Salida: - 0: Envío correcto (ACK OK) *
//* - 1: No recepcibido (NO ACK) *
//* - 2: No enviado *
//*****************************************************
int RF_SEND()
{
int i;
int estado;
if(bit_test(INTCON,7))
interRF=1;
else
interRF=0;
disable_interrupts(GLOBAL);
// INICIO
output_low(RF_CE);
//STATUS
//Reseteo del registro STATUS
output_low(RF_CS);
spi_write(0x27);
spi_write(0x70);
output_high(RF_CS);
// EN_RXADDR
//Se habilita el Pipe0 para la recepción del ACK
output_low(RF_CS);
spi_write(0x22);
spi_write(0x01);
output_high(RF_CS);
// TX_ADDR
//Se configura la dirección de transmisión=RF_DIR
output_low(RF_CS);
spi_write(0x30);
spi_write(RF_DIR);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
output_high(RF_CS);
// RX_ADDR_P0
//Para la recepción del ACK se debe configurar el Pipe0 con
//la misma dirección a trasmitir.
output_low(RF_CS);
spi_write(0x2A);
spi_write(RF_DIR);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
spi_write(0xC2);
output_high(RF_CS);
// RX_ADDR_P1
//Se mete en RF_DIR la direccion propia.
//De esta manera el receptor sabe la dirección
//del transmisor.
output_low(RF_CS);
spi_write(0x0B);
RF_DIR=spi_read(0);
spi_read(0);
spi_read(0);
spi_read(0);
spi_read(0);
output_high(RF_CS);
// W_TX_PAYLOAD
//Se manda los datos al transductor
output_low(RF_CS);
spi_write(0xA0);
DATA_N_SND++;
spi_write(DATA_N_SND);
spi_write(RF_DIR);
for (i=0;i<8;i++)
{
spi_write(RF_DATA[i]);
}
output_high(RF_CS);
// CONFIG
//Se pasa a modo transmisión.
output_low(RF_CS);
spi_write(0x20);
spi_write(0x0E);
output_high(RF_CS);
// Pulso de comienzo de envío
output_high(RF_CE);
delay_us(15);
output_low(RF_CE);
noRF=0;
while (input(RF_IRQ)==1) {
noRF++;
//Si no da respuesta en 7ms, no se ha enviado.
if(noRF==500) { break; }
}
// STATUS
//Lectura del estado en el registro estatus.
output_low(RF_CS);
estado=spi_read(0x27);
spi_write(0x70);
output_high(RF_CS);
// EN_RXADDR
//Habilitar los Pipe0,Pipe1 y Pipe2.
output_low(RF_CS);
spi_write(0x22);
spi_write(0x07);
output_high(RF_CS);
// TX_FLUSH
//Limpieza de la FIFO de salida
output_low(RF_CS);
spi_write(0xE1);
output_high(RF_CS);
// CONFIG
//Paso a modo recepción
output_low(RF_CS);
spi_write(0x20);
spi_write(0x0F);
output_high(RF_CS);
// FIN
output_high(RF_CE);
delay_us(150);
//Si no da respuesta en 7ms, no se ha enviado.
if(noRF==500)
{
if(interRF==1)
enable_interrupts(GLOBAL);
clear_interrupt(int_ext);
return(2);
}
//estado
//Chequeo de los bit del registro STATUS que indican si se ha recibido
//ACK y si se ha terminado las retrasmisiones sin ningun ACK.
if ((bit_test(estado,4)==0) && (bit_test(estado,5)==1)){
if(interRF==1)
enable_interrupts(GLOBAL);
clear_interrupt(int_ext);
return(0);
}
else{
if(interRF==1)
enable_interrupts(GLOBAL);
clear_interrupt(int_ext);
return(1);
}
}
//*****************************************************
//*****************************************************
//* RF_RECEIVE() *
//*****************************************************
//*Descripción: Esta rutina se encarga de comprobar si*
//*se ha producido una recepción y de ser así, *
//*devuelve la trama recibida. *
//*****************************************************
//*Variables de entrada:- *
//*Variables de salida: - RF_DATA[] *
//* - RF_DIR *
//*Salida: - 0: Recepción correcta y única *
//* - 1: Recepción correcta y múltiple *
//* - 2: No se ha producido recepción *
//* - 3: No se ha producido recepción *
//*****************************************************
int RF_RECEIVE()
{
int i;
int mas;
int estado;
if (input(RF_IRQ)==1 && RCVNW==0){
return (2);
}
//STATUS
//Lectura y reseteo del registro STATUS
output_low(RF_CS);
estado=spi_read(0x27);
spi_write(0x70);
output_high(RF_CS);
//estado
//Chequeo de la interrupción de recepción.
if (bit_test(estado,6)==0 && RCVNW==0){
return(3);
}
//R_RX_PAYLOAD
//Lectura de los datos recibidos.
output_low(RF_CS);
spi_write(0x61);
DATA_N_RCV=spi_read(0);
RF_DIR=spi_read(0);
for (i=0;i<8;i++)
{
RF_DATA[i]=spi_read(0);
}
output_high(RF_CS);
//FIFO_STATUS
//Comprobación del estado de la FIFO de
//recepción para comprobar si hay más datos
output_low(RF_CS);
spi_write(0x17);
mas=spi_read(0);
output_high(RF_CS);
if (bit_test(mas,0)==0){
RCVNW=1;
return(1);
}
RCVNW=0;
return(0);
}
//****************************************************
claro, porque estás utilizando la función delay_xx antes de configurar el reloj de temporización.
debes incluir la libreria despues,Código: C[/code]
[code]#include <16F88.h> #fuses XT //Oscilador a cristal standar #fuses NOWDT //sin WatchDog Timer #fuses NOPROTECT //sin proteccion de memoria de programa #fuses PUT //sin PowerUp Timer #fuses NOBROWNOUT //sin brownout #fuses NOLVP //sin programación en baja tensión #use delay(clock=4000000) #include "PIC16F88E.h" // Librería modificada para el el nRF24L01 con el PIC 16F88. ...