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. По идее все должно заработать.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий

  1. Гость

    Ошибочка: "Для перевода в режим приему процедура таже за исключением бита PRIM_RX, которые устанавливается в 0."

    Тут ведь для перевода в режим передачи)

    Ответить