nRF24L01+ и stm32f4 discovery

Давно не было у меня такого затыка с драйвером для микросхемы.
Целую неделю я убил на отладку.
Теперь и говорить больно.

Но всеже.
В микросхеме nRF24L01+ есть интерфейс spi, по которому собственно и осуществляется весь обмен.
Я построил работу так, чтобы микросхема больше находилось в режиме приемника и только малое время в режиме передачи. Такой подход позволяет обеспечить более менее стабильную связь в обе стороны.
Что нужно сделать чтобы оживить приемопередатчик ?
На просторах интернета куча статей в которых передача запускается с полупинка ногой AVR, но такой подход почему то себя не оправдал.
Перед передачей nRF24L01+ нужно настроить.

  • Указать канал передачи.
  • Указать длину данных в каналах
  • Указать выходную мощность
  • Указать скорость передачи
  • Включить auto-acknowledgment
  • Указать сколько попыток передачи и с каким интервалом делать
  • Выключить динамическую длину (Полезная функция, но пока не разобрался).
  • Очистить FIFO
  • Сбросить прерывания

Чтобы это сделать нужно уметь читать и писать регистры.
Запись производится посылкой команды W_REGISTER и номера регистра. После чего шлем данные.

u8 nRF24L01_write_reg(u8 reg, u8 data) { u8 resp; reg &= 0x1F; // 5bit reg num nRF24L01_CS_LOW; resp = nRF24L01_spi_send(nRF24L01_W_REGISTER | reg); resp = nRF24L01_spi_send(data); nRF24L01_CS_HIGH; return resp; }

Чтение происходит аналогично, но командой чтения. Пишем R_REGISTER и номер регистра после чего засылаем мусор для того, чтобы выдвинуть нужные данные.
Для установки адреса микросхемы нужно уметь писать пятибайтные регистры:

void nRF24L01_write_regm(u8 reg, u8 *data, u8 len) { reg &= 0x1F; // 5bit reg num nRF24L01_CS_LOW; nRF24L01_spi_send(nRF24L01_W_REGISTER | reg); while(len—) { nRF24L01_spi_send(*data++); } nRF24L01_CS_HIGH; }

Очистка FIFO осуществляется посылкой команд FLUSH_TX и FLUSH_RX.

Для перевода устройства в режим приема устанавливаем в регистре CONFIG биты PWR_UP и PRIM_RX в единицу. После чего установить ногу CE в высокое состояние.
Для перевода в режим приему процедура таже за исключением бита PRIM_RX, которые устанавливается в 0.

Для передачи данных нужно перевести устройство в режим передатчика. После чего записать данные для передачи.

void nRF24L01_write_payload(u8 *data, u8 len) { nRF24L01_CS_LOW; nRF24L01_spi_send(nRF24L01_W_TX_PAYLOAD); while(len—) { nRF24L01_spi_send(*data++); } nRF24L01_CS_HIGH; }

После записи устанавливаем CE в 1 и ждем пока данные улетят.

На приемной стороне ждем когда данные появятся, читая регистр статуса на предмет установки флага RX_DR. Или же цепляем ногу прерывания и по переходу в ноль читаем данные.

u8 nRF24L01_readRx(u8 *resp,u8 len) { nRF24L01_CS_LOW; nRF24L01_spi_send(nRF24L01_R_RX_PAYLOAD); while(len—) { *resp++ = nRF24L01_spi_send(nRF24L01_NOP); } nRF24L01_CS_HIGH; return nRF24L01_read_reg(nRF24L01_STATUS_REG); }

Я сделал так. Одна микросхема передает данные и ждет ответ. После чего сравнивает полученное и переданное.

nRF24L01_writeTx(str); do { status_reg = nRF24L01_readStatus(); } while (status_reg.bit.MAX_RT == 0 && status_reg.bit.TX_DS == 0); nRF24L01_ClearStatus(); nRF24L01_configure_rx(); do { status_reg = nRF24L01_readStatus(); req++; if (req > 1000) { req = 0; break; } } while (status_reg.bit.RX_DR == 0); if (status_reg.bit.RX_DR) { // чистим буфер memset(dataIn,0,32); // читаем nRF24L01_readRx(dataIn,32); // сравниваем int ret = memcmp(dataIn,str,32); if (ret == 0) successfulTransactions++; else badTransactions++; }

Другая микросхема — получает данные и отправляет их назад.
В процессе отладки делал, чтобы она еще выдавала полученное в UART.

Проект можете глянуть тут: https://github.com/lamazavr/nRF24L01_lib
Там же два pdf. Один — документация, другой — описание работы с микросхемой nRF24L01.

PS старался делать библиотеку. Для использования меняйте nRF24L01_gpio_init, nRF24L01_spi_init и nRF24L01_spi_send. По идее все должно заработать.

 

Источник: malimar.ru

teamviewer-com
Не копируйте текст!