Rispondi a: Problema comunicazione NRF24L01+

Home Forum FORUM ELETTRONICA MICROCONTROLLORI E CODICI Problema comunicazione NRF24L01+ Rispondi a: Problema comunicazione NRF24L01+

#4306
Led_ON
Partecipante

CODICE TRASMETTITORE: (provo a vedere se riesco a postare)


sbit RF_CS_TRIS at TRISB3_bit;       //PIN CHIP SELECT
sbit RF_CE_TRIS at TRISB2_bit;       //PIN ENABLE
sbit SCK_TRIS at TRISB1_bit;         //CLK SPI
sbit SDI_TRIS at TRISB0_bit;         //DATA IN
sbit SDO_TRIS at TRISB5_bit;         //DATA OUT
//----------------------------------------------------------------------------------------------------------------------------//
sbit SS_pin at RB3_bit;
sbit CE_pin at RB2_bit;
sbit SCK_pin at RB1_bit;
sbit MOSI_pin at RB5_bit;
sbit MISO_pin at RB0_bit;
//----------------------------------------------------------------------------------------------------------------------------//
sbit Led at RB4_bit;                 //LED INDICAZIONE
//----------------------------------------------------------------------------------------------------------------------------//
#define R_REGISTER_cmd                0x00           //COMANDO DI SCRITTURA
#define W_REGISTER_cmd                0x20           //COMANDO DI LETTURA
#define R_RX_PL_WID_cmd               0x60           //LEGGI DIMENSIONE PAYLOAD
#define R_RX_PAYLOAD_cmd              0x61           //LEGGI PAYLOAD RICEVUTO
#define W_TX_PAYLOAD_cmd              0xA0           //SCRIVI PAYLOAD
#define W_ACK_PAYLOAD_cmd             0xA8           //ACK DEL PAYLOAD
#define W_TX_PAYLOAD_NO_ACK_cmd       0xB0           //DISABILITA AUTO ACK
#define FLUSH_TX_cmd                  0xE1           //SVUOTA LA FIFO DEL TX
#define FLUSH_RX_cmd                  0xE2           //SVUOTA LA FIFO DELL'RX
#define REUSE_TX_PL_cmd               0xE3           //RIUTILIZZA ULTIMO PAYLOAD INVIATO
#define NOP_cmd                       0xFF           //NESSUN COMANDO
//----------------------------------------------------------------------------------------------------------------------------//
#define CONFIG_reg                    0b00000000     //INTERRUPT , CRC, ON/OFF, TX MODE SETTING
#define EN_AA_reg                     0x01           //AUTO ACK PIPE
#define EN_RXADDR_reg                 0x02           //ABILITAZIONE INDIRIZZI RX
#define SETUP_AW_reg                  0x03           //NUMERO DI INDIRIZZI (5)
#define SETUP_RETR_reg                0x04           //SETTING TEMPO DI RITRASMISSIONE (250uS)
#define RF_CH_reg                     0x05           //CANALE 5
#define RF_SETUP_reg                  0b00000110     //{b5-b3 => (00 1Mbps),(01 2Mbps), (10 250Kbps)} {b2:b1 => (00 -18dBm), (01 -12dBm), (10 -6dBm), (11 0dBm)}
#define STATUS_reg                    0x07           //REGISTRO DI STATO, INVIATO AL PIN MOSI
#define OBSERVE_TX_reg                0x08           //CONTA I LOST PACKET E I RETRASMITTED PACKET
#define RPD_reg                       0x09           //AVVERTE SE VI è UN TRASMETTITORE ATTIVO
#define RX_ADDR_P0_reg                0x0A           //RICEVE L'INDIRIZZO 0
#define RX_ADDR_P1_reg                0x0B           //
#define RX_ADDR_P2_reg                0x0C           //
#define RX_ADDR_P3_reg                0x0D           //
#define RX_ADDR_P4_reg                0x0E           //
#define RX_ADDR_P5_reg                0x0F           //
#define TX_ADDR_reg                   0x10           //TRASMISSIONE INDIRIZZI
#define RX_PW_P0_reg                  0x11           //NUMERO DI BYTE DEL PAYLOAD NEL DATA PIPE 0
#define RX_PW_P1_reg                  0x12           //
#define RX_PW_P2_reg                  0x13           //
#define RX_PW_P3_reg                  0x14           //
#define RX_PW_P4_reg                  0x15           //
#define RX_PW_P5_reg                  0x16           //
#define FIFO_STATUS_reg               0x17           //RIUTILIZZA TRASMISSIONE E STATO DELLA FIFO
#define DYNPD_reg                     0x1C           //ENABLE DYNAMIC PAYLOAD LENGHT
#define FEATURE_reg                   0x1D           //ABILITAZIONE MODALITà DYPLD, ACK, NO ACK

//----------------------------------------------------------------------------------------------------------------------------//
unsigned char x = 0;                                 //CONTIENE IL BYTE DA INVIARE

//----------------------------------------------------------------------------------------------------------------------------//
unsigned char nRF24L01_read()                        //questo sottoprogramma simula una comunicazione SPI
{
  unsigned char s = 0;                               //variabile per esegguire 8 esecuzioni
  unsigned char msg = 0;

  for(s = 0; s < 8; s++){                            //esegue 8 volte
      msg <<= 1;                                     //shifto msg
      SCK_pin = 1;                                   //attivo il clock
      delay_us(8);                                   //aspetto 8us (f spi 62Kbps)
      if(MISO_pin != 0)                              //se in=0
      {
        msg |= 1;                                    //azzero il bit di msg
      }
      SCK_pin = 0;                                   //disattivo il clock
      delay_us(8);
  }

  return msg;                                       //ritorno il valore letto
}

//----------------------------------------------------------------------------------------------------------------------------//
void nRF24L01_write(unsigned char d){                //sottoprogramma che simula una scrittura spi
  unsigned char s = 0;

  for(s = 0; s < 8; s++)                            //questo for serve a trasmettere sul pin mosi bit per bit il dato d
  {
    if((d & 0x80) != 0)
    {
      MOSI_pin = 1;                                 //se il bit scandito è 1 trasmetto 1
    }
    else
    {
      MOSI_pin = 0;                                 //altrimenti 0
    }
    d <<= 1;                                        //shifto d per inviare il prossimo bit
    SCK_pin = 1;                                    //creo un clock
    delay_us(8);
    SCK_pin = 0;
    delay_us(8);
  }
}

//----------------------------------------------------------------------------------------------------------------------------//
void register_write(unsigned char reg, unsigned char value)                //sottoprogramma per scrivere i registri
{
  SS_pin = 0;                                                              //indico che sto per inviare un comando
  nRF24L01_write((reg | W_REGISTER_cmd));                                  //maschero il registro con il comando per scrivere
  nRF24L01_write(value);                                                   //invio il valore che voglio scrivere nel registro
  SS_pin = 1;
  delay_us(8);
}

//----------------------------------------------------------------------------------------------------------------------------//
void write_command(unsigned char cmd) {                                    //sottoprogramma scrittura comandi
  SS_pin = 0;                                                              //indico che voglio inviare un comando
  nRF24L01_write(cmd);                                                     //scrivo il comando cmd
  SS_pin = 1;                                                              //ripristino il pin ss
  delay_us(8);
}

//----------------------------------------------------------------------------------------------------------------------------//
unsigned char register_read(unsigned char reg)                            //sottoprogramma lettura registri
{
  unsigned char value = 0;

  SS_pin = 0;
  nRF24L01_write((reg | R_REGISTER_cmd));                                 //indico che voglio leggere e quale registro leggere
  value = nRF24L01_read();                                                //leggo il dato che il modulo mi manda
  SS_pin = 1;
  delay_us(8);

  return value;
}

//----------------------------------------------------------------------------------------------------------------------------//
void set_TX_RX_address(unsigned char *addr, unsigned char bytes, unsigned char reg)      //sottoprogramma per scrivere gli indirizzi
{
  unsigned char n = 0;

  SS_pin = 0;
  nRF24L01_write((reg | W_REGISTER_cmd));                                               //indico che voglio scrivere i registri
  for(n = 0; n < bytes; n++)
  {
    nRF24L01_write(addr[n]);                                                            //bytes contiene il numero di indirizzi
  }                                                                                     //scrivo gli n indirizzi
  SS_pin = 1;
  delay_us(8);
}

//----------------------------------------------------------------------------------------------------------------------------//
void flush_TX_RX()                                      //sottoprogramma per cancellare le FIFO
{
  register_write(STATUS_reg, 0x70);
  write_command(FLUSH_TX_cmd);
  write_command(FLUSH_RX_cmd);
}

//----------------------------------------------------------------------------------------------------------------------------//
void send_data(unsigned char bytes, unsigned char *value)        //sottoprogramma per inviare i dati
{
  unsigned char s = 0;

  flush_TX_RX();                                                //cancello le FIFO
  register_write(CONFIG_reg, 0x3A);                             //setto la modalità tx da CONFIG_reg e attivo il modulo

  SS_pin = 0;
  nRF24L01_write(W_TX_PAYLOAD_cmd);                             //scrivo nel registo di trasmissione i bit da inviare
  for(s = 0; s < bytes; s++)
  {
    nRF24L01_write(value[s]);
  }
  SS_pin = 1;
  delay_us(8);

  CE_pin = 1;                                                 //faccio partire l'invio, aspetto 60us e poi disattivo il modulo
  delay_us(60);
  CE_pin = 0;

  register_write(CONFIG_reg, 0x38); //En modo RX se quita
}

//----------------------------------------------------------------------------------------------------------------------------//
void receive_data(unsigned char bytes, unsigned char *value)         //sottoprogramma per la ricezione, indico il numero di bytes del dato
{                                                                    //value contiene il dato letto
  unsigned char s = 0;

  SS_pin = 0;                                                        //scrivo il comando che indica che voglio leggere
  nRF24L01_write(R_RX_PAYLOAD_cmd);
  for (s = 0; s < bytes; s++)
  {
    value[s] = nRF24L01_read();                                      //leggo il dato che il modlo mi sta inviando
  }
  SS_pin = 1;
  delay_us(8);
}

//----------------------------------------------------------------------------------------------------------------------------//
void nrF24L01_init_TX()                                             //sottoprogramma per settare la modalità trasmissione
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};        //indirizzo a 5bytes con valore a piacere(devo coincidere però con il rx)

  CE_pin = 0;

  register_write(SETUP_RETR_reg, 0x00);                             //ritrasmissione disabilitata
  register_write(SETUP_AW_reg, 0x03);                               //setto che ho indirizzo a 5bytes
  register_write(RF_SETUP_reg, 0x0E);                               //potenza 0dbm e velocità 250Kbps
  register_write(RF_CH_reg, 0x09);                                  //setto il canale di trasmissione, canale 9 in questo caso(il ricevitore deve avere uguale canale)
  register_write(EN_AA_reg, 0x00);                                  //auto ack disabilitato
  register_write(CONFIG_reg, 0x38);                                 //interrupt abilitati su TX_DS e MAX_RT, crc abilitato
  set_TX_RX_address(address, 5, TX_ADDR_reg);                       //inserisco gli indirizzi nell'apposito registro
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();                                                    //cancella le fifo

  CE_pin = 1;
}

//----------------------------------------------------------------------------------------------------------------------------//
void nrF24L01_init_RX()                                             //programma per settare la modalità RX
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};        //indirizzo a 5bytes uguale a quello del TX

  CE_pin = 0;

  register_write(CONFIG_reg, 0x38);                                 //Crc abilitato, no interrup di ricezione
  register_write(SETUP_RETR_reg, 0x00);                             //ritrasmissione non richiesta
  register_write(SETUP_AW_reg, 0x03);                               //indirizzo a 5bytes
  register_write(RF_SETUP_reg, 0x0E);                               //potenza 0dbm e velocità 250Kbps
  register_write(RF_CH_reg, 0x09);                                  //canale9
  register_write(EN_AA_reg, 0x00);                                  //no ack
  register_write(RX_PW_P0_reg, 0x01);                               //dato a 1byte
  register_write(CONFIG_reg, 0x3B);                                 //setto il modulo come RX
  set_TX_RX_address(address, 5, TX_ADDR_reg);                       //scrivo gli indirizzi nell'apposito registro
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();                                                    //cancello le fifo

  CE_pin = 1;
}

//----------------------------------------------------------------------------------------------------------------------------//
unsigned char get_Status_Reg()                       //sottoprogramma per leggere lo status register che mi fornisce info sul modulo
{
  return register_read(STATUS_reg);
}

//----------------------------------------------------------------------------------------------------------------------------//

void main(){                                        //programma principale

 TRISA     =  0x00;                                 //setto in e output e inizializzo le uscite a 0
 TRISB     =  0x00;                                 //indicare solo le porte disponibile sul microcontrollore
 TRISC     =  0x00;
 PORTA = 0X00;
 PORTB = 0X00;
 PORTC = 0x00;

//----------------------------------------------------------------------------------------------------------------------------//
 RF_CS_TRIS = 0;
 RF_CE_TRIS = 0;
 SCK_TRIS = 0;
 SDI_TRIS = 1;                                      //MISO
 SDO_TRIS = 0;                                      //MOSI

 CE_pin = 0;
 SS_pin = 0;
 SCK_pin = 0;
 MOSI_pin = 0;                                    //fine settaggio porte di comunicazione col modulo
 //----------------------------------------------------------------------------------------------------------------------------//

 delay_ms(10);

 nrF24L01_init_TX();                             //setto il modulo come TX

 delay_ms(100);                                  //delay di assestamento

 while(1){                                        //ciclo infinito
  x=10;                                //il dato lo prendo dall'adc (si può prendere da altre fonti)
  delay_ms(3000);                                //aspetto 3sec prima di un nuovo invio
  send_data(1, &x);                              //invio 1byte e il byte è la variabile x
  PORTC = x;                                     //visualizzo il dato inviato sul trasmettitore

 }