Advertisement
Guest User

NRF Receiver

a guest
Apr 19th, 2014
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.82 KB | None | 0 0
  1. #define F_CPU 7372800UL   // 8 MHz
  2.  
  3. /* 9600 baud */
  4. #define UART_BAUD_RATE  4800
  5.  
  6. #define DataLen 5   // length of data packet sent / received
  7.  
  8. #define CSN_PIN 4
  9. #define CE_PIN  3
  10.  
  11. #include <avr/io.h>
  12. #include <stdio.h>
  13. #include <util/delay.h>
  14. #include <avr/interrupt.h>
  15.  
  16. #include "uart.h"
  17. #include "nRF24L01.h"
  18. //#include "lcd.h"
  19.  
  20. uint8_t *data;
  21.  
  22. char buffer[7];
  23.  
  24.  
  25. /***************** SPI *****************************/   // Sending data between the chip and the chip nrf'ens
  26. // Initialization
  27. void  InitSPI ( void )
  28. {
  29.     // Set SCK (PB5), MOSI (PB3), CSN (SS & PB2) & C as outport
  30.     // NOTE! Must be set before the SPI Enable neadn
  31.     DDRB |= (1<<DDB7 ) | ( 1 << DDB5 ) | ( 1 << DDB4 ) | ( 1 << DDB3 );
  32.    
  33.     /* Enable SPI, Master, set clock rate fck/16 .. can change the speed but it does so much */
  34.     SPCR |= ( 1 << SPE ) | ( 1 << MSTR ); // | (1 << SPR0) | (1 << SPR1);
  35.    
  36.     SETBIT ( PORTB ,CSN_PIN);   // CSN IR_High to start with, we will not send anything to nrf'en yet!
  37.     CLEARBIT ( PORTB , CE_PIN );    // CE low to start with, nrf'en will not send / receive anything yet!
  38. }
  39.  
  40. // Send command to nrf'en on then get back a byte
  41. char  WriteByteSPI ( unsigned  char  CDATA )
  42. {
  43.     // Load Byte to Data register
  44.     SPDR  =  CDATA ;
  45.    
  46.     /* Wait for transmission complete */
  47.     while (!(SPSR & (1<<SPIF)));
  48.    
  49.     // Return what was sent back by nrf'en (first time after csn-low will Statusregistert)
  50.     return SPDR ;
  51. }
  52.  
  53. void ioinit(){
  54.    
  55. }
  56.  
  57. // When data is received / sent as goes interr uptet INT0 second-bottom running
  58. void  INT0_interrupt_init ( void )
  59. {
  60.     DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
  61.     // PD2 (INT0 pin) is now an input
  62.  
  63.     ////PORTD |= (1 << PORTD2);    // turn On the Pull-up
  64.     // PD0 is now an input with pull-up enabled
  65.    
  66.     MCUCR |=(1<<ISC01); // INT0 falling edge PD2
  67.     MCUCR &=~(1<<ISC00); // INT0 falling edge PD2
  68.    
  69.     GICR |=(1<<INT0);   // enablar int0
  70.     sei (); // Enable global interrupts are then
  71. }
  72.  
  73. uint8_t *WriteToNrf(uint8_t ReadWrite,uint8_t reg,uint8_t *val,uint8_t antVal)  // takes in "ReadWrite" (W el R), "reg" (a record), "* Choice" (an array) & "antVal" (number integer in the variable)
  74. {
  75.     //"ReadWrite" ("W" or "R"), "reg" (the register), "*val" (an array with the package) & "antVal" (number of integers in the package)
  76.     ////cei();
  77.    
  78.     if(ReadWrite == W)  // W = want to write to nrf-one (R = read of it, R_REGISTER (0x00), so do not care one else function)
  79.     {
  80.         reg=W_REGISTER + reg;   // example: reg = EN_AA: 0b0010 0000 + 0001 = 0b0000 0b0010 0001
  81.     }
  82.    
  83.     // Static uint8_t for it to go to return an array (note the "*" on the top tool!)
  84.     static uint8_t ret[32];     // assume that the longest you want to read when they call the "R" is dataleng-far, that uses only 1 byte datalengd the want to read out 5bytes RF_Adress so write 5 here ist!
  85.    
  86.     _delay_us(10);      // all the delay is such that the NRF will manage! (Micro seconds)
  87.     CLEARBIT(PORTB,CSN_PIN);    // CSN low = nrf chip starts listening
  88.     _delay_us(10);
  89.     WriteByteSPI(reg);  // first SPI command after CSN was telling nrf'en which of its records to be edited as: 0b0010 0001 write to registry EN_AA
  90.     _delay_us(10);
  91.    
  92.     int  i;
  93.     for (i=0;i<antVal;i++)
  94.     {
  95.         if  (ReadWrite == R && reg!= W_TX_PAYLOAD)
  96.         {
  97.             ret[i]=WriteByteSPI(NOP);   // other and the rest of the SPI command tells the NRF which values ??in this case should be read
  98.             _delay_us(10);
  99.         }
  100.         else
  101.         {
  102.             WriteByteSPI(val[i]);   // other and the rest of the SPI command tells the NRF which values ??in this case should be written to
  103.             _delay_us(10);
  104.         }
  105.     }
  106.     SETBIT(PORTB,CSN_PIN);  // CSN IR_High = nrf chip stop listening
  107.    
  108.     ////sei();  // enable global interrupt
  109.    
  110.     return ret;     // returns an array
  111. }
  112.  
  113. // Resets nrf'en for new communication
  114. void reset(void)
  115. {
  116.     _delay_us(10);
  117.     CLEARBIT(PORTB,CSN_PIN);    // CSN Low
  118.     _delay_us(10);
  119.     WriteByteSPI(W_REGISTER + STATUS);  //
  120.     _delay_us(10);
  121.     WriteByteSPI(0x70);     // conditioned pulls all interrupts in the status register (to be able to listen again)
  122.     _delay_us(10);
  123.     SETBIT(PORTB,CSN_PIN);  // CSN IR_High
  124. }
  125.  
  126. //Function to retrieve some thing of nrf's records
  127. uint8_t GetReg(uint8_t reg)
  128. {
  129.     // Internal uses: USART_Transmit (GetReg (STATUS)); // Where the status of the registry to Check
  130.     _delay_us(10);
  131.     CLEARBIT (PORTB,CSN_PIN);   // CSN Low
  132.     _delay_us(10);
  133.     WriteByteSPI(R_REGISTER+reg);   // Which registry would you like to read (now with R_Register because nothing will be written to register)
  134.     _delay_us(10);
  135.     reg=WriteByteSPI(NOP);  // Send NOP number of bytes you want to download (usually 1gång, but eg addr is 5 bytes!) and save isf not in the "reg", but an array using a loop
  136.     _delay_us(10);
  137.     SETBIT(PORTB,CSN_PIN);  // CSN IR_High
  138.     return  reg;    // Returns the registry hopefully with bit5 = 1 (tx_ds = successful transmission)
  139. }
  140.  
  141. // Initialize nrf'en (note the NRF must vala to sleep when this happens CE low)
  142. void nrf24L01_init(void)
  143. {
  144.     _delay_ms(100);     // allow the radio to reach power-down if the shutdown
  145.     uint8_t val[5];     // an array of integers that sends values ??to WriteToNrf function
  146.    
  147.     //EN_AA - (enable auto-acknowledgments) - Transmitter gets automatic response from receiver when successful transmission! (lovely function!)
  148.     //Only works if Transmitter has identical RF_Adress on its channel ex: RX_ADDR_Po = TX_ADDR
  149.     val[0]=0x01; //set value
  150.     WriteToNrf(W, EN_AA, val, 1); //N=write mode, EN_AA=register to write to, val=data to write, 1=number of data bytes.
  151.    
  152.     //Choose number of enabled data pipes (1-5)
  153.     val[0]=0x01;
  154.     WriteToNrf(W, EN_RXADDR, val, 1); //enable data pipe 0
  155.  
  156.     //RF_Adress width setup (how many bytes is the receiver address, the more the merrier 1-5)
  157.     val[0]=0x03; //0b0000 00011 = 5 bytes RF_Adress
  158.     WriteToNrf(W, SETUP_AW, val, 1);
  159.  
  160.     // RF channel setup - select the frequency from 2.400 to 2.527 GHz 1MHz/steg
  161.     val[0]=0x01;
  162.     WriteToNrf(W,RF_CH,val,1);  // RF channel registry 0b0000 0001 = 2.401 GHz (same on the TX RX)
  163.  
  164.     //RF setup - choose power mode and data speed. Here is the diference with the (+) version!!!
  165.     val[0]=0x27; //00000111 bit 3="0" 1Mbps=longer range, bit 2-1 power mode ("11" = -odB ; "00"=-18dB)
  166.     WriteToNrf(W, RF_SETUP, val, 1);
  167.  
  168.     //RF_Adress setup 5 byte - Set Receiver address (set RX_ADDR_Po = TX_ADDR if EN_AA is enabled!!!)
  169.     int i=0;
  170.     for(i=0; i<5; i++){
  171.         val[i]=0x11; //ox12 x 5 to get a long and secure address.
  172.     }
  173.     //----------WriteToNrf(W, RX_ADDR_P0, val, 5); //since we chose pipe 0 on EN_RXADDR we give this address to that channel.
  174.     //Here you can give different addresses to different channels (if they are enabled in EN_RXADDR) to listen on several different transmitters)
  175.    
  176.     //TX RF_Adress setup 5 byte - Set Transmitter address (not used in a receiver but can be set anyway)
  177.     for(i=0; i<5; i++){
  178.         val[i]=0x11; //ox12 x 5 - same on the Receiver chip and the RX-RF_Address above if EN_AA is enabled!!!
  179.     }
  180.     //----------WriteToNrf(W, TX_ADDR, val, 5);
  181.  
  182.     //Payload width Setup - 1-32byte (how many bytes to send per transmission)
  183.     val[0]=0x05; //Send 5 bytes per package this time (same on receiver and transmitter)
  184.     WriteToNrf(W,RX_PW_P0,val,1);
  185.  
  186.     val[0]=0x2F; //0b00l0 00011 "2" sets it up to 7SouS delay between every retry (at least Seeus at 25okbps and if payload >5bytes in 1Hbps,
  187.     //and if payload >1Sbyte in 2Hbps) "F" is number of retries (1-15, now 15)
  188.     WriteToNrf(W, SETUP_RETR, val, 1);
  189.  
  190.     //CONFIG reg setup - Now it's time to boot up the Qgf and choose if it's suppose to be a transmitter or receiver
  191.     val[0]=0x1F; //0b0001 1110 - bit 0="0":transmitter bit 0="1":Receiver, bit 1="1"=power up,
  192.     //bit 4="1"= mask_Max_RT i.e. IRQ-interrupt is not triggered if transmission failed.
  193.     WriteToNrf(W, CONFIG, val, 1);
  194.  
  195.     //device need 1.5ms to reach standby mode (CE=low)
  196.     _delay_ms(100);
  197.  
  198.     // Sei ();
  199. }
  200.  
  201. // The receiver opens and "Listening" in 1s
  202. void  receive_payload ( void )
  203. {
  204.     //sei();        // Enable global interrupt
  205.    
  206.     SETBIT(PORTB,CE_PIN);   // CE IR_High = "Listening"
  207.     _delay_ms(1000);    // listening in 1s and received goes int0-interruptvektor Started
  208.     CLEARBIT(PORTB,CE_PIN);  // ce low back-stop listening
  209.    
  210.     //cli();    // Disable the global interrupt
  211. }
  212.  
  213. // Send the data
  214. void transmit_payload( uint8_t  *W_buff)
  215. {
  216.     WriteToNrf(R,FLUSH_TX,W_buff,0);  // send 0xE1 which flushes the registry to old data should not be on the wait to be sent when you want to send the new data! R stands for W_REGISTER not be added. sends no command efterråt because it is not needed! W_buff [] is just there to an array has to be there ...
  217.     WriteToNrf(R,W_TX_PAYLOAD,W_buff,DataLen);  // send data in W_buff to nrf-one (note can not be read w_tx_payload registry!)
  218.    
  219.     //sei();    // enable global interrupt already!
  220.     // USART_Transmit (GetReg (STATUS));
  221.    
  222.     _delay_ms(10);      // need to be really ms, not us?? YEEES! otherwise it will not work!
  223.     SETBIT(PORTB,CE_PIN);   // CE high = send data INT0 interruptet running when the transmission was successful and if EN_AA is on, also the response of the receiver is received
  224.     _delay_us ( 20 );       // at least 10us!
  225.     CLEARBIT(PORTB,CE_PIN);     // CE low
  226.     _delay_ms(10);      // need to be really ms, not us?? YEEES! otherwise it will not work!
  227.    
  228.     // Cli (); // Disable the global interrupt ... ajabaja, then closes USART_RX-listening to!
  229.    
  230. }
  231.  
  232. int main(void)
  233. {
  234.     ////lcd_init(LCD_DISP_ON);
  235.     ////lcd_puts("LCD init");
  236.     _delay_ms(500);
  237.     ////lcd_clrscr();
  238.    
  239.     InitSPI();
  240.     ////lcd_puts("SPI init");
  241.     _delay_ms(500);
  242.     ////lcd_clrscr();
  243.    
  244.     ioinit();
  245.     INT0_interrupt_init();
  246.     ////lcd_puts("INT0 init");
  247.     _delay_ms(500);
  248.     ////lcd_clrscr();
  249.    
  250.     nrf24L01_init();
  251.     ////lcd_puts("NRF init");
  252.     _delay_ms(500);
  253.     ////lcd_clrscr();
  254.    
  255.     uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
  256.     ////lcd_puts("USART init");
  257.     _delay_ms(500);
  258.     ////lcd_clrscr();
  259.    
  260.     //sei();
  261.    
  262.     //Clear the screen
  263.     ////lcd_clrscr();
  264.    
  265.    
  266.     char buffer[5];
  267.    
  268.     uart_puts("EA_AA:");
  269.     itoa( GetReg(EN_AA), buffer, 16);   // convert interger into string (decimal format)
  270.     uart_puts(buffer);        // and transmit string to UART
  271.     uart_puts("\n");
  272.    
  273.     uart_puts("EN_RXADDR:");
  274.     itoa( GetReg(EN_RXADDR), buffer, 16);   // convert interger into string (decimal format)
  275.     uart_puts(buffer);        // and transmit string to UART
  276.     uart_puts("\n");
  277.    
  278.     uart_puts("SETUP_AW:");
  279.     itoa( GetReg(SETUP_AW), buffer, 16);   // convert interger into string (decimal format)
  280.     uart_puts(buffer);        // and transmit string to UART
  281.     uart_puts("\n");
  282.    
  283.     uart_puts("RF_CH:");
  284.     itoa( GetReg(RF_CH), buffer, 16);   // convert interger into string (decimal format)
  285.     uart_puts(buffer);        // and transmit string to UART
  286.     uart_puts("\n");
  287.    
  288.     uart_puts("RF_SETUP:");
  289.     itoa( GetReg(RF_SETUP), buffer, 16);   // convert interger into string (decimal format)
  290.     uart_puts(buffer);        // and transmit string to UART
  291.     uart_puts("\n");
  292.    
  293.     uart_puts("RX_ADDR_P0:");
  294.     itoa( GetReg(RX_ADDR_P0), buffer, 16);   // convert interger into string (decimal format)
  295.     uart_puts(buffer);        // and transmit string to UART
  296.     uart_puts("\n");
  297.    
  298.     uart_puts("TX_ADDR:");
  299.     itoa( GetReg(TX_ADDR), buffer, 16);   // convert interger into string (decimal format)
  300.     uart_puts(buffer);        // and transmit string to UART
  301.     uart_puts("\n");
  302.    
  303.     uart_puts("RX_PW_P0:");
  304.     itoa( GetReg(RX_PW_P0), buffer, 16);   // convert interger into string (decimal format)
  305.     uart_puts(buffer);        // and transmit string to UART
  306.     uart_puts("\n");
  307.    
  308.     uart_puts("SETUP_RETR:");
  309.     itoa( GetReg(SETUP_RETR), buffer, 16);   // convert interger into string (decimal format)
  310.     uart_puts(buffer);        // and transmit string to UART
  311.     uart_puts("\n");
  312.    
  313.     uart_puts("CONFIG:");
  314.     itoa( GetReg(CONFIG), buffer, 16);   // convert interger into string (decimal format)
  315.     uart_puts(buffer);        // and transmit string to UART
  316.     uart_puts("\n");
  317.  
  318.    
  319.     //uint8_t buffer[5];
  320.     //  SETBIT(PORTB,1);    // CE IR_High = "Listening"
  321.    
  322.     while(1){
  323.         reset();
  324.         receive_payload();
  325.  
  326.         if ((GetReg(STATUS)&(1<<RX_DR))!=0)
  327.         {
  328.             data=WriteToNrf(R, R_RX_PAYLOAD, data, 1);
  329.             uart_puts("Data Received\n");
  330.            
  331.             uart_putc(data[0]);
  332.         }else{
  333.            
  334.             uart_puts("STATUS:");
  335.             itoa( GetReg(STATUS), buffer, 16);   // convert interger into string (decimal format)
  336.             uart_puts(buffer);        // and transmit string to UART
  337.             uart_puts("\t");
  338.         }
  339.         _delay_ms(1000);
  340.     }
  341.    
  342.     return 0;
  343. }
  344.  
  345.  
  346.  
  347.  
  348. ISR(INT0_vect)  // vector that is triggered when transmit_payload managed to send or when receive_payload received data NOTE: when Mask_Max_rt is set in the config register so it will not go off when MAX_RT is was reached on the mailing lodge nmisslyckats!
  349. {
  350.     cli();  // Disable the global interrupt
  351.     CLEARBIT(PORTB ,CE_PIN);        // ce low back-stop listening / transmitting
  352.    
  353.     uart_puts("In ISR(INT0_vect)");
  354.     // Receiver function to print out on usart:
  355.     data = WriteToNrf (R, R_RX_PAYLOAD, data, DataLen); // Read the received data
  356.     reset();
  357.     for (int i = 0; i <DataLen; i++)
  358.     {
  359.         uart_putc(data[i]);
  360.         ////lcd_putc(data[i]);
  361.     }
  362.     sei();
  363. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement