Как правильно принимать данные у NRF24L01

Обсуждаем цифровые устройства...
Ответить
Аватара пользователя
Serbis
Прорезались зубы
Сообщения: 211
Зарегистрирован: Чт авг 02, 2012 19:59:40

Как правильно принимать данные у NRF24L01

Сообщение Serbis »

Если есть знатоки данного изделия, подскажите как с ним правильно работать, уже всю голову сломал. Ну вот собственно есть такой код:
status = NRF24_ReadReg(STATUS); //1

if(status & 0x40) {
NRF24_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH);
NRF24_WriteReg(STATUS, 0x40); //2


Выполняет он прием данных, т е считывает регистр статуса, если там выставлен флаг прихода данных, читаем данные, и переписывает регистр статуса с сброшенными битами приема. В чем тут проблема - если приходит новый пакет между точками 1 и 2, мы об этом факте не узнаем, так как регистр статуса уже прочитан, после чего пришел новый пакет, и мы на позиции 2 инфу об этом факте затираем. Данная проблема не проявляет себя при низких скоростях, но вот как только к данные начинают идти подряд от значительно более быстрого устройства, она происходит регулярно. При этом насколько я понимаю, ножка IRQ сбрасывается именно при изменении регистра статуса. Т е один фиг, что через прерывание работать, что через статус, все равно эта ситуация будет иметь место быть. Посмотрел код либы на ардуино, там то же самое сделано. Как собственно правильно принимать данные от этой железяки?
Аватара пользователя
khomych
Мучитель микросхем
Сообщения: 423
Зарегистрирован: Сб фев 21, 2009 16:11:32
Откуда: Харьков
Контактная информация:

Re: Как правильно принимать данные у NRF24L01

Сообщение khomych »

Нужно изучать работу с регистром FIFO STATUS (0x17).

Сам сейчас мучаю эти модули, но до FIFO буфера не добрался

Стало самому интересно в этой теме.

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

  uint8_t status, fifo_before, fifo_after;

  status = NRF24_ReadReg(STATUS);//STATUS
  if(status & RX_DR)
  {
    fifo_before = NRF24_ReadReg(FIFO_STATUS);//FIFO_STATUS
    NRF24_Read_Buf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);
    fifo_after = NRF24_ReadReg(FIFO_STATUS);//FIFO_STATUS
   
    printf("\n\rFIFO STATUS BEFORE: %d, FIFO STATUS AFTER: %d\n\r", fifo_before, fifo_after);
  }


выводит в терминал
FIFO STATUS BEFORE: 16, FIFO STATUS AFTER: 17


| RES | TX_REUSE | TX_FULL | TX_EMPTY | RES | RX_FULL | RX_EMPTY |
16 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
17 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |


следовательно, до чтения PAYLOAD флаг RX_EMPTY в регистре FIFO_STATUS установлен в "0" что означает, что в буфере FIFO есть данные, после чтения PAYLOAD флаг RX_EMPTY устанавливается в "1" - буфер пуст. Флаг RX_FULL находится в "0". я буфер не переполняю. Проверил возможность переполнения буфера - все отрабатывает как и описано в ДШ - устанавливается флаг RX_FULL .

Как дальше с этим жить я ХЗ. Максимально поднять скорость SPI NRF24l01 и перед сбросом флага

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

NRF24_WriteReg(STATUS, 0x40);
проверить бит RX_EMPTY на наличие несчитанных данных
Аватара пользователя
Serbis
Прорезались зубы
Сообщения: 211
Зарегистрирован: Чт авг 02, 2012 19:59:40

Re: Как правильно принимать данные у NRF24L01

Сообщение Serbis »

Ну в общем решил я проблему. Она оказалась сдвоенным косяком. Самым главным был косяк с тем, что как оказалось мьютексы во FreeRTOS при захвате в узких циклах из потоков в одинаковым приоритетом могут приводить к удушению одного из потоков :shock: . Это для меня, человека привыкшего к прелестям pthreads оказалось просто удивительно жутким фактом. Ну собственно происходило удушение одного из потоков на линии обработки данных, и получалась иллюзия того, что пакет один периодически не доходил. Но все же косяк с недоходом пакета из-за высокой скорости передатчика происходил, намного реже, но все же. После перелопачивания кучи чужого кода, пришел вот к такой конструкции.

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

bool NRF24_available() {
    uint8_t fs = NRF24_ReadReg(FIFO_STATUS);
    if (!(fs & _BV(0)))
       return true;

    return false;
}

//----------

int NRF24_Receive(uint8_t *payload)
{
   NRF24_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH);
   uint8_t status = NRF24_ReadReg(STATUS);
   NRF24_WriteReg(STATUS, status | 0x70);
   memcpy(payload, RX_BUF, TX_PLOAD_WIDTH);

   return TX_PLOAD_WIDTH;
}

Т е сначала проверяем есть ли данные, а потом читаем. После этого, все стало работать как хорошо отлаженные часы.
Ответить

Вернуться в «Цифровая техника»