Syntax help

Hey, I'm trying to use a nRF24L01+ without a library (manly because I want to learn how it works a bit better) but I can't understand this:

spi->transfer(R_REGISTER | (REGISTER_MASK & reg));

I see this for both arduino libraries and pic mcu libraries but I'm not familiar with this. I've used SPI before, with external ADCs (ads1247 and ad7795), and this module seemed simpler to use, but when I try to read the status register using the function below I receive 1111 1111.

void STATUS(){
digitalWrite(CSN, LOW);
SPI.transfer(0x27);
SPI.transfer(0b00000000); //data to read
data = SPI.transfer(0xff);//nop
Serial.println(data, BIN);
digitalWrite(CSN, HIGH);
}

Edit to delete stuff that did not seem relevant - the code I use for my Attiny 1634 also does not use the SPI library

Note that EVERY spi transfer receives data as well as transmitting it. Your code seems to ignore some of the received values.

Careful attention to that “un-put-downable” work of literature, the Nordic nRF24L01+ datasheet is advised.

…R

yes, well in the datasheet nordic it says this :No Operation. Might be used to read the STATUS register
so I assumed that like the ads1247 that to read the data I need to just send a clock signal(thus the NOP, which seems to be confirmed in diagram in the spi timing chapter) and thats why i dont care about what the nrf sends me before

When you send the NOP command you get back the value of the status register at the same time as the NOP command is being sent. So you must use the returned value.

Have you tried this simpler version

void STATUS(){
  digitalWrite(CSN, LOW);
     data = SPI.transfer(0xff);//nop
  digitalWrite(CSN, HIGH);
  Serial.println(data, BIN)
 }

And your problem may be trying to do Serial.print() before you close off the transaction with CSN, HIGH. However I have not experimented with that.

...R
PS the word is "syntax"

...R
PS the word is "syntax"

it was a typo. If you wish to be impolite, I respectfully ask you not to answer or post here. I trying to describe the problem giving the most information that I can because, after all, I am requesting help. Anyway this is slightly out of the scope of my question which was that does this mean and do: spi->transfer(R_REGISTER | (REGISTER_MASK & reg));.

R: I tried you solution and it didn't work, all I receive is 1111 1111.

spi->transfer(R_REGISTER | (REGISTER_MASK & reg));

Well! I know nothing about SPI, but I can talk about code.

spi is a pointer to a class which has a “transfer” method. You are telling that object to “transfer” an integer value.

The value is certain bits in reg combined with certain bits in R_REGISTER.

Let’s say that we need to pass a byte value that has a particular bit format, like

PPPP0QQQ

Where PPPP is some special constant control code like 0b1010 and QQQ is the content of your variable reg.

The purpose of this is that if your reg contains a silly value like 27, which is 0b00011011, the garbage bits not in the QQQ range don’t clobber the important control bits in the PPP range.

So, in this example, R_REGISTER will be the constant 0b10100000. You see that it has the PPPP bits set correctly, and all the other bits are zero.

REGISTER_MASK will be 0b00000111. It has 1 bits where QQQ is, and zero bits elsewhere.

So the first thing we do is take the bitwise AND of reg with REGISTER_MASK. This wipes any bits not in the QQQ area. For instance, in my exmple if reg contains 0b00011011, then (reg&REGISTER_MASK) will evaluate to 0b00000011.

We then bitwise OR that value with R_REGISTER. This sets the PPPP bits without disturbing anything else (because all the other bits are zero). In this example, (R_REGISTER|0b00000011) evaluates to 0b10100011.

The result is an integer (or byte) whose bits are in the format we need. PPPP is 1010, like it needs to be, and QQQ is 011. Now, this isn’t 27, but serves you right for trying to stuff 27 into a three-bit field.

It’s a very, very standard thing. Anything named “MASK” is probably meant to be used in this way. Think of it like a spraypainting mask, like masking tape. It protects the bits that you don’t want to get screwed up.

Robin2:
PS the word is "syntax"

Indeed. Sintax is the levy on cigarettes and alcohol.

LOL! Dad joke!

it was a typo. If you wish to be impolite, I respectfully ask you not to answer or post here.

I believe he wished to be helpful. On a board where people routinely use 'code' as a singular noun, it's believable that people could get this one wrong.

kiyoshi7:
R: I tried you solution and it didn't work, all I receive is 1111 1111.

Post the complete program that you tried it in and I will try it with my Uno and nRF24

...R
PS. I was rather hoping you would edit your Original Post and correct the typo in the title.

first off R. I Believe I must apologize for my misunderstanding earlier, sorry.

well it’s still a sketch so it’s a bit clunky, but here it is:

#include<SPI.h>

const int CSN = 10;
const int CE  = 9;
const int IRQ = 2;
uint8_t data;

void setup() 
{
 Serial.begin(115200);
 delay (10);
 
 SPIinitialize(); // Arduino setup SPI.
 NRF24L01Init();
}

void loop() {
  Serial.println("loop");
  delay(1000);
  STATUS();
}

void SPIinitialize()
{
 // Arduino ADC interface (wire according to requirements)
 pinMode(CSN, OUTPUT); // pin 10 as CSN SPI chip select
 pinMode( CE, OUTPUT); // pin 09 as CE mode as reciever    : monitoring(1) or standby (0)
                      //                   as transmitter : Transmit      or standby
// attachInterrupt(digitalPinToInterrupt(IRQ), FUNCTION TO RUN, mode); 
 digitalWrite(CSN, HIGH); // pins set to high, desablita a comunicação SPI.
 digitalWrite(CSN, HIGH);
  
 // Arduino SPI settings (change first line according to IC specifications)
 // defines SPI comunication type and initializes module
 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // SPI setup SPI communication
 delay(200); // SPI delay for initialization
 SPI.begin(); // SPI Module 'wake up'
 }

void NRF24L01Init(){
  digitalWrite(CSN, LOW);
  SPI.transfer(0x20);                   // Reg. 0       COMMAND    001A AAAA
  SPI.transfer(0x1E);                   // 0001 1110     DATA

  SPI.transfer(0x21);                   // ShockBurst   COMMAND    001A AAAA
  SPI.transfer(0x3F);                   // 0011 1111     DATA

  SPI.transfer(0x22);                   // EN_RXADDR    COMMAND    001A AAAA
  SPI.transfer(0x03);                   // 0000 0011     DATA

  SPI.transfer(0x23);                   // SETUP_AW     COMMAND    001A AAAA
  SPI.transfer(0x03);                   // 0000 0011     DATA

  SPI.transfer(0x24);                   // SETUP_RETR   COMMAND    001A AAAA
  SPI.transfer(0x0F);                   // 0000 1111     DATA
  
  SPI.transfer(0x25);                   // RF_CH        COMMAND    001A AAAA
  SPI.transfer(0x02);                   // 0000 0010     DATA
  
  SPI.transfer(0x26);                   // RF_SETUP     COMMAND    001A AAAA
  SPI.transfer(0x07);                   // 0000 0111     DATA

  digitalWrite(CSN, HIGH);
  }

void STATUS(){        
  digitalWrite(CSN, LOW);
  SPI.transfer(0x07);
  data = SPI.transfer(0xff);// NOP
  digitalWrite(CSN, HIGH);
  Serial.println(data, BIN);
  }

PS. I was rather hoping you would edit your Original Post and correct the typo in the title.

I didn’t know I could change the title, thanks I’ll try to

 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // SPI setup SPI communication
 delay(200); // SPI delay for initialization
 SPI.begin(); // SPI Module 'wake up'

Think about that, for a minute. Does that order of statements make sense? The comments are WRONG. Either fix them, or get rid of them.

Beginning a transaction without ending the transaction does not make sense.

You seem to have an awful lot of junk in your program. This works for me

#include <SPI.h>

#define CE_PIN   9
#define CSN_PIN 10

void setup() {
    Serial.begin(115200);
    pinMode(CE_PIN, OUTPUT);
    pinMode(CSN_PIN, OUTPUT);
    SPI.begin();

    digitalWrite(CSN_PIN, LOW);
        byte status = SPI.transfer(0x07);
    digitalWrite(CSN_PIN, HIGH);
    Serial.print("Status "); Serial.println(status);
}

void loop() {

}

…R

ok then I should get rid of SPI.begin? thanks I found that kinda odd thats why I commented the third line line that.

R: ya in the testing/figuring out stage my programs are always full of junk. I'll try your code, but you didn't have to 'set' the spi communication mode and etc?

edit:
R: I just tested your code and I received 255 (1111 1111) either this is expected or my chip is busted. I know I wired it right, I also confirmed the pin out with the vendor, so i think i'll try it with another nRF25L01+ module

kiyoshi7:
R: I just tested your code and I received 255 (1111 1111) either this is expected or my chip is busted. I know I wired it right, I also confirmed the pin out with the vendor, so i think i'll try it with another nRF25L01+ module

I was getting 28 - which I think is what is expected.

Have you a 10µF capacitor across Vcc and GND for the nRF24?

...R

Yes, I've also tried without the capacitor. and just now to confirm that I didn't invert the pinout I inverted it and the ran the program, which gave me 0, at least I confirmed that the chip wasn't fried(good thing I have 3)

kiyoshi7:
Yes, I've also tried without the capacitor.

I intended you to try it WITH the capacitor.

Make a simple drawing showing how you have everything connected and post a photo of the drawing.

...R

I was with the capacitor, I ALSO tried without. but maybe I hooked it up wrong so here(it's in google drive):

Google Drive is slooooow. For the future just attach your PNG here. See this Image Guide

What exactly is meant by ArduinoPower-2 and ArduinoPower-1. That is not standard Arduino-speak.

Assuming they refer to the Uno's 3.3v pin and GND pin it looks like you have things connected the same way I have mine connected. However I have never had any reason to use the interrupt and I just leave that nRF24 pin unconnected.

...R

[OT]

Robin2:
However I have never had any reason to use the interrupt and I just leave that nRF24 pin unconnected.

It works as specified in the datasheet, I test(ed) that feature very intensive.

[/OT]

I intend to use the interrupt. the name is because I couldn't name each pin individually, so I named it arduino power since on the boaed it says 'power' and labled the wires 3.3v and gnd. later I'm gonna get an o'scope and try to see what's happening. thanks guys at least now I know where the problem is and as soon as I find a solution I'll post it here

Whandall:
It works as specified in the datasheet, I test(ed) that feature very intensive.

Thanks. That's useful to know.

Of course it does depend on sensible Arduino code :slight_smile:

...R