nrf24l01+ противоречит самому себе?

Недавно я купил несколько таких микросхем на платах вместе с некоторыми "адаптерными платами", которые предположительно регулируют напряжение от 5 В до 3,3 В с помощью необходимых конденсаторов. Так что источник питания не должен быть проблемой, хотя я и не пробовал использовать отдельный источник питания. Итак, мне нравится создавать свои вещи с нуля, чтобы действительно знать все, что происходит, поэтому я не использую библиотеку для этого чипа, но я полностью прочитал техническое описание и разобрался во всех функциях. Сначала, пройдя через каждый вариант одного из модулей был успешно посылая пакеты, как указано в TX_DS прерывать, но ничего не показывает вверх на один в режиме приемника, и после проверки я выбрал, чтобы отключить все функции и удалось, наконец, добиться каких-то действий в качестве приемника прерывается каждый раз, когда передатчик послал пакет с КПР и не ACK.

Но теперь возникла проблема, в таблице данных четко указано:

IRQ RX_DR утверждается событием прибытия нового пакета. Процедура обработки этого прерывания должна быть следующей:

1) считывание полезной нагрузки через SPI,

2) очистить IRQ RX_DR,

3) прочитайте FIFO_STATUS,чтобы проверить, доступны ли дополнительные полезные нагрузки в RX FIFO,

4) если в RX FIFO больше данных, повторите шаг 1).

Однако после получения прерывания и считывания 33 байтов с помощью команды регистр состояния считывает 4E (0100 1110), в котором говорится, что прерывание действительно было RX_DR, но все биты номера канала включены, что означает пустой RX FIFO. Следующие 32 байта означают 0.

Как это может быть? Кто-нибудь испытывал нечто подобное?

ОБНОВЛЕНИЕ: Протестировано с отдельным блоком питания на стороне RX, проблема все еще остается в силе.

Фотографии: https://1drv.ms/f/s!ag6xbmoahj8xkokwmg89riaa1m71квт

Код Arduino: (не стесняйтесь поправлять меня, я не эксперт в этом языке :p)

Главная

void setup() {
  attachInterrupt(digitalPinToInterrupt(radio.irq), interrupt, FALLING);
  Serial.begin(9600) ;
  Serial.write("\n    ----Boot----\n\nInitializing radio...\n");

  //Starts radio as PRX
  //Sets channel
  //Sets bitrate to 1Mbps
  if (radio.init()) {
    Serial.println("Radio ready.\n\n ----Boot complete----\n\n");
  } else {
    Serial.write("Couldn't initialize radio!\n\n  ----Boot failed----\n");
    return;
  }
  delay(10);
  digitalWrite(9, HIGH);
}


void loop() {
}


void interrupt() {
  Serial.write("\nINTERRUPT\n");
  digitalWrite(9, LOW);

  radio.readRegister(0x17, 2, true, BIN);
  radio.readRXpayload(true);
  radio.clearIRQ();

  digitalWrite(9, HIGH);
}

Класс радиосвязи

#include "BitUtils.h"

BitUtils utils;

uint8_t* tmp = (uint8_t*)malloc(sizeof(uint8_t) * 33);
uint8_t initialPipe0[5] = {0x28, 0x18, 0xdb, 0xc2, 0x86};
uint8_t beaconAddress[5] = {0x29, 0x26, 0x13, 0x12, 0x00};

class Radio {
  public:
    uint8_t nullmsg[1] = {0x00};

    uint8_t rx_config[1] = {0b00100011}; //0x00
    uint8_t tx_config[1] = {0b00100010}; //0x00
    uint8_t aa_config[1] = {0b00000000}; //0x01
    uint8_t ch_config[1] = {0b00110100}; //0x05
    uint8_t rf_config[1] = {0b00000110}; //0x06
    uint8_t features_config[1] = {0b00000000}; //0x1D

    uint8_t clear_irq[1] = {0b01110000}; //0x07

    uint8_t clk = 13;
    uint8_t miso = 12;
    uint8_t mosi = 11;
    uint8_t slaveselect = 10;
    uint8_t chipenable = 9;
    uint8_t irq = 2;

    SPISettings spiConfig = SPISettings(2000000, MSBFIRST, SPI_MODE0);


    boolean init() {
      noInterrupts();

      pinMode(clk, OUTPUT);
      pinMode(miso, INPUT);
      pinMode(mosi, OUTPUT);
      pinMode(slaveselect, OUTPUT);
      pinMode(chipenable, OUTPUT);
      pinMode(irq, INPUT);
      digitalWrite(clk, LOW);
      digitalWrite(slaveselect, HIGH);
      digitalWrite(chipenable, LOW);
      delay(11);

      transfer(nullmsg, 1, tmp);
      if (tmp[0] != 0b00001110) {
        return false;
      }

      writeRegister(0x00, rx_config, 2); Serial.print("0x00: ");
      readRegister(0x00, 2, true, BIN);
      writeRegister(0x01, aa_config, 2); Serial.print("0x01: ");
      readRegister(0x01, 2, true, BIN);
      writeRegister(0x05, ch_config, 2); Serial.print("0x05: ");
      readRegister(0x05, 2, true, BIN);
      writeRegister(0x06, rf_config, 2); Serial.print("0x06: ");
      readRegister(0x06, 2, true, BIN);
      writeRegister(0x1D, features_config, 2); Serial.print("0x1D: ");
      readRegister(0x1D, 2, true, BIN);

      pipeAddress(initialPipe0, 0);
      pipeAddress(beaconAddress, 1);

      Serial.print("Pipe 0 address: ");
      readRegister(0x0A, 6, true, HEX);
      Serial.print("Pipe 1 address: ");
      readRegister(0x0B, 6, true, HEX);

      delay(2);
      interrupts();
      return true;
}


    //    -- Operations --

    void clearIRQ() {
      writeRegister(0x07, clear_irq, 2);
      Serial.println("Cleared IRQ");
    }

    void sendTXpayload(uint8_t data[], boolean ack) {
      uint8_t message[33] = {0b10100000};
      if (!ack) {
        message[0] = 0b10110000;
      }
      for (int i = 31; i > -1; i--) {
        message[32 - i] = data[i];
      }

      transfer(message, 33, tmp);
      pulseCE(12);
      delay(2);
    }
    void readRXpayload(boolean report) {
      uint8_t message[33] = {0b01100001};

      transfer(message, 33, tmp);
      if (report) {
        utils.prtArr(tmp, 33, HEX);
      }
    }

    void mode(char m) {
      digitalWrite(chipenable, LOW);

      if (m == 't') {
        writeRegister(0x00, tx_config, 2);
        Serial.println("Set tx mode.");
      }
      if (m == 'r') {
        writeRegister(0x00, rx_config, 2);
        Serial.println("Set rx mode.");
      }
    }

    void pipeAddress(uint8_t* address, uint8_t number) {
      uint8_t pipeNumber = 0x0A + number;
      for (int i = 4; i > -1; i--) {tmp[4 - i] = address[i];}

      if (number < 2) {
        writeRegister(pipeNumber, tmp, 6);
      }else{
        writeRegister(pipeNumber, address, 2);
      }
    }

    void sendTo(uint8_t* address) {
      for (int i = 4; i > -1; i--) {
        tmp[4 - i] = address[i];
      } 
      writeRegister(0x10, tmp, 6);
      Serial.print("TX Address: ");
      readRegister(0x10, 6, true, HEX);
    }

    void setChannel(uint8_t ch) {
      writeRegister(0b00000101, new uint8_t[1] {ch}, 2);
      Serial.write("Frequency set to: ");
      Serial.print(2400 + tmp[1], DEC);
      Serial.println("MHz");
    }


    //    -- Low operations --

    void readStatus(boolean prt) {
      transfer(nullmsg, 1, tmp);
      if (prt) {
        utils.prtArr(tmp, 2, BIN);
      }
    }
    void readRegister(uint8_t address, uint8_t amount, boolean prt, uint8_t format) {
      uint8_t message[amount] = {address};
      transfer(message, amount, tmp);

      if (prt) {
        utils.prtArr(tmp, amount, format);
      }
    }
    void writeRegister(uint8_t address, uint8_t* data, uint8_t amount) {
      uint8_t message[amount] = {(uint8_t)(0b00100000 | address)};
      for (uint8_t i = 1; i < amount; i++) {
        message[i] = data[i - 1];
      }

      transfer(message, amount, tmp);
    }
    void pulseCE(int duration) {
      digitalWrite(chipenable, HIGH);
      delayMicroseconds(duration);
      digitalWrite(chipenable, LOW);
    }


    //    -- Bidirectional SPI bus --

    void transfer(uint8_t* data, uint8_t amount, uint8_t* output) {
      SPI.beginTransaction(spiConfig);
      digitalWrite(slaveselect, LOW);
      delayMicroseconds(1);

      for (uint8_t i = 0; i < amount; i++) {
        output[i] = SPI.transfer(data[i]);
      }

      delayMicroseconds(1);
      digitalWrite(slaveselect, HIGH);
      SPI.endTransaction();
    }
};

, 👍2

Обсуждение

Вы можете опубликовать код Arduino?, @MichaelT

@MichaelT отредактировано в коде, @Manuel Covas

Мне интересно, связана ли ваша проблема с проблемой, с которой я сталкиваюсь с моими nRF24L01? Видишь https://arduinoprosto.ru/q/85874/nrf24l01-continuously-reading-closed-pipe, @PyNZ


2 ответа


1

Мой совет состоял бы в том, чтобы удалить весь ненужный код, чтобы создать минимальный полный пример (MCVE). nRF24L01 не так сложен, когда вы знакомитесь с регистрами данных, и, к сожалению, именно здесь многие люди застревают, пытаясь использовать библиотеки, не читая данные. Однако опубликованный код предполагает, что вы выполнили свою домашнюю работу. Вот как я настроил nRF24L01 для использования IRQ (хронологический порядок сверху вниз):

// Begin SPI 
// Register 0x0A: set receiver addresses
// Register 0x11: set payload number of bytes

// flush RX (spi transfer B11100010) and TX (spi transfer B11100001)

// attach ISR on IRQ digital input pin.

// start the main program loop

Это называется ISR:

void isr(){
// Read payload data
digitalWrite(CSN_pin, LOW);
 data_in[0] = SPI.transfer(B01100001); //read payload register
 data_in[1] = SPI.transfer(B00000000);
 data_in[2] = SPI.transfer(B00000000);
 data_in[3] = SPI.transfer(B00000000);
 // etc
digitalWrite(CSN_pin, HIGH);

// flush RX
digitalWrite(CSN_pin, LOW);
 SPI.transfer(B11100010);//flush RX
digitalWrite(CSN_pin, HIGH);

// Read status register 0x07
digitalWrite(CSN_pin, LOW);
 SPI.transfer(0x07);
 reg7 = SPI.transfer(0x00);
digitalWrite(CSN_pin, HIGH);

reg7 |= B01000000; // RX_DR set bit 6
// write back to status register
digitalWrite(CSN_pin, LOW);
 SPI.transfer(0x20+0x07);
 SPI.transfer(reg7);
digitalWrite(CSN_pin, HIGH);
}    

Изменить: бит 6 регистра состояния-это флаг RX_DR. Если это 1 (что имеет место в примере операции), то данные не были получены. Установите бит 6, чтобы очистить прерывание.

,

Я думал, что "RX_DR` означает "Данные готовы", и на странице 30 они указывают: "После проверки пакета Enhanced ShockBurst™ разбирает пакет и загружает полезную нагрузку в FIFO RX и утверждает IRQ RX_DR"., @Manuel Covas

Вы правы, но в паспорте данных (p59) также говорится, что "RX_DR=0" утверждается, когда новые данные поступают в RX FIFO, напишите "1", чтобы очистить бит. Это то, что делает код в моем ответе. Помните также "MASK_RX_DR=0", но это значение по умолчанию при запуске., @MichaelT

Это было бы странно, нет? Значения сброса для IRQ равны "0", и я действительно получаю прерывание, когда пакет отправляется другим радиоприемником. RX_DR переходит в " 1 "в регистре состояния, кроме того, при записи" 1 "для очистки бита он возвращается к "0". Не знаю, почему они сделали это таким образом, но, по крайней мере, это то, что происходит со мной. Основная проблема заключалась в том, что IRQ и остальная часть устройства указывали пустые FIFO., @Manuel Covas

Я просто следую тому, что написано в паспорте. (Псевдо) код, написанный выше, действительно работает, я использую его в своих собственных проектах nRF24., @MichaelT


0

Мне интересно, связана ли ваша проблема с проблемой, с которой я сталкиваюсь с моим nRF24L01? См. nRF24L01 непрерывное считывание закрытой трубы

,