AVR nRF24L01 Communication SPI example code

Go To Last Post
29 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone, I need an AVR code or examples about communication atmega328p's with nRF24L01 . If you have code , Please sharing :) 

Last Edited: Tue. Jan 14, 2020 - 02:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For what purpose?  A class assignment, a fun project, a product that will be made available for sale, etc...?  What is the end-goal?

 

My understanding is that there is code available at Adafruit.com and other places for the Arduino, for which, several Arduino board models use the Mega328P.

 

If you are thinking about writing code for the nRF24L01P from scratch, I've learned first hand, it's no trivial task.

 

I'm currently using two Arduino Nano rev 3.0 controller boards (Mega328P) with the nRF24LL01P and it's been quite a challenge, to say the least.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just google! There are lots of working examples.

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I actually found the nRF24L01+ to be one of the easier and better-documented modules I've worked with. I had a working system up and running within a few days using just the data sheet. You can easily obtain the data sheet from Nordic Semi. The only gotcha that wasn't obvious to me is that you need to specify the receive payload width or else the received data will never be clocked out of the FIFO.

 

Here is some sample code to initialize receiving:

 

    /* Set receive payload width to 1 byte */
	ldi r17, RX_PW_P0
	ldi r18, PAYLOAD_WIDTH
	rcall SetRegisterSingle

	/* Set address width to 5 bytes */
	ldi r17, SETUP_AW
	ldi r18, AW_5
	rcall SetRegisterSingle

	/* Set RF channel to initial value */
	ldi r17, RF_CH
	ldi XL, low(Channel)
	ldi XH, high(Channel)
	ld r18, X
	rcall SetRegisterSingle

	/* Enable receive pipe 0 only */
	ldi r17, EN_RXADDR
	ldi r18, (1<<ERX_P0)
	rcall SetRegisterSingle

	/* Set receive address on pipe 0 */
	ldi r17, RX_ADDR_P0
	ldi r18, ADDR_LEN
	ldi XL, low(Addr)
	ldi XH, high(Addr)
	rcall SetRegisterMulti

	/* Mask transmit-related RF module interrupts, enable CRC, and power up RF module in receive mode */
	ldi r17, CONFIG
	ldi r18, (1<<MASK_TX_DS)|(1<<MASK_MAX_RT)|(1<<EN_CRC)|(1<<PWR_UP)|(1<<PRIM_RX)
	rcall SetRegisterSingle

	/* Clear any pending interrupts on RF module */
	ldi r17, STATUS
	ldi r18, (1<<TX_DS)|(1<<MAX_RT)|(1<<RX_DR)
	rcall SetRegisterSingle

This initializes the transmitter:

 

	/* Set 5-byte address width */
	ldi r17, SETUP_AW
	ldi r18, AW_5
	rcall SetRegisterSingle

	/* Set initial RF channel */
	ldi r17, RF_CH
	ldi XH, high(Channel)
	ldi XL, low(Channel)
	ld r18, X
	rcall SetRegisterSingle

	/* Mask RX_DR interrupt on RF module, enable CRC, power up RF module in transmit-standby mode */
	ldi r17, CONFIG
	ldi r18, (1<<MASK_RX_DR)|(1<<EN_CRC)|(1<<PWR_UP)
	rcall SetRegisterSingle

	/* Clear any pending RF module interrupts */
	ldi r17, STATUS
	ldi r18, (1<<TX_DS)|(1<<MAX_RT)|(1<<RX_DR)
	rcall SetRegisterSingle

 

These are some of the subroutines called by the above code as well as subroutines to transmit and receive a payload byte:

 

/* 
 * TransmitPayload
 *
 * Inputs:
 * 
 * r17 = payload byte to send
 *
 */

TransmitPayload:
	push r16
	cbi PORTD, RF_CSN
	ldi r16, W_TX_PAYLOAD
	rcall SPITransfer
	mov r16, r17
	rcall SPITransfer
	sbi PORTD, RF_CSN
	pop r16
	ret

/* 
 * GetPayload
 *
 * Inputs:
 * 
 * None
 *
 * Outputs:
 *
 * r16 = payload from nRF24L01+ (byte)
 *
 */

GetPayload:
	cbi PORTD, RF_CSN
	ldi r16, R_RX_PAYLOAD
	rcall SPITransfer
	ldi r16, SPI_NOP
	rcall SPITransfer
	sbi PORTD, RF_CSN
	ret

/*
 * SendCommand
 *
 * Inputs:
 *
 * r16 = command byte to send
 *
 */

SendCommand:
	cbi PORTD, RF_CSN
	rcall SPITransfer
	sbi PORTD, RF_CSN
	ret

/*
 * SetAddress
 *
 * Inputs:
 *
 * r25 = number of address bytes
 * XH:XL = address of address bytes (MSByte first)
 *
 */

SetAddress:
	push XH
	push XL
	ldi r25, ADDR_LEN
	ldi r17, RX_ADDR_P0
	rcall SetRegisterMulti
	pop XL
	pop XH
	ldi r25, ADDR_LEN
	ldi r17, TX_ADDR
	rcall SetRegisterMulti
	ret

/*
 * SetRegisterSingle
 * 
 * Inputs:
 * 
 * r17 = register to set
 * r18 = desired register value (byte)
 *
 */

SetRegisterSingle:
	push r16
	cbi PORTD, RF_CSN
	ldi r16, W_REGISTER
	add r16, r17
	rcall SPITransfer
	mov r16, r18
	rcall SPITransfer
	sbi PORTD, RF_CSN
	pop r16
	ret

/*
 * SetRegisterMulti
 * 
 * Inputs:
 * 
 * r17 = register to set
 * r25 = number of bytes in register value
 * XH:XL = starting address of register value
 *
 */

SetRegisterMulti:
	push r16
	cbi PORTD, RF_CSN
	ldi r16, W_REGISTER
	add r16, r17
	rcall SPITransfer
	add XL, r25
SetLoop:
	ld r16, -X
	rcall SPITransfer
	dec r25
	brne SetLoop
	sbi PORTD, RF_CSN
	pop r16
	ret

/* 
 * GetRegisterSingle
 *
 * Inputs:
 * 
 * r17 = register to retrieve
 *
 * Outputs:
 *
 * r16 = register value (byte)
 *
 */

GetRegisterSingle:
	cbi PORTD, RF_CSN
	ldi r16, R_REGISTER
	add r16, r17
	rcall SPITransfer
	ldi r16, SPI_NOP
	rcall SPITransfer
	sbi PORTD, RF_CSN
	ret

/* 
 * SPITransfer
 *
 * Inputs:
 * 
 * r16 = data (byte) to transmit on SPI bus
 *
 * Outputs:
 *
 * r16 = data (byte) received from SPI bus
 *
 */
	
SPITransfer:
	out USIDR, r16
	ldi r16, (1<<USIOIF)
	out USISR, r16
	ldi r16, (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
SPITransferLoop:
	out USICR, r16
	sbis USISR, USIOIF
	rjmp SPITransferLoop
	in r16, USIDR
	ret

I've also attached a copy of the .inc file I created (named as a .txt due to file type restrictions) that defines the constants. Feel free to use this code if you want. Or, you know, you could just go look for a library like the other posters suggested. cheeky

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely you have done zero searching.  You can't throw a rock without hitting example code for that radio.

 

https://www.google.ca/search?q=mirf

http://www.airspayce.com/mikem/arduino/RadioHead/

http://www.airspayce.com/mikem/arduino/NRF24/

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This project is my graduation project , I searched it from  google, youtube  or forums but I didnt find anything except "http://www.tinkerer.eu/AVRLib/nR..." and  "http://www.tinkerer.eu/AVRLib/SPI/" but I cant work these code. My project is the  8bit communication  between two atmega328p's with nrf24L01 however I can ony use AVR libraries and AVR code, Arduino is used C++ libraries so  it is not usefull for me. I know atmega328p is arduino chip but My teacher said" only use avr code ".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's my own code at http://www.barefootelectronics.com It's for xMega, but would pretty readily adapt.

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But the only bit that's actually specifc to the AVR is just the lowest-level where you're dealing directly with the SPI peripheral hardware. You can simply encapsulate that into functions like spi_init(), spi_write(), and spi_read().

 

Above that, the code should be completely generic and independent of any particular microcontroller.

 

The nRF24L01 is a Nordic Semiconductor product - they provide a whole load of documentation and examples on their site: http://www.nordicsemi.com/eng/Pr...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you download the data sheet yet? Awneil is right in that all you really do with the AVR is use SPI to talk to the RF module. Are you planning to write this project from scratch or were you planning to cut and paste various bits of code and then tweak things until it starts working?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

search for NRF24L01 c source. Are you using atmelstudio?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Utku, You should ask your questions in the forum, not in private messages. Also, I gave you the link above.

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I handle it , thanks for everyone, in the codes , I read  at above ,  Interrupts part is not suitable for atmega328p, I change the code

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone I need some help with Atmega8a and nrf24l01+ module. I have made an rx and tx using atmega8a and nrf module, when i connect it to 5v supply(i have used 1117 at 3.3 v for nrf)the communicatioin works fine without any garbage value. But when I connect the transmitter section with AA batteries the communication is ok sometimes and it give garbage values sometimes. Its not reliable and accuarte there is data loss as well. What can be the soulution please help. When using AA batteries the voltage across Atmega8A is 3.27V and across NRF module its 2.9V.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the Atmega8A supposed to work correctly at 3.3V? ie what is you clock speed?

 

If you are using different supply voltages you should get level translators. And why is the voltage "across NRF module its 2.9V." if you are running both from the same batteries?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My clock speed is set to default of 1MHz.

I have used all default settings i have not configured it via fuse bits.

 

"across NRF module its 2.9V." because of 1117 which i have used for voltage conversion.

 

I have removed it now and the voltage is same at both ends now ie at Atmega8A and NRF.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My clock speed is set to default of 1MHz.

And the next bit of information is the baud rate you are using and whether it has a large error rate at 1MHz, you can check this from the datasheet .

 

Also remember that for reliable comms you should have a UART friendly CRYSTAL and not rely on the internal oscillator.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

NRF modules are SPI and don't use a baud rate. Many of my projects operate them from 2 AA cells.

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The baud rate which i am working with is 9600 with U2X bit set so the error % is 0.2, will this affect a  lot. I will try with external crystal this time and check.

@ Torby i m sending data via serial terminal to test.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can you share your code.

we are also doing project using NRF24l01+ to transmit and receive the GPS time between them'.

thanks in advance.

 

JANARDHAN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Folks don't like to share code here, UNLESS you actually start some, on your own. Then, we will help you with what you have done. But, YOU need to make that first step!

 

Best wishes

Jim

 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can You share the actual code with please.I have been trying from a long time.it is not working for me.

please share your code.

thanks in advance

JANARDHAN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i have tried all the possibilities but no use.please help me

JANARDHAN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, Janardhan -

 

What have you tried? Please show us something. And saying "does not work" is of no help. How does it fail? 

 

Please do not say that you are trying this without an oscilloscope or a logic analyzer or debugging capability! While it might seem simple, it is fairly complex and you needs something more than just plugging into RF modules, trying to communicate, than saying "it fails"!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JANARDHAN KUKUDALA wrote:
i have tried all the possibilities but no use.please help me

 

As noted already, show what you have done, post your code that does not work, explain what does not work, what you expect to happen.

 

What AVR are you using?  Post a schematic of your connections.

 

 

Expecting folks that have done the work are not inclined to hand it over just because you make a plea for help.

 

Another Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JANARDHAN KUKUDALA wrote:
i have tried all the possibilities
Does that include this?....

 

https://howtomechatronics.com/tutorials/arduino/arduino-wireless-communication-nrf24l01-tutorial/

 

The fact is that debugging a setup that includes two separate senders/receivers is always going to be fraught as there are "too many unknowns" because if there's a problem you can't know which end of the link you got wrong. So the best bet is to start out with a setup that is almost bound to work straight off (two Arduinos and NRF2410L shileds) then gradually switch over one end to your own implementation knowing that the other end of the link is "robust".

 

Also, if you do use Arduino then you may not want to use the whole Arduino software system but what you can do is look at their specific code for NRF and get an idea of the steps needed, if not the exact code, and stand more chance of getting the steps right in your own implementation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guys,
Sorry  I am late to the forum. I want to learn about programming NRF24 from scratch bit by bit.... Is there any guide that can help me with this. ** I am not a programmer but I know basic C programming.**

 

TIA

Aneesh Kola

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anee_19 wrote:

Hi Guys,
Sorry  I am late to the forum. I want to learn about programming NRF24 from scratch bit by bit.... Is there any guide that can help me with this. ** I am not a programmer but I know basic C programming.**

 

TIA

Start with reading the Datasheet from start to finish.... then read it again and make sure you understand what is written in it.

Then you can start with writing code for it and slowly see it come to life. Or you go and grab an arduino example and see how that works and either use that code or base your own code on it depending on how much you really want to learn about this chip.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anee_19 's question continues here:  https://www.avrfreaks.net/forum/nrf24l01-2

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Topic locked