Страница 1 из 1

помогите портировать код nRF24L01 на аttiny84

Добавлено: Вт июн 17, 2014 20:09:25
vimax
всем привет!
помогите плиииз портировать код nRF24L01 на аttiny84
с мк занимаюсь не очень давно, подскажите что требуется изменить в этом коде
к сожалению требуется реализация именно на этом мк.
заранее признателен

rx.c
Спойлер

Код: Выделить всё

#define F_CPU 8000000UL   // 8 MHz

/* 9600 baud */
#define UART_BAUD_RATE   9600

#define DataLen 5   // length of data packet sent / received

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "uart.h"
#include "nRF24L01.h"
#include "lcd.h"

uint8_t *data;

/***************** SPI *****************************/   // Sending data between the chip and the chip nrf'ens
// Initialization
void  InitSPI ( void )
{
   // Set SCK (PB5), MOSI (PB3), CSN (SS & PB2) & C as outport
   // NOTE! Must be set before the SPI Enable neadn
   DDRB |= (1<<DDB5 ) | ( 1 << DDB3 ) | ( 1 << DDB2 ) | ( 1 << DDB1 );
   
   /* Enable SPI, Master, set clock rate fck/16 .. can change the speed but it does so much */
   SPCR |= ( 1 << SPE ) | ( 1 << MSTR );//  | (1 << SPR0) | (1 << SPR1);
   
   SETBIT(PORTB,2);    // CSN IR_High to start with, we will not send anything to nrf'en yet!
   CLEARBIT(PORTB,1);    // CE low to start with, nrf'en will not send / receive anything yet!
}

// Send command to nrf'en on then get back a byte
char  WriteByteSPI ( unsigned  char  CDATA )
{
   // Load Byte to Data register
   SPDR  =  CDATA ;
   
   /* Wait for transmission complete */
   while (!(SPSR & (1<<SPIF)));
   
   // Return what was sent back by nrf'en (first time after csn-low will Statusregistert)
   return SPDR ;
}

void ioinit(){
   
}

// When data is received / sent as goes interr uptet INT0 second-bottom running
void  INT0_interrupt_init ( void )
{
   DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
   // PD2 (INT0 pin) is now an input

   ////PORTD |= (1 << PORTD2);    // turn On the Pull-up
   // PD0 is now an input with pull-up enabled
   
   MCUCR |=(1<<ISC01); // INT0 falling edge PD2
   MCUCR &=~(1<<ISC00); // INT0 falling edge PD2
   
   GICR |=(1<<INT0);    // enablar int0
   sei (); // Enable global interrupts are then
}

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)
{
   //"ReadWrite" ("W" or "R"), "reg" (the register), "*val" (an array with the package) & "antVal" (number of integers in the package)
   ////cei();
   
   if(ReadWrite == W)    // W = want to write to nrf-one (R = read of it, R_REGISTER (0x00), so do not care one else function)
   {
      reg=W_REGISTER + reg;    // example: reg = EN_AA: 0b0010 0000 + 0001 = 0b0000 0b0010 0001
   }
   
   // Static uint8_t for it to go to return an array (note the "*" on the top tool!)
   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!
   
   _delay_us(10);       // all the delay is such that the NRF will manage! (Micro seconds)
   CLEARBIT(PORTB,2);    // CSN low = nrf chip starts listening
   _delay_us(10);
   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
   _delay_us(10);
   
   int  i;
   for (i=0;i<antVal;i++)
   {
      if  (ReadWrite == R && reg!= W_TX_PAYLOAD)
      {
         ret[i]=WriteByteSPI(NOP);    // other and the rest of the SPI command tells the NRF which values ??in this case should be read
         _delay_us(10);
      }
      else
      {
         WriteByteSPI(val[i]);    // other and the rest of the SPI command tells the NRF which values ??in this case should be written to
         _delay_us(10);
      }
   }
   SETBIT(PORTB,2);    // CSN IR_High = nrf chip stop listening
   
   ////sei();  // enable global interrupt
   
   return ret;    // returns an array
}

// Resets nrf'en for new communication
void reset(void)
{
   _delay_us(10);
   CLEARBIT(PORTB,2);    // CSN Low
   _delay_us(10);
   WriteByteSPI(W_REGISTER + STATUS);    //
   _delay_us(10);
   WriteByteSPI(0x70);    // conditioned pulls all interrupts in the status register (to be able to listen again)
   _delay_us(10);
   SETBIT(PORTB,2);    // CSN IR_High
}

//Function to retrieve some thing of nrf's records
uint8_t GetReg(uint8_t reg)
{
   // Internal uses: USART_Transmit (GetReg (STATUS)); // Where the status of the registry to Check
   _delay_us(10);
   CLEARBIT (PORTB,2);    // CSN Low
   _delay_us(10);
   WriteByteSPI(R_REGISTER+reg);    // Which registry would you like to read (now with R_Register because nothing will be written to register)
   _delay_us(10);
   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
   _delay_us(10);
   SETBIT(PORTB,2);    // CSN IR_High
   return  reg;    // Returns the registry hopefully with bit5 = 1 (tx_ds = successful transmission)
}

// Initialize nrf'en (note the NRF must vala to sleep when this happens CE low)
void nrf24L01_init(void)
{
   _delay_ms(100);    // allow the radio to reach power-down if the shutdown
   uint8_t val[5];    // an array of integers that sends values ??to WriteToNrf function
   
   //EN_AA - (enable auto-acknowledgments) - Transmitter gets automatic response from receiver when successful transmission! (lovely function!)
   //Only works if Transmitter has identical RF_Adress on its channel ex: RX_ADDR_Po = TX_ADDR
   val[0]=0x01; //set value
   WriteToNrf(W, EN_AA, val, 1); //N=write mode, EN_AA=register to write to, val=data to write, 1=number of data bytes.
   
   //Choose number of enabled data pipes (1-5)
   val[0]=0x01;
   WriteToNrf(W, EN_RXADDR, val, 1); //enable data pipe 0

   //RF_Adress width setup (how many bytes is the receiver address, the more the merrier 1-5)
   val[0]=0x03; //0b0000 00011 = 5 bytes RF_Adress
   WriteToNrf(W, SETUP_AW, val, 1);

   // RF channel setup - select the frequency from 2.400 to 2.527 GHz 1MHz/steg
   val[0] = 0x01 ;
   WriteToNrf(W,RF_CH,val,1);  // RF channel registry 0b0000 0001 = 2.401 GHz (same on the TX RX)

   //RF setup - choose power mode and data speed. Here is the diference with the (+) version!!!
   val[0]=0x27; //00000111 bit 3="0" 1Mbps=longer range, bit 2-1 power mode ("11" = -odB ; "00"=-18dB)
   WriteToNrf(W, RF_SETUP, val, 1);

   //RF_Adress setup 5 byte - Set Receiver address (set RX_ADDR_Po = TX_ADDR if EN_AA is enabled!!!)
   int i=0;
   for(i=0; i<5; i++){
      val[i]=0x11; //ox12 x 5 to get a long and secure address.
   }
   WriteToNrf(W, RX_ADDR_P0, val, 5); //since we chose pipe 0 on EN_RXADDR we give this address to that channel.
   //Here you can give different addresses to different channels (if they are enabled in EN_RXADDR) to listen on several different transmitters)
   
   //TX RF_Adress setup 5 byte - Set Transmitter address (not used in a receiver but can be set anyway)
   for(i=0; i<5; i++){
      val[i]=0x11; //ox12 x 5 - same on the Receiver chip and the RX-RF_Address above if EN_AA is enabled!!!
   }
   WriteToNrf(W, TX_ADDR, val, 5);

   //Payload width Setup - 1-32byte (how many bytes to send per transmission)
   val[0]=0x05; //Send 5 bytes per package this time (same on receiver and transmitter)
   WriteToNrf(W,RX_PW_P0,val,1);

   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,
   //and if payload >1Sbyte in 2Hbps) "F" is number of retries (1-15, now 15)
   WriteToNrf(W, SETUP_RETR, val, 1);

   //CONFIG reg setup - Now it's time to boot up the Qgf and choose if it's suppose to be a transmitter or receiver
   val[0]=0x1E; //0b0001 1110 - bit 0="0":transmitter bit 0="1":Receiver, bit 1="1"=power up,
   //bit 4="1"= mask_Max_RT i.e. IRQ-interrupt is not triggered if transmission failed.
   WriteToNrf(W, CONFIG, val, 1);

   //device need 1.5ms to reach standby mode (CE=low)
   _delay_ms(100);

   // Sei ();
}

// The receiver opens and "Listening" in 1s
void  receive_payload ( void )
{
   //sei();       // Enable global interrupt
   
   SETBIT(PORTB,1);    // CE IR_High = "Listening"
   _delay_ms(1000);    // listening in 1s and received goes int0-interruptvektor Started
   CLEARBIT(PORTB,1);  // ce low back-stop listening
   
   //cli();    // Disable the global interrupt
}

// Send the data
void transmit_payload( uint8_t  *W_buff)
{
   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 ...
   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!)
   
   //sei();    // enable global interrupt already!
   // USART_Transmit (GetReg (STATUS));
   
   _delay_ms(10);       // need to be really ms, not us?? YEEES! otherwise it will not work!
   SETBIT(PORTB,1);    // 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
   _delay_us ( 20 );       // at least 10us!
   CLEARBIT(PORTB,1);    // CE low
   _delay_ms(10);       // need to be really ms, not us?? YEEES! otherwise it will not work!
   
   // Cli (); // Disable the global interrupt ... ajabaja, then closes USART_RX-listening to!
   
}



int main(void)
{
   lcd_init(LCD_DISP_ON);
   lcd_puts("LCD init");
    _delay_ms(500);
   lcd_clrscr();
   
   InitSPI();
   lcd_puts("SPI init");
   _delay_ms(500);
   lcd_clrscr();
   
   ioinit();
   INT0_interrupt_init();
   lcd_puts("INT0 init");
   _delay_ms(500);
   lcd_clrscr();
   
   nrf24L01_init();
   lcd_puts("NRF init");
   _delay_ms(500);
   lcd_clrscr();
   
   ////uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
   ////lcd_puts("USART init");
   ////_delay_ms(500);
   ////lcd_clrscr();   
   
   //sei();
   
   //Clear the screen
   lcd_clrscr();
   
char buffer[5];


lcd_puts("STATUS:");
itoa( GetReg(STATUS), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();

lcd_puts("TEST:");
itoa(0xBC, buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("EA_AA:");
itoa( GetReg(EN_AA), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("EN_RXADDR:");
itoa( GetReg(EN_RXADDR), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("SETUP_AW:");
itoa( GetReg(SETUP_AW), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("RF_CH:");
itoa( GetReg(RF_CH), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("RF_SETUP:");
itoa( GetReg(RF_SETUP), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("RX_ADDR_P0:");
itoa( GetReg(RX_ADDR_P0), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("TX_ADDR:");
itoa( GetReg(TX_ADDR), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("RX_PW_P0:");
itoa( GetReg(RX_PW_P0), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("SETUP_RETR:");
itoa( GetReg(SETUP_RETR), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();


lcd_puts("CONFIG:");
itoa( GetReg(CONFIG), buffer, 16);   // convert interger into string (decimal format)
lcd_puts(buffer);        // and transmit string to UART
_delay_ms(500);
lcd_clrscr();

   while(1){
   reset();
   
   int i;
   for (i=0;i<5;i++)
   {
      buffer[i]=0x93;
   }
   transmit_payload(buffer);
   
   lcd_puts("STATUS:");
   itoa( GetReg(STATUS), buffer, 16);   // convert interger into string (decimal format)
   lcd_puts(buffer);        // and transmit string to UART
   _delay_ms(500);
   lcd_clrscr();

   }
   
   return 0;
}

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!
{
   cli();    // Disable the global interrupt
   CLEARBIT(PORTB ,1);       // ce low back-stop listening / transmitting
   SETBIT(PORTB,0);  // part one
   _delay_ms(500);
   CLEARBIT(PORTB,0);  // led off
   // Receiver function to print out on usart:
   data = WriteToNrf (R, R_RX_PAYLOAD, data, DataLen); // Read the received data
   reset();
   for (int i = 0; i <DataLen; i++)
   {
      lcd_putc(data[i]);
   }
   _delay_ms(1000);
lcd_clrscr();
   sei();
}
nRF24L01.h
Спойлер

Код: Выделить всё

/* Memory Map */
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#define DYNPD 0x1C
#define FEATURE 0x1D

/* Bit Mnemonics */
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW 0
#define ARD 4
#define ARC 0
#define PLL_LOCK 4
#define RF_DR 3
#define RF_PWR 6
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
#define RX_P_NO 1
#define TX_FULL 0
#define PLOS_CNT 4
#define ARC_CNT 0
#define TX_REUSE 6
#define FIFO_FULL 5
#define TX_EMPTY 4
#define RX_FULL 1
#define RX_EMPTY 0
#define DPL_P5 5
#define DPL_P4 4
#define DPL_P3 3
#define DPL_P2 2
#define DPL_P1 1
#define DPL_P0 0
#define EN_DPL 2
#define EN_ACK_PAY 1
#define EN_DYN_ACK 0

/* Instruction Mnemonics */
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define REGISTER_MASK 0x1F
#define ACTIVATE 0x50
#define R_RX_PL_WID 0x60
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define W_ACK_PAYLOAD 0xA8
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF

/* Non-P omissions */
#define LNA_HCURR 0

/* P model memory Map */
#define RPD 0x09

/* P model bit Mnemonics */
#define RF_DR_LOW 5
#define RF_DR_HIGH 3
#define RF_PWR_LOW 1
#define RF_PWR_HIGH 2