It is currently Thu Dec 13, 2018 2:36 am

НИЛ АСЭМ Научно - исследовательская лаборатория автоматизированных систем экологического мониторинга

nRF24L01 2.4GHz Transceiver SPI - Data and Control Interface

by Admin » Wed Jun 27, 2018 1:36 pm

Дистанционное управление с помощью радиомодуля nRF24L01+

ImageImageImage
Фото различных типов модуля

Модуль NRF24L01 позволяет связать приборы радиоканалом передачи данных. С помощью NRF24L01 до семи приборов объединяются в общую радиосеть по топологии звезда. Чип передает данные на частоте от 2.400 до 2.525 ГГц в зависимости от выбранного канала, которых в NRF24L01 доступно 126 (ISM диапазон), шаг между соседними каналами составляет 1 МГц, используется модуляция GFSK. Один прибор в радиосети ведущий, остальные ведомые. В устройстве реализованы контрольные суммы, подтверждение передачи пакетов и повторная посылка в случае ошибки. За стабильную и надежную передачу и прием данных отвечает протокол Enhanced ShockBurst. Принимающее устройство должно давать ответ о приеме данных, подтверждая таким образом обратную связь. При упрощенном рассмотрении модуль приемопередатчика NRF24L01 является конвертером интерфейса SPI в радиосигнал, содержит приемник, передатчик и антенну.

Сфера применения модуля:
nRF24L01+ можно с успехом применять в следующих областях:
· Мобильная электроника;
· Компьютеры;
· Автоматизированные системы;
· Различные элементы «умного дома» — сигнализация, регулирование температуры и другие функции;
· Игры;
· Бытовая электроника.

Типичные применения трансиверов – беспроводные датчиковые сети. Простейшая схема такой сети, построенной на трансиверах nRF24AP1 показана ниже:

Image
Пример организации беспроводной датчиковой сети

На этом рисунке узлы сети S1-S3 выполняют роль беспроводных датчиков: они имеют в своем составе трансивер, аналоговый или цифровой датчик и микроконтроллер для обработки информации от подключенного датчика. В данном примере информация от таких беспроводных датчиков собирается одним узлом сети, называемым хабом. Этот узел может просто выводить информацию на LCD экран или передавать по проводной шине, либо передавать собранную информацию другим узлам беспроводной сети. Трансивер nRF24L01 целесообразно применять при необходимости передавать данные на сравнительно большой скорости. Некоторыми из применений этого трансивера можно назвать: передача потока информации с подвижных объектов, беспроводные пульты управления с обратной связью, беспроводная передача аудиосигнала, активная радиочастотная идентификация.

Характеристики модуля:
· Низкие затраты энергии;
· Наличие усовершенствованного ускорителя аппаратного протокола ShockBurst;
· Операционная система ISM;
· Скорость передачи данных 250 Кбит/с, 1 Мбит/с и 2 Мбит/с;
· Полная совместимость со всеми стандартными сериями nRF24L Nordic, а также сериями nRF24E и nRF240;
· Напряжение питания 3,3В;
· Рабочие температуры от -40С до 85С, температуры хранения от -40С до 125С;
· Дальность связи от 100 до 1100 м, в зависимости от типа модуля и антенны.

Микросхема nRF24L01+:

Image
Блок-схема микросхемы nRF24L01

В микросхему входят: синтезатор частоты, усилитель мощности, генератор, демодулятор, модулятор и другие части, образующие многофункциональный трансивер.Связь происходит в диапазоне частот 2,4–2,4835 ГГц. Частота, на которой будут работать модули, определяется номером канала. Они имеют шаг 1 МГц. Каналу 0 соответствует частота 2,4 ГГц, каналу 76 частота 2,476 ГГц. При скорости 250 Кбод связь возможна на большей дистанции. В режиме приема данных RX потребление тока выше, чем в режиме передачи TX. Модуль работает в четырех режимах: Power Down – выключен, Standby – спящий режим, RX Mode – приемник, TX Mode – передатчик. Микросхема nRF24L01+ имеет функции энергосбережения.

Надежный обмен данными гарантирует собственный протокол обмена Enhanced ShockBurst™. Прием данных подтверждает обратная связь в виде ответа. Принимающий данные модуль приемопередатчика 2.4 ГГц NRF24L01 отвечает подтверждением приема. Если подтверждение приема не получено, то передача повторяется.

Приемопередатчик – трансивер, имеет трехуровневый FIFO буфер приема, разделенный на шесть каналов, и трехуровневый FIFO буфер передачи. Одна микросхема nRF24L01+ конфигурируется как центральный принимающий узел и 6 как сообщающие данные. Такие обозначения функций до некоторой степени условны. На самом деле при любой роли МС в обмене данными каждая из них работает поочередно как приемник и передатчик. Обмен данными в такой сети происходит на одном частотном канале. Благодаря большому количеству каналов рядом могут работать еще 7 микросхем и еще и еще…

Image
Работа модуля в сети топологии звезда

В пакете передаваемых данных есть 9 бит идентификации после битов адреса. Первые 2 бита используются для индикации данных счетчика приема пакетов для контроля очередности приема. Остальные семь бит не используются и зарезервированы под будущие продукты.

Image
Структура пакетов данных для протоколов ShockBurst™ и Enhanced ShockBurst™

Это позволяет отслеживать правильную очередность приема пакетов информации. Для совместимости с микросхемами nRF2401, nRF24E1 и nRF905, nRF9E5 поле идентификации пакета может не использоваться. Количество повторных попыток передачи пакета задается программно. Если отправить пакет не удалось, то генерируется прерывание для контроллера, а в регистре статуса трансивера устанавливается бит MAX_RT. Для успешной передачи пакета вырабатывается сигнал прерывания (вывод TX_DS IRQ) и передающий FIFO буфер очищается.

Технология передачи данных в nRF24L01 следующая: анализируя адрес принятого пакета, приемник распознает, от какого передатчика этот пакет пришел. Как только приемник успешно принимает и идентифицирует пакет данных, он высылает пакет подтверждения приема с таким же адресом, как и принятый пакет. Если передатчик не получает этого подтверждения, он посылает пакет данных повторно. Количество повторных попыток передачи пакета можно задавать программно при конфигурации трансивера. Если отправить пакет так и не удалось, генерируется прерывание для контроллера, а в регистре статуса трансивера устанавливается бит MAX_RT. При успешной передачи пакета также вырабатывается сигнал прерывания (вывод TX_DS IRQ), а передающий FIFO буфер очищается.

Для настройки различных параметров и функций используются регистры микросхемы. Каждый регистр (кроме трех регистров полезной нагрузки) имеет 5-битный адрес, который маскируется в R_REGISTER и W_REGISTER инструкциями, соответственно чтение и запись.

Доступны следующие регистры:
CONFIG – настройка прерываний, контрольной суммы, питания и статуса Tx/Rx.
EN_AA – включение и отключение Enhanced ShockBurst ™ на отдельных каналах Rx.
EN_RXADDR – включение и отключение канала Rx.
SETUP_AW – длина адреса.
SETUP_RETR – настройка задержки повтора и количества попыток связаться, если не получено подтверждение приема.
RF_CH – установка радиочастотного канала.
RF_SETUP – настройка скорости передачи по эфиру, выходной мощности и коэффициента усиления.
STATUS – статус битов состояния прерывания, буфер Tx FIFO полный и количество каналов получивших пакеты.
OBSERVE_TX – количество потерянных и повторно переданных пакетов.
CD – обнаружение несущей частоты.
RX_ADDR_Pn – адрес для Rx канала n.
TX_ADDR – адрес назначения передаваемых пакетов.
RX_PW_Pn – величина постоянной нагрузки на Rx канал n.
FIFO_STATUS – статус автоповтора, буфер Tx FIFO полный / пустой, Rx FIFO полный / пустой.
ACK_PLD – полезная нагрузка отправки пакетов ответа, если ответы пакетов включены (записывается с указанием W_ACK_PAYLOAD).
TX_PLD – Тх FIFO (записывается с инструкциями W_TX_PAYLOAD и W_TX_PAYLOAD_NO_ACK).
RX_PLD – Rx FIFO (читается с инструкцией R_RX_PAYLOAD).
DYNPD – включить или отключить функцию динамического расчета полезной нагрузки на каналы Rx.
FEATURE – включение или отключение динамической полезной нагрузки, ACK полезной нагрузки, и селективные функции ACK.

Схема электрическая принципиальная модуля:
Image
Схема + антенный тракт модуля


Распиновка модуля:

Image

Помимо выходов питания линии сигналов могут подключаться к контактам с питающим напряжением 5 В. Такая совместимость обеспечена внутренними цепями микросхемы. Вход устройства, которое подключается к плате, должен потреблять ток не выше 10 мА.

Микросхема содержит следующие выходы:

GND – земля;
VCC – напряжение питания 3,3В
CE – высокий уровень микросхемы;
CSN – включение низкого уровня микросхемы. В этом случае устройство реагирует на SPI команды;
SCK – такт SPI, максимальное значение 10 МГц;
MOSI – передача информации от контроллера;
MISO – прием данных в контроллер;
IRQ – сигнал для аппаратного прерывания.

Подключение модуля:

Перед первым включением следует смонтировать на модуле 2 конденсатора. Между выводами VCC и GND припать конденсатор в SMD корпусе (планарный) емкостью 0,1 мкФ со стороны пайки к монтажным площадкам на плате, затем к ним припаять электролитический конденсатор емкостью 100 мкФ на напряжение 10 В. Питать модуль необходимо от отдельного стабилизатора напряжения 3,3 В, способного обеспечить ток нагрузки 200 мА.

В качестве примера использования данного радиомодуля приведу схему дистанционного управления двумя нагрузками (устройствами). Передатчик снабжен двумя кнопками и двумя светодиодами. Если горит синий, значит связь с приемником удовлетворительная и можно перейти смело к дистанционному управлению нагрузками. Если загорелся красный светодиод, то это значит, что связь с приемником нарушена, возможно вы вышли за радиус стабильной связи; когда связь будет возможна, загорится снова синий светодиод. Приемник, для примера, в качестве управляемой нагрузки содержит два светодиода. Таким образом, при нажатии на первую кнопку передатчика, загорится первый светодиод приемника; при нажатии второй кнопки передатчика, загорится второй светодиод приемника, соответственно.


Image Image
Схема передатчика + PCB

Image Image
Схема приемника + PCB


Image Image
Внешний вид разработанных устройств: слева - передатчик (TX), справа - приёмник (RX).
Вид сверху и вид снизу.


Управляющий код для микроконтроллера (на Proton BASIC Compiler):

1. Передатчик.
Code: Select all
'****************************************************************
'*  Notes   : Pressing and releasing a switch on the PTX        *
'*            toggles a LED on the PRX. The code is designed    *
'*            for DPL so PTX can send 1 to 32 data bytes        *
'*            dynamically LED on PTX indicates error            *
'****************************************************************

    Device = 16F877A
    Config FOSC_XT, WDTE_OFF, PWRTE_ON, BOREN_ON, LVP_OFF, CPD_OFF, WRT_OFF, DEBUG_OFF, CP_OFF
  Xtal = 4                       
  Declare All_Digital = True
  Declare Keep_Hex_File = On
  Declare Create_Coff = On

  Declare LCD_DTPin PORTD.4
  Declare LCD_RSPin PORTC.7
  Declare LCD_ENPin PORTC.6
  Declare LCD_Interface 4
  Declare LCD_Lines 2
  Declare LCD_Type 0

  Symbol NRF_IRQ  = PORTB.0       ' IRQ   
  Symbol NRF_CE   = PORTC.1       ' Controls Data transmit/receive
  Symbol NRF_CSN  = PORTC.2       ' "Chip Select Not"
  Symbol LED      = PORTD.0       ' LED
  Symbol SW1      = PORTD.1       ' Switch to GND pin has pullup

  'Symbol NRF_MISO  = PORTC.4       ' Master In Slave Out   
  'Symbol NRF_MOSI  = PORTC.5       ' Master Out Slave In   
  'Symbol NRF_CLK  = PORTC.3        ' Master Clock   

  TRISA  = 000000    ' A7=      A6=      A5=          A4=          A3=         A2=   A1=        A0=     
  TRISB  = 000001    ' B7=      B6=      B5=          B4=          B3=         B2=   B1=        B0=NRF_IRQ     
  TRISC  = 010000    ' C7=RS    C6=EN    C5=NRF_MOSI  C4=NRF_MISO  C3=NRF_CLK  C2=   C1=NRF_CE  C0=
  TRISD  = 000010    ' D7=LCD3  D6=LCD2  D5=LCD1      D4=LCD0      D3=         D2=   D1=SW1     D0=LED


'              +--------- WCOL: write collision detect
'              |+-------- SSPOV: Receive Overflow Indicator
'              ||+------- SSPEN: Synchronous Serial Port Enable
'              |||+------ CKP: Clock Polarity Select
'              ||||++++-- SSPM3:SSPM0: Synchronous Serial Port Mode
'              ||||||||   
'              ||||||||   1111 = I2C Slave mode, 10-bit address with Start and Stop bit interrupts enabled(2)
'              ||||||||   1110 = I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled(2)
'              ||||||||   1011 = I2C Firmware Controlled Master mode (slave Idle)(2)
'              ||||||||   1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))(2,3)
'              ||||||||   0111 = I2C Slave mode, 10-bit address(2)
'              ||||||||   0110 = I2C Slave mode, 7-bit address(2)
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0101 = SPI Slave mode, clock = SCK pin, SS pin control disabled, SS can be used As i/O pin(3)
'              ||||||||   0100 = SPI Slave mode, clock = SCK pin, SS pin control enabled(3)
'              ||||||||   0011 = SPI Master mode, clock = TMR2 Output/2(3,4)
'              ||||||||   0010 = SPI Master mode, clock = FOSC/64(3)
'              ||||||||   0001 = SPI Master mode, clock = FOSC/16(3)
'              ||||||||   0000 = SPI Master mode, clock = FOSC/4(3)
'              ||||||||
  SSPCON =    000010   ' SPI Mode
  Symbol SSPEN = SSPCON.5        ' SSP Enable bit


'              +--------- SMP: Sample position
'              |+-------- CKE: SPI clock polarity
'              ||+------- D/A: I2C only
'              |||+------ P:   I2C only
'              ||||+----- S:   I2C only
'              |||||+---- R/W: I2C only
'              ||||||+--- UA:  I2C only
'              |||||||+-- BF:  buffer full
'              ||||||||
  SSPSTAT =   000000   ' SPI Mode


'              +--------- RBPU 0=PORTB Pull-up Enable Bit
'              |+-------- INTEDG
'              ||+------- T0CS 1=Timer0 external Clock Source Select bit
'              |||+------ TOSE 1=low to high Timer0 Source Edge Select bit
'              ||||+----- PSA 0=assign Timer0 1=asigned to WDT
'              |||||+++-- PS2:PS0 Prescaler Select bits
'              ||||||||   111=1:256
'              ||||||||
'              ||||||||
 OPTION_REG    = 000111


'              +--------- GIE: 1=Enables all unmasked interrupts                    IPEN=0 (default)
'              |+-------- PEIE: 1=Enables all unmasked peripheral interrupts        IPEN=0 (default)
'              ||+------- TMR0IE: 1=Enables the TMR0 overflow interrupt
'              |||+------ INTE: 1=Enables the INT0 external interrup
'              ||||+----- RBIE: 1=Enables the RB port change interrupt
'              |||||+---- TMR0IF: 1=TMR0 register has overflowed (must be cleared in software)
'              ||||||+--- INTF: 1=The INT0 external interrupt occurred (must be cleared in software)
'              |||||||+-- RBIF: 1=At least one of the RB7:RB4 pins changed state (must be cleared in software)
'              ||||||||
  INTCON =    100000   ' GIE and TMR0IE
  Symbol TMR0IF  = INTCON.2       ' TMR0 Overflow Interrupt Flag bit


'              +--------- SPPIF: 1=Streaming Parallel Port Read/Write Interrupt occurred
'              |+-------- ADIF: 1=A/D Converter Interrupt completed
'              ||+------- RCIF: 1=EUSART Receive Interrupt occurred (EUSART receive buffer, RCREG, is full)
'              |||+------ TXIF: 1=EUSART Transmit Interrupt Flag occurred (EUSART transmit buffer, TXREG, is empty)
'              ||||+----- SSPIF: 1=Master Synchronous Serial Port Interrupt occurred (transmission/reception is complete)
'              |||||+---- CCP1IF: 1=CCP1 Interrupt Flag bit TMR1 register capture/compare occurred
'              ||||||+--- TMR2IF: 1=TMR2 to PR2 Match Interrupt occurred
'              |||||||+-- TMR1IF: 1=TMR1 Overflow Interrupt occurred
'              ||||||||
    PIR1    = 000000   '
  Symbol SSPIF = PIR1.3           ' interrupt flag - last bit set   

   
  Symbol W_REGISTER         = 0x20                ' Address 0 Write Register command
  Symbol R_REGISTER         = 0x00                ' Address 0 Read Register command
  Symbol R_RX_PAYLOAD       = 0x61                ' Read RX spi_array
  Symbol W_TX_PAYLOAD       = 0xA0                ' Write TX spi_array
  Symbol FLUSH_TX           = 0xE1                ' Flush TX FIFO
  Symbol FLUSH_RX           = 0xE2                ' Flush RX FIFO
  Symbol REUSE_TX_PL        = 0xE3                ' Reuse last sent spi_array
  Symbol R_RX_PL_WID        = 0x60                ' read RX spi_array width for the top Rx spi_array in the FIFO
  Symbol W_ACK_PAYLOAD      = 0xA8                ' RX mode: write spi_array to be transmitted with ACK packet mask for last 3 bits in range 000 - 101
  Symbol W_TX_PAYLOAD_NOACK = 0xB0                ' Disable auto ACK on the specific packet
  Symbol NRF_NOP            = 0xFF                ' Reuse last sent spi_array
  Symbol TO16_50MS = 58        ' Prescaler 1:256; TMR0 Preload = 58; Actual Interrupt Time : 49.922 ms


'====================================   
    GoTo Main
'====================================
'
  Dim rxled_state As Bit                          ' the state of the rx LED
  Dim i As Byte                                   ' index for loops and arrays
  Dim temp_byte As Byte
  Dim nrf_ptr As Byte                             ' array pointer
  Dim spi_array[16] As Byte                       ' SPI transmit array
  Dim nrf_inx As Byte                             ' SPI loop index
  Dim nrf_channel As Byte                         ' intialize with default value
  Dim nrf_address As Dword                        ' Pipe 0 4 byte address - real address be read from EEPROM
  Dim nrf_rfsetup As Byte
  Dim nrf_setretr As Byte
  Dim NRF_Status As Byte                          ' status byte
  Dim nrf_errf As Byte                            ' error flgas

SPI_NRF:       
  nrf_inx = 0
  Repeat
    SSPBUF = spi_array[nrf_inx]                 ' put the output byte in the buffer
    While SSPIF = 0 : Wend                      ' wait for end of transaction
    SSPIF = 0                                   ' clear the SSP flag
    spi_array[nrf_inx] = SSPBUF                 ' read the input buffer, the status is always in spi_array[0]
    Inc nrf_inx               
  Until nrf_inx > nrf_ptr                         ' nrf_ptr must be sent with the command so we know how many bytes to transfer
  Return   
'
Load_NRF:
  nrf_channel = 0x02                              ' Channel #2
  nrf_address = 0xCFE7E7CF                        ' some address
  nrf_rfsetup = 0x26                              ' 00100110 => 250kbps, 0dBm
  nrf_setretr = 0x58                              ' 01010100 => ARD = 1500uS, ARC = 8
  Return

Init_PTX:

'REG 00 CONFIG
'              +--------- Reserved 0
'              |+-------- MASK_RX_DR: 0=Reflect RX_DR as active Low Interrupt On the IRQ pin
'              ||+------- MASK_TX_DS: 0=Reflect TX_DS as active low interrupt on the IRQ pin
'              |||+------ MASK_MAX_RT: 0=Reflect MAX_RT as active low interrupt on the IRQ pin
'              ||||+----- EN_CRC: Enable CRC. Forced high if one of the bits in the EN_AA is high
'              |||||+---- CRCO: CRC encoding scheme '0' - 1 byte   '1' – 2 bytes
'              ||||||+--- PWR_UP: 1:POWER UP, 0:POWER DOWN
'              |||||||+-- PRIM_RX: RX/TX control 1:PRX, 0:PTX
'              ||||||||
'   CONFIG  = 001100

  NRF_CE = 0                                      ' Clear NRF_CE so we can Write to NRF in Standby mode
  NRF_CSN = 0
  spi_array[0] = W_REGISTER                       ' W_REGISTER at address 0x00 => CONFIG
  spi_array[1] = 0x4C                             ' 01001000 PTX, PWR_Dn, CRC 2 byte, CRC enabled, MASK_MAX_RT, MASK_TX_DS intterupts reflected on NRF_IRQ
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1   
'----------------------------------------   
'REG 01 EN_AA   
'              ++-------- Reserved 00
'              ||+------- ENAA_P5: Enable auto ack data pipe 5
'              |||+------ ENAA_P4: Enable auto ack data pipe 4
'              ||||+----- ENAA_P3: Enable auto ack data pipe 3
'              |||||+---- ENAA_P2: Enable auto ack data pipe 2
'              ||||||+--- ENAA_P1: Enable auto ack data pipe 1
'              |||||||+-- ENAA_P0: Enable auto ack data pipe 0
'              ||||||||
'   EN_AA   = 000001

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x01                ' W_REGISTER At address 0x01 => EN_AA
  spi_array[1] = 0x01                             ' Enable auto-ack on pipes 0 , TX mode
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 03 SETUP AW
'              ++++++---- Reserved 000000
'              ||||||++-- AW: 10 = 4bytes
'              ||||||||
'   SETUP_AW= 000010

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x03                ' W_REGISTER at address 0x03 => SETUP AW
  spi_array[1] = 0x02                             ' Address width = 4 bytes
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 04 SETUP RETR
'              ++++------ ARD: auto retransmit delay 0000=250us  0101=1500us
'              ||||++++-- ARC: 11 = Up tp 3 Re-transmit on fail of AA
'              ||||||||
'SETUP_RETR = 011000

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x04                ' W_REGISTER at address 0x04 => SETUP RETR
  spi_array[1] = nrf_setretr                      ' auto retransmit values loaded frm LUT  x038
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1 
'----------------------------------------   
'REG 05 RF_CH
'              +--------- Reserved 0
'              |+++++++-- RF_CH: Sets the frequency channel nRF24L01+ operates on
'              ||||||||
'   RF_CH   = 000010

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x05                ' W_REGISTER at address 0x05 => RF_CH
  spi_array[1] = nrf_channel                      ' default channel = 2
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------     
'REG 06 RF_SETUP
'              +--------- CONT_WAVE: enable continuous carrier
'              |+-------- Reserved 0
'              ||+------- RF_DR_LOW: Set RF Data Rate to 250kbps
'              |||+------ PLL_LOCK: testing only
'              ||||+----- RF_DR_HIGH: Air data rate ‘00’ – 1Mbps ‘01’ – 2Mbps ‘10’ – 250kbps ‘11’ – Reserved
'              |||||++--- RF_PWR: RF output power in TX mode 00=18dBm 01=12dBm 10=6dBm 11=0dBm
'              |||||||+-- Obsolete 0
'              ||||||||
'  RF_SETUP = 100110

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x06                ' W_REGISTER at address 0x06 => RF_SETUP    x026
  spi_array[1] = nrf_rfsetup                      ' 0x02 = DR 1Mbps, RF_POWER -12dBm, 0x26 = DR 250kbps, RF_POWER 0dBm
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1   
'----------------------------------------   
'REG 07 STATUS
'              +--------- Reserved 0
'              |+-------- RX_DR: Data Ready RX FIFO interrupt. Write 1 to clear
'              ||+------- TX_DS: Data Sent TX FIFO interrupt. Write 1 To Clear
'              |||+------ MAX_RT: Maximum number of TX retransmits interrupt. Write 1 To Clear
'              ||||+++--- RX_P_NO: Data pipe number for the payload available for reading from RX_FIF
'              |||||||+-- TX_FULL: TX FIFO full flag.
'              ||||||||
'   STATUS  = 110000

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x07                ' W_REGISTER at address 0x07 => STATUS
  spi_array[1] = 0x70                             ' Clear RX_DR, TX_DS and  MAX_RT Interrupts 110000
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1   
'----------------------------------------     
'REG 10 TX_ADDR
  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x10                ' W_REGISTER at address 0x10 => TX_ADDR
  spi_array[1] = nrf_address.Byte0                ' RX address byte 0 LSByte
  spi_array[2] = nrf_address.Byte1                ' RX address byte 1
  spi_array[3] = nrf_address.Byte2                ' RX address byte 2
  spi_array[4] = nrf_address.Byte3                ' RX address byte 3
  nrf_ptr = 4
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 0A RX_ADDR_P0 (Only if ACK is to be received into pipe 0)   
  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x0A                ' W_REGISTER at address 0x0A => RX_ADDR_P0
  spi_array[1] = nrf_address.Byte0                ' RX address byte 0 LSByte
  spi_array[2] = nrf_address.Byte1                ' RX address byte 1
  spi_array[3] = nrf_address.Byte2                ' RX address byte 2
  spi_array[4] = nrf_address.Byte3                ' RX address byte 3
  nrf_ptr = 4
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------         
'REG 0x1C DYNPD   
'              ++-------- Reserved 00
'              ||+------- DPL_P5: Enable dynamic payload length data pipe 5.
'              |||+------ DPL_P4: Enable dynamic payload length data pipe 4.
'              ||||+----- DPL_P3: Enable dynamic payload length data pipe 3.
'              |||||+---- DPL_P2: Enable dynamic payload length data pipe 2.
'              ||||||+--- DPL_P1: Enable dynamic payload length data pipe 1.
'              |||||||+-- DPL_P0: Enable dynamic payload length data pipe 0.
'              ||||||||
'  DYNPD    = 000001

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x1C                ' W_REGISTER at address $1C => DYNPD (Dynamic Payload)
  spi_array[1] = 0x01                             ' enable dynamic payload on Pipe0
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------       
'REG 0x1D FEATURE   
'              +++++----- Reserved 00000
'              |||||+---- EN_DPL: Enables Dynamic Payload Length
'              ||||||+--- EN_ACK_PAY: Enables Payload with ACK
'              |||||||+-- EN_DYN_ACK: Enables the W_TX_PAYLOAD_NOACK command
'              ||||||||
'   FEATURE = 000110

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x1D                ' W_REGISTER at address $1D => FEATURE
  spi_array[1] = 0x06                             ' 0x04 If we don't need ack with payload  Set Bit 1 (EN_ACK_PAY) To Enable payload with ACK
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1     
  '----------------------------------------       
  Return   
'
FLUSH_TX_FIFO:                                      ' flush all TX FIFO slots 
  spi_array[0] = FLUSH_TX
  nrf_ptr = 0
  NRF_CSN = 0
  GoSub SPI_NRF
  NRF_CSN = 1
  Return   


'              +--------- Reserved 0
'              |+-------- MASK_RX_DR: 0=Reflect RX_DR as active Low Interrupt On the IRQ pin
'              ||+------- MASK_TX_DS: 0=Reflect TX_DS as active low interrupt on the IRQ pin
'              |||+------ MASK_MAX_RT: 0=Reflect MAX_RT as active low interrupt on the IRQ pin
'              ||||+----- EN_CRC: Enable CRC. Forced high if one of the bits in the EN_AA is high
'              |||||+---- CRCO: CRC encoding scheme '0' - 1 byte   '1' – 2 bytes
'              ||||||+--- PWR_UP: 1:POWER UP, 0:POWER DOWN
'              |||||||+-- PRIM_RX: RX/TX control 1:PRX, 0:PTX
'              ||||||||
'   CONFIG  = 001100   
'
NRF_PWRDN:                                          ' power Down
  NRF_CSN = 0                                     ' enable Slave
  spi_array[0] = W_REGISTER                       ' W_REGISTER at address $00 => CONFIG
  spi_array[1] = 0x4C                             ' PTX, PWR_DN, CRC 2 Byte, CRC enabled, MASK_MAX_RT, MASK_TX_DS intterupts reflected On NRF_IRQ
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1                         
  Return


'              +--------- Reserved 0
'              |+-------- MASK_RX_DR: 0=Reflect RX_DR as active Low Interrupt On the IRQ pin
'              ||+------- MASK_TX_DS: 0=Reflect TX_DS as active low interrupt on the IRQ pin
'              |||+------ MASK_MAX_RT: 0=Reflect MAX_RT as active low interrupt on the IRQ pin
'              ||||+----- EN_CRC: Enable CRC. Forced high if one of the bits in the EN_AA is high
'              |||||+---- CRCO: CRC encoding scheme '0' - 1 byte   '1' – 2 bytes
'              ||||||+--- PWR_UP: 1:POWER UP, 0:POWER DOWN
'              |||||||+-- PRIM_RX: RX/TX control 1:PRX, 0:PTX
'              ||||||||
'   CONFIG  = 101110   

TX_POWERUP:                                         ' Power up
  spi_array[0] = W_REGISTER                       ' CONFIG Register
  spi_array[1] = 0x4E                             ' PTX, PWR UP, CRC 2 Byte, CRC enabled, MASK_MAX_RT, MASK_TX_DS intterupts reflected On NRF_IRQ
  nrf_ptr = 1
  NRF_CSN = 0
  GoSub SPI_NRF
  NRF_CSN = 1
  DelayUS 3000                                    ' Critical! min 1500uS Tpd2stby delay
  GoSub FLUSH_TX_FIFO
  Return
'
READ_NRF_STATUS:                                    ' read STATUS for Interrupt source
  spi_array[0] = R_REGISTER | 0x07                ' Read Register $07 => STATUS
  nrf_ptr = 0
  NRF_CSN = 0
  GoSub SPI_NRF 
  NRF_CSN = 1   
  Print At 1, 12, Hex2 spi_array[0]
  NRF_Status = (spi_array[0] >> 4) & 7            ' shift and mask so we have bits 6:4 in place [2:0] bit2=RX_DR, bit1 = TX_DS, bit0 = MAX_RT       
  Return

CLR_NRF_INT:                                        ' Clear Interrupts   
  spi_array[0] = W_REGISTER | 0x07                ' W_REGISTER at address $07 => STATUS
  spi_array[1] = 0x70                             ' Clear all Interrupts
  nrf_ptr = 1
  NRF_CSN = 0
  GoSub SPI_NRF 
  NRF_CSN = 1   
  Return           
'
NRF_Transmit:
  spi_array[0] = W_TX_PAYLOAD                     ' TX payload command
  spi_array[1] = temp_byte
  nrf_ptr = 1
  NRF_CSN = 0
  GoSub SPI_NRF
  NRF_CSN = 1
  High NRF_CE                                     ' transmit
  DelayUS 20
  Low NRF_CE
  '
  nrf_errf = 0                                    ' clear error flag here
  TMR0 = TO16_50MS                                ' load Timer0 register with preset value of 50mS                           
  TMR0IF = 0                                      ' clear TMR0 flag 
  While NRF_IRQ = 1                               ' wait for NRF_IRQ pin goes low
    If TMR0IF = 1 Then                            ' timer elapsed before IRQ = timeout
      nrf_errf = 0x0F                             ' set the error flags to 15so LED will flash 8 times
      NRF_Status = 0
      Return
    EndIf
  Wend                 
  '
  GoSub READ_NRF_STATUS                           ' read STATUS for Interrupt source and shif >> 4 to lower nible NRF_Status.2 = RX_DR, NRF_Status.1 = TX_DS, NRF_Status.0 = MAX_RT
  GoSub CLR_NRF_INT                               ' Clear Interrupts
  If NRF_Status = 0x02 Then Return                ' good Ack no payload = 0x02       
  If NRF_Status = 0x06 Then                       ' good Ack with payload
    nrf_ptr = 3
    NRF_CSN = 0
    Clear spi_array                         
    spi_array[0] = R_RX_PAYLOAD             ' Read Rx payload command
    GoSub SPI_NRF
    NRF_CSN = 1
    Print At 2, 1, "ACK pload=", spi_array[0], spi_array[1], spi_array[2], spi_array[3]
  End If
  If NRF_Status.0 = 0x01 Then nrf_errf = 4        ' MAX_RT no ack LED flash twice
  Return
  '
'---[main control loop]--------------   
Main:
  DelayMS 100
  Cls
  Print At 1, 1, "TX..STATUS="
  Low LED   
  High NRF_CSN                                    ' unselect NRF slave
  Low NRF_CE                                      ' clear CE until we start working   
  SSPEN = 1                                       ' Enable SPI   
  DelayMS 250
  GoSub Load_NRF
  GoSub Init_PTX                 
  '
  rxled_state = 0
  '
  While 1 = 1
    If SW1 = 0 Then                           ' add which ever anti bounce needed
      High LED
      rxled_state = ~rxled_state              ' to toggle the LED on the Rx
      temp_byte = 0x30 + rxled_state          ' ON = "1" Off = "0"
      GoSub TX_POWERUP                        ' powerup the nrf the first target command is protected in a buffer
      GoSub NRF_Transmit
      'Print At 2, 1, "ACK pload=", spi_array[0], spi_array[1], spi_array[2], spi_array[3]
      '
      If nrf_errf != 0 Then                   ' error indicator
        For i = 0 To nrf_errf                 ' two flashed = no ack, 8 flashed = timeout - the PTX is not working
          LED = ~LED
          DelayMS 100
        Next
      EndIf
      GoSub NRF_PWRDN                         ' power down the NRF
      DelayMS 200
      Low LED
      Clear spi_array
      While SW1 = 0 : Wend                    ' wait to release switch
    EndIf
      'DelayMS 200                             ' loop delay
  Wend

2. Приёмник.
Code: Select all
'****************************************************************
'*  Notes   : A LED on the PTX is turned ON by receiveing       *
'*          : ASCI "1" from PTX or OFF by receiveing "0"        *
'*          : The code is designed for DPL so 1 to 32 Bytes     *
'*          : can be received                                   *
'****************************************************************
    Device = 16F877A
    Config FOSC_XT, WDTE_OFF, PWRTE_ON, BOREN_ON, LVP_OFF, CPD_OFF, WRT_OFF, DEBUG_OFF, CP_OFF
  Xtal = 4                       
  Declare All_Digital = True
  Declare Keep_Hex_File = On
  Declare Create_Coff = On

  Declare LCD_DTPin PORTD.4
  Declare LCD_RSPin PORTC.7
  Declare LCD_ENPin PORTC.6
  Declare LCD_Interface 4
  Declare LCD_Lines 2
  Declare LCD_Type 0

  Symbol NRF_IRQ  = PORTB.0       ' IRQ   
  Symbol NRF_CE   = PORTC.1       ' Controls Data transmit/receive
  Symbol NRF_CSN  = PORTC.2       ' "Chip Select Not"
  Symbol LED      = PORTD.0       ' LED
  Symbol SW1      = PORTD.1       ' Switch to GND pin has pullup

  Symbol NRF_MISO = PORTC.4       ' Master In Slave Out   Fixed when using MSSP
  Symbol NRF_MOSI = PORTC.5       ' Master Out Slave In   
  Symbol NRF_CLK  = PORTC.3        ' Master Clock   

  TRISA  = 000000    ' A7=      A6=      A5=          A4=          A3=         A2=   A1=        A0=     
  TRISB  = 000001    ' B7=      B6=      B5=          B4=          B3=         B2=   B1=        B0=NRF_IRQ     
  TRISC  = 010000    ' C7=RS    C6=EN    C5=NRF_MOSI  C4=NRF_MISO  C3=NRF_CLK  C2=   C1=NRF_CE  C0=
  TRISD  = 000010    ' D7=LCD3  D6=LCD2  D5=LCD1      D4=LCD0      D3=         D2=   D1=SW1     D0=LED


'              +--------- WCOL: write collision detect
'              |+-------- SSPOV: Receive Overflow Indicator
'              ||+------- SSPEN: Synchronous Serial Port Enable
'              |||+------ CKP: Clock Polarity Select
'              ||||++++-- SSPM3:SSPM0: Synchronous Serial Port Mode
'              ||||||||   
'              ||||||||   1111 = I2C Slave mode, 10-bit address with Start and Stop bit interrupts enabled(2)
'              ||||||||   1110 = I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled(2)
'              ||||||||   1011 = I2C Firmware Controlled Master mode (slave Idle)(2)
'              ||||||||   1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))(2,3)
'              ||||||||   0111 = I2C Slave mode, 10-bit address(2)
'              ||||||||   0110 = I2C Slave mode, 7-bit address(2)
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0010 = Master FOSC/64
'              ||||||||   0101 = SPI Slave mode, clock = SCK pin, SS pin control disabled, SS can be used As i/O pin(3)
'              ||||||||   0100 = SPI Slave mode, clock = SCK pin, SS pin control enabled(3)
'              ||||||||   0011 = SPI Master mode, clock = TMR2 Output/2(3,4)
'              ||||||||   0010 = SPI Master mode, clock = FOSC/64(3)
'              ||||||||   0001 = SPI Master mode, clock = FOSC/16(3)
'              ||||||||   0000 = SPI Master mode, clock = FOSC/4(3)
'              ||||||||
  SSPCON =    000010   ' SPI Mode
  Symbol SSPEN = SSPCON.5        ' SSP Enable bit


'              +--------- SMP: Sample position
'              |+-------- CKE: SPI clock polarity
'              ||+------- D/A: I2C only
'              |||+------ P:   I2C only
'              ||||+----- S:   I2C only
'              |||||+---- R/W: I2C only
'              ||||||+--- UA:  I2C only
'              |||||||+-- BF:  buffer full
'              ||||||||
  SSPSTAT =   000000   ' SPI Mode


'              +--------- GIE: 1=Enables all unmasked interrupts                    IPEN=0 (default)
'              |+-------- PEIE: 1=Enables all unmasked peripheral interrupts        IPEN=0 (default)
'              ||+------- TMR0IE: 1=Enables the TMR0 overflow interrupt
'              |||+------ INT0IE: 1=Enables the INT0 external interrup
'              ||||+----- RBIE: 1=Enables the RB port change interrupt
'              |||||+---- TMR0IF: 1=TMR0 register has overflowed (must be cleared in software)
'              ||||||+--- INT0IF: 1=The INT0 external interrupt occurred (must be cleared in software)
'              |||||||+-- RBIF: 1=At least one of the RB7:RB4 pins changed state (must be cleared in software)
'              ||||||||
  INTCON =    100000   ' GIE and TMR0IE
  Symbol TMR0IF  = INTCON.2       ' TMR0 Overflow Interrupt Flag bit


'              +--------- PSPIF: 1=Streaming Parallel Port Read/Write Interrupt occurred
'              |+-------- ADIF: 1=A/D Converter Interrupt completed
'              ||+------- RCIF: 1=EUSART Receive Interrupt occurred (EUSART receive buffer, RCREG, is full)
'              |||+------ TXIF: 1=EUSART Transmit Interrupt Flag occurred (EUSART transmit buffer, TXREG, is empty)
'              ||||+----- SSPIF: 1=Master Synchronous Serial Port Interrupt occurred (transmission/reception is complete)
'              |||||+---- CCP1IF: 1=CCP1 Interrupt Flag bit TMR1 register capture/compare occurred
'              ||||||+--- TMR2IF: 1=TMR2 to PR2 Match Interrupt occurred
'              |||||||+-- TMR1IF: 1=TMR1 Overflow Interrupt occurred
'              ||||||||
    PIR1    = 000000   '
  Symbol SSPIF = PIR1.3           ' interrupt flag - last bit set   


  Symbol W_REGISTER         = 0x20        ' Address 0 Write Register command
  Symbol R_REGISTER         = 0x00        ' Address 0 Read Register command
  Symbol R_RX_PAYLOAD       = 0x61        ' Read RX spi_array
  Symbol W_TX_PAYLOAD       = 0xA0        ' Write TX spi_array
  Symbol FLUSH_TX           = 0xE1        ' Flush TX FIFO
  Symbol FLUSH_RX           = 0xE2        ' Flush RX FIFO
  Symbol REUSE_TX_PL        = 0xE3        ' Reuse last sent spi_array
  Symbol R_RX_PL_WID        = 0x60        ' read RX spi_array width for the top Rx spi_array in the FIFO
  Symbol W_ACK_PAYLOAD      = 0xA8        ' RX mode: write spi_array to be transmitted with ACK packet mask for last 3 bits in range 000 - 101
  Symbol W_TX_PAYLOAD_NOACK = 0xB0        ' Disable auto ACK on the specific packet
  Symbol NRF_NOP            = 0xFF        ' Reuse last sent spi_array

  Dim temp_byte As Byte
  Dim nrf_inx As Byte                     ' SPI loop index
  Dim nrf_ptr As Byte                     ' array pointer
  Dim nrf_channel As Byte                 ' intialize with default value
  Dim nrf_address As Dword                ' Pipe 0 4 byte address - real address be read from EEPROM
  Dim nrf_rfsetup As Byte
  Dim nrf_setretr As Byte
  Dim ack_dataout As Byte                 ' for sending only 1 byte payload with ack
  Dim nrf_errf As Byte                    ' error flgas
  Dim NRF_Status As Byte                  ' status byte
  Dim DataOut[16] As Byte                 ' array for Ackpayload
  Dim DataIn[16] As Byte                  ' general array
  Dim spi_array[16] As Byte               ' SPI transmit array
  Dim DummyCount As Word


'==================================   
  GoTo MAIN                               '
'==================================
'   
Load_NRF:
  nrf_channel = 0x02                      ' Channel #2
  nrf_address = 0xCFE7E7CF                ' some address
  nrf_rfsetup = 0x26                      ' 00100110 => 250kbps, 0dBm
  nrf_setretr = 0x58                      ' 00100100 => ARD = 1500uS, ARC = 8
  Return
'
'---[SPI sub for the NRF24L01+]-------------
SPI_NRF:       
  nrf_inx = 0
  Repeat
    SSPBUF = spi_array[nrf_inx]         ' put the output byte in the buffer
    While SSPIF = 0 : Wend              ' wait for end of transaction
    SSPIF = 0                           ' clear the SSP flag
    spi_array[nrf_inx] = SSPBUF         ' read the input buffer, the status is always in spi_array[0]
    Inc nrf_inx               
  Until nrf_inx > nrf_ptr                 ' nrf_ptr must be sent with the command so we know how many bytes to transfer
  Return   

'=========================================
Init_PRX:

'REG 00 CONFIG   
'              +--------- Reserved 0
'              |+-------- MASK_RX_DR: 0=Reflect RX_DR as active Low Interrupt On the IRQ pin
'              ||+------- MASK_TX_DS: 0=Reflect TX_DS as active low interrupt on the IRQ pin
'              |||+------ MASK_MAX_RT: 0=Reflect MAX_RT as active low interrupt on the IRQ pin
'              ||||+----- EN_CRC: Enable CRC. Forced high if one of the bits in the EN_AA is high
'              |||||+---- CRCO: CRC encoding scheme '0' - 1 byte   '1' – 2 bytes
'              ||||||+--- PWR_UP: 1:POWER UP, 0:POWER DOWN
'              |||||||+-- PRIM_RX: RX/TX control 1:PRX, 0:PTX
'              ||||||||
'   CONFIG  = 111001 

  NRF_CE = 0                              ' standby mode
  NRF_CSN = 0                     
  spi_array[0] = W_REGISTER               ' W_REGISTER at address $00 => CONFIG
  spi_array[1] = 0x39                     ' PRX, PWR DOWN,CRC = 2 Byte, CRC Enable, RX_DR INT
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 01 EN_AA   
'              ++-------- Reserved 00
'              ||+------- ENAA_P5: Enable auto ack data pipe 5
'              |||+------ ENAA_P4: Enable auto ack data pipe 4
'              ||||+----- ENAA_P3: Enable auto ack data pipe 3
'              |||||+---- ENAA_P2: Enable auto ack data pipe 2
'              ||||||+--- ENAA_P1: Enable auto ack data pipe 1
'              |||||||+-- ENAA_P0: Enable auto ack data pipe 0
'              ||||||||
'   EN_AA   = 000001   '

  NRF_CSN = 0 
  spi_array[0] = W_REGISTER | 0x01        ' W_REGISTER at address $01 => EN_AA
  spi_array[1] = 0x01                     ' enable auto-ack only for pipe 0
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 02 EN_RXADDR   
'              ++-------- Reserved 00
'              ||+------- ERX_P5:
'              |||+------ ERX_P4:
'              ||||+----- ERX_P3:
'              |||||+---- ERX_P2:
'              ||||||+--- ERX_P1:
'              |||||||+-- ERX_P0:
'              ||||||||
'  EN_RXADDR= 000001

  NRF_CSN = 0 
  spi_array[0] = W_REGISTER | 0x02        ' W_REGISTER at address $02 => EN_RXADDR
  spi_array[1] = 0x01                     ' enable only pipe 0
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 03 SETUP_AW     
'              ++++++---- Reserved 000000
'              ||||||++-- AW: 10 = 4bytes
'              ||||||||
'   SETUP_AW= 000010

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x03        ' W_REGISTER at address $03 => SETUP AW
  spi_array[1] = 0x02                     ' address width = 4 bytes
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------
'REG 05 RF_CH   
'              +--------- Reserved 0
'              |+++++++-- RF_CH: Sets the frequency channel nRF24L01+ operates on
'              ||||||||
'   RF_CH   = 000010

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x05        ' W_REGISTER at address $05 => RF_CH
  spi_array[1] = nrf_channel              ' set channel to variable
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 06 RF_SETUP                            ' note - reduce power and increase speed in final app
'              +--------- CONT_WAVE: enable continuous carrier
'              |+-------- Reserved 0
'              ||+------- RF_DR_LOW: Set RF Data Rate to 250kbps
'              |||+------ PLL_LOCK: testing only
'              ||||+----- RF_DR_HIGH: Air data rate ‘00’ – 1Mbps ‘01’ – 2Mbps ‘10’ – 250kbps ‘11’ – Reserved
'              |||||++--- RF_PWR: RF output power in TX mode 00=18dBm 01=12dBm 10=6dBm 11=0dBm
'              |||||||+-- Obsolete 0
'              ||||||||
'  RF_SETUP = 100110

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x06        ' W_REGISTER at address $06 => RF_SETUP
  spi_array[1] = nrf_rfsetup              ' 0x02 = DR 1Mbps, RF_POWER -12dBm, 0x26 = DR 250kbps, RF_POWER 0dBm
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------   
'REG 07 STATUS   
'              +--------- Reserved 0
'              |+-------- RX_DR: Data Ready RX FIFO interrupt. Write 1 to clear
'              ||+------- TX_DS: Data Sent TX FIFO interrupt. Write 1 To Clear
'              |||+------ MAX_RT: Maximum number of TX retransmits interrupt. Write 1 To Clear
'              ||||+++--- RX_P_NO: Data pipe number for the payload available for reading from RX_FIF
'              |||||||+-- TX_FULL: TX FIFO full flag.
'              ||||||||
'   STATUS  = 111110

  spi_array[0] = W_REGISTER | 0x07        ' W_REGISTER at address $27 => STATUS
  spi_array[1] = 0x7E                     ' Clear Interrupts
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1   
'----------------------------------------             
'REG 08 OBSERVE_TX
'              ++++------ PLOS_CNT: count lost packets. Reset by writing to RF_CH.
'              ||||++++-- ARC_CNT: Count retransmitted packets. The counter is reset when tx of a new packet starts
'              ||||||||
'OBSERVE_TX = 100110

'----------------------------------------
'REG 09 RPD
'              +++++++--- Reserved 0000000
'              |||||||+-- RPD: Received Power Detector
'              ||||||||
'       RPD = 100110

'----------------------------------------
'REG 0A RX_ADDR_P0  (length set by AW - 4 bytes)         

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x0A        ' W_REGISTER at address $0A => RX_ADDR_P0
  spi_array[1] = nrf_address.Byte0        ' RX address byte 0 LSByte
  spi_array[2] = nrf_address.Byte1        ' RX address byte 1
  spi_array[3] = nrf_address.Byte2        ' RX address byte 2
  spi_array[4] = nrf_address.Byte3        ' RX address byte 3
  nrf_ptr = 4
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------
'REG 11 RX_PW_PO   
'              ++-------- Reserved 00
'              ||++++++-- RX_PW_P0: Number of bytes in RX payload in data pipe 0 (1 to 32 bytes). 0 Pipe not used
'              ||||||||
'  RX_PW_PO = 000100

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x11        ' W_REGISTER at address $11 => RX_PW_PO
  spi_array[1] = 0x04                     ' 4 byte payload width on Pipe0
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------         
'REG 0x1C DYNPD   
'              ++-------- Reserved 00
'              ||+------- DPL_P5: Enable dynamic payload length data pipe 5.
'              |||+------ DPL_P4: Enable dynamic payload length data pipe 4.
'              ||||+----- DPL_P3: Enable dynamic payload length data pipe 3.
'              |||||+---- DPL_P2: Enable dynamic payload length data pipe 2.
'              ||||||+--- DPL_P1: Enable dynamic payload length data pipe 1.
'              |||||||+-- DPL_P0: Enable dynamic payload length data pipe 0.
'              ||||||||
'  DYNPD    = 000001

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x1C        ' W_REGISTER at address $1C => DYNPD (Dynamic Payload)
  spi_array[1] = 0x01                     ' enable dynamic payload on Pipe0
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------       
'REG 0x1D FEATURE   
'              +++++----- Reserved 00000
'              |||||+---- EN_DPL: Enables Dynamic Payload Length
'              ||||||+--- EN_ACK_PAY: Enables Payload with ACK
'              |||||||+-- EN_DYN_ACK: Enables the W_TX_PAYLOAD_NOACK command
'              ||||||||
'   FEATURE = 000110

  NRF_CSN = 0
  spi_array[0] = W_REGISTER | 0x1D        ' W_REGISTER at address $1D => FEATURE
  spi_array[1] = 0x06                     ' set bit 2 (EN_DPL) to enable dynamic payload.  set bit 1 (EN_ACK_PAY) to enable payload with ACK   
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
'----------------------------------------               
'REG 00 CONFIG     
'              +--------- Reserved 0
'              |+-------- MASK_RX_DR: 0=Reflect RX_DR as active Low Interrupt On the IRQ pin
'              ||+------- MASK_TX_DS: 0=Reflect TX_DS as active low interrupt on the IRQ pin
'              |||+------ MASK_MAX_RT: 0=Reflect MAX_RT as active low interrupt on the IRQ pin
'              ||||+----- EN_CRC: Enable CRC. Forced high if one of the bits in the EN_AA is high
'              |||||+---- CRCO: CRC encoding scheme '0' - 1 byte   '1' – 2 bytes
'              ||||||+--- PWR_UP: 1:POWER UP, 0:POWER DOWN
'              |||||||+-- PRIM_RX: RX/TX control 1:PRX, 0:PTX
'              ||||||||
'   CONFIG  = 111111   

  NRF_CSN = 0
  spi_array[0] = W_REGISTER               ' W_REGISTER at address $00 => CONFIG
  spi_array[1] = 0x3F                     ' PRX, PWR UP,CRC = 2 byte, CRC enable, RX_DR INT
  nrf_ptr = 1
  GoSub SPI_NRF
  NRF_CSN = 1
  DelayUS 2000                            ' Critical! min 1500uS Tpd2stby delay
  Return
'=========================================
'
RX_DPL_LEN:
  NRF_CSN = 0
  spi_array[0] = R_RX_PL_WID              ' Read Rx payload length
  nrf_ptr = 1                             ' index of 2 bytes
  GoSub SPI_NRF
  NRF_CSN = 1
  nrf_ptr = spi_array[1]                  ' the payload length is returned and can be used to determine hthe number of data bytes
  If nrf_ptr > 0x20 Then                  ' max length = 32 byte so error
    nrf_ptr = 0
    nrf_errf = 1
    Clear spi_array
    GoSub FLUSH_RX_FIFO
    Return
  EndIf
  Return
'
RX_RECIEVE:
  nrf_errf = 0
  GoSub RX_DPL_LEN                        ' get the dynamic payload length in nrf_ptr
  If nrf_errf = 1 Then Return             ' return error from dynamic payload length
  NRF_CSN = 0
  Clear spi_array                         
  spi_array[0] = R_RX_PAYLOAD             ' Read Rx payload command
  GoSub SPI_NRF
  NRF_CSN = 1
  Return
'
READ_NRF_STATUS:                            ' read STATUS for Interrupt source
  spi_array[0] = R_REGISTER | 0x07        ' Read Register $07 => STATUS
  nrf_ptr = 0
  NRF_CSN = 0
  GoSub SPI_NRF 
  NRF_CSN = 1   
  NRF_Status = spi_array[0]               ' bit6=RX_DR, bit5 = TX_DS, bit4 = MAX_RT         
  Return
'
CLR_NRF_INT:                              ' Clear Interrupts   
  spi_array[0] = W_REGISTER | 0x07        ' W_REGISTER at address $07 => STATUS
  spi_array[1] = 0x70                     ' Clear all Interrupts
  nrf_ptr = 1
  NRF_CSN = 0
  GoSub SPI_NRF 
  NRF_CSN = 1   
  Return
'   
FLUSH_RX_FIFO:                              ' flush all RX FIFO slots   
  spi_array[0] = FLUSH_RX
  nrf_ptr = 0
  NRF_CSN = 0
  GoSub SPI_NRF
  NRF_CSN = 1     
  Return
'
NRF_RX_READY:
  GoSub FLUSH_RX_FIFO 
  Clear DataIn
  Clear spi_array
  NRF_CE = 1                              ' Active Rx mode
  DelayUS 150                             ' min 130uS RX settle delay
  Return
'
MAIN:     
  DelayMS 100
  Cls
  High NRF_CSN                            ' unselect the NRF tranciver
  Low NRF_CE                              ' clear NRF_CE until we start working
  SSPEN = 1                               ' SSP Enable
  Low LED
  Print At 1, 1, "RX..PAYLOAD="
  GoSub Load_NRF
  GoSub Init_PRX           
  GoSub NRF_RX_READY                      ' activate as RX using standard values
  DummyCount = 1
  '
  While 1 = 1
    spi_array[0] = W_ACK_PAYLOAD                     ' stuff TX FIFO ACK payload
    spi_array[1] = "A"
    spi_array[1] = "B"
    spi_array[1] = "C"
    spi_array[1] = "D"
    nrf_ptr = 5
    NRF_CSN = 0
    GoSub SPI_NRF
    NRF_CSN = 1
    '
    Inc DummyCount
    Print At 2,1,Dec DummyCount
    If NRF_IRQ = 0 Then     
      Print At 2,1,"        "
      DummyCount = 1
      GoSub READ_NRF_STATUS
      GoSub CLR_NRF_INT                  ' Clear NRF Interrupts from Status reg
      If NRF_Status.6 = 1 Then           ' Status.6 = RX_DR   
        GoSub RX_RECIEVE                 ' get the payload                                   
        If nrf_errf = 0 Then               
          LED = spi_array[1] - 0x30      ' ignor spi_array[0] it has garbage from the command, "0" = 0x30, "1" = 0x31       
          Print At 1,13,Dec spi_array[1]
        EndIf                               
      EndIf   
      GoSub NRF_RX_READY 
    EndIf
  Wend



Литература:
1. nRF24L01 Product Specification.
2. Introduction to wireless networks.
3. Antenna tuning.
4. l/4 printed monopole antenna for 2.45GHz.


На главную
Admin
Site Admin
 
Posts: 209
Joined: Wed Sep 20, 2017 9:55 am

Return to Промежуточные исследования и разработки

cron

User Menu

Login