Home › Forum › FORUM ELETTRONICA › MICROCONTROLLORI E CODICI › Problema comunicazione NRF24L01+ › Rispondi a: Problema comunicazione NRF24L01+
21 Gennaio 2018 alle 14:54 #4306
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 }
