Двигали нами три мотива:
• Прикладной — надо было уместить передатчик в пространство строго определенного размера.
• Исследовательский — неужели эта кроха ни на что путное, кроме как растерянно моргать светодиодами, не способна?
• Биологический — жаба задавила. Использовать нафаршированный ATmega328 только для того, чтобы он изредка выходил из беспробудной спячки, опрашивал пару датчиков и отправлял данные в эфир, показалось нам верхом расточительства.
Что в конце концов из этого получилось вы узнаете во второй части статьи.
Содержание статьи / Table Of Contents
Можно, конечно, пожертвовать функцией Reset и обеспечить недостающий, шестой вывод. Но ведь помимо обслуживания nRF24L01+ хотелось бы ещё что-то делать, датчики, к примеру, опрашивать.
Давайте попробуем выжать из малютки ATtiny85 все
Из рассмотренных в первой части статьи способов организации протокола SPI мы будем использовать только программный. Его применением достигается максимальная экономия выводов МК. Он универсален, всё, что вы прочтёте ниже, можно повторить на любом другом микроконтроллере.
Комментарии к коду по-прежнему будут подробными, однако повторяющиеся я буду опускать, так что при необходимости вам придётся обращаться к первой части статьи.
↑ 1) Прощайте, прерывания. Здравствуй, первая освобождённая нога!
Идея лежит на поверхности - отказ от прерываний. Создадим единую для передатчика и приёмника функцию проверки флагов регистра STATUS и поместим её в тело основной функции.Удаляем из программы всё, что связано с прерываниями. Один вывод сэкономили.
↑ 2) CE нам больше не CE. Вторая свободная нога тиньки
Установим вывод CE в 1 на постоянной основе. С приёмником всё просто. Соединяем указанный вывод с питанием и, как только биты PWR_UP и PRIM_RX регистра CONFIG будут установлены в 1, трансивер готов принимать данные.В случае с передатчиком есть одно препятствие. Согласно спецификации nRF24L01+ не должен единовременно находится в режиме передатчика более 4 миллисекунд. Какие кары ждут нарушителя, производитель умалчивает. Не будем рисковать и преступать запрет, а, по привычке, обойдём его.
Обратимся к диаграмме из спецификации и, следуя выделениям красным и зелёным, выпишем, что нужно сделать для успешной передачи в эфир данных.
1. Установить бит PWR_UP регистра CONFIG в 1, а PRIM_RX - в 0.
2. Загрузить отправляемые данные в стек FIFO.
3. Вывод CE должен находится в высоком состоянии хотя бы 10 мкс.
4. Соблюсти все временные задержки и ограничения, включая злосчастные 4 мс.
В первой части мы так и делали – настраивали трансивер, загружали данные и передергивали на 11 мкс вывод CE.
Однако, пункты 1-4 определяют необходимые и достаточные условия, но - не последовательность. Что это означает? А то, что мы можем:
1. Подключить всё же вывод CE к питанию.
2. Загрузить отправляемые данные в стек FIFO.
3. Установить бит PWR_UP регистра CONFIG в 1, а PRIM_RX - в 0.
4. Выдержать 1.5 мс для перехода трансивера в состояние Standby-I, 10 мкс и 130 мкс, необходимые для отправки данных, что суммарно не превышает ограничение в 4 мс.
5. Вернуть бит PWR_UP в 0.
Говоря иначе, мы будем передёргивать бит PWR_UP, а не вывод CE. Можно передёргивать и бит PRIM_RX, но я выбрал этот вариант, поскольку он позволяет добиться максимального энергосбережения – передатчик большую часть времени находится в состоянии Power Down.
Перейдём к программе. Расширим макрофункции sbi() и cbi(), сделав их более универсальными:
и, для удобства, оформим процесс отправки данных в виде трёх функций:
Вычищаем из кода все упоминания о выводе CE, радуемся ещё одному свободному выводу и делаем
↑ 3) Превращаем CSN и SCK в CSN_SCK
Здесь и дальше нам с мальчишками помогла замечательная статья Нёда Ральфа [1]. Идея состоит в объединении выводов CSN и SCK в один посредством RC-цепочки.Работает это при общении МК с nRF24L01+ следующим образом:
1. Сначала МК использует объединённый вывод CSN_SCK в качестве CSN, выставляя его в низкое состояние.
2. Затем - как SCK, подавая тактовые импульсы.
Параметры RC-цепочки подбираются таким образом, чтобы с одной стороны уровень напряжения на выводе CSN трансивера не успел подняться до логического 1 за время передачи байта, а с другой - чтобы SPI-протокол не получился совсем уж медленным.
В программе мы, во-первых, заменим макроопределения выводов CSN и SCK на CSN_SCK и добавим ещё одно - времени задержки цепочки RC_DELAY.
Можно, конечно, с помощью заумных формул высчитать значение задержки, мы же применили простой и проверенный способ – метод «тыка». В нашем случае вышло 1 мс.
Во-вторых, в функциях, созданных нами в первой части статьи, добавится строка _delay_ms(RC_DELAY). Где именно, вы узнаете, сделав завершающий шаг.
↑ 4) Превращаем MOSI и MISO в MOMI
Тот, кто успел уже пробежаться по вышеуказанной статье, понял, что речь снова идёт про объединение, только других выводов – MOSI и MISO в MOMI через резистор.Программно мы будем менять через регистр DDR направление вывода MOMI, используя его то как вход, то как выход, в зависимости от требований текущего момента.
Внесём соответствующие изменения в макросы и в окончательном виде они будут выглядеть так:
А написанные нами в прошлый раз функции примут такой вид:
Полный код для передатчика:
Полный код для приёмника:
↑ Заключение
В итоге, ценой программных и минимальных аппаратных затрат, мы добились управления радио-модулем всего двумя выводами МК. В запасе осталось ещё три, ну и пин Reset прозапас.Как вы понимаете, эта часть статьи не только о трансивере nRF24L01+, но и о SPI-протоколе в целом. К примеру, мы использовали описанные здесь приёмы для управления TFT-дисплеем всё тем же ATtiny85. Более того, информацию, полученную из пунктов 3 и 4, можно применить и в других случаях, при нехватке выводов.
Третья часть статьи целиком и полностью будет посвящена «ардуинщикам». В ней я покажу, как подружить оболочку Arduino IDE и ATtiny85, как запустить режим «Power Down» не только на nRF24L01+, но и на МК, чтобы получить максимальную экономию энергии.
Кроме того, мы рассмотрим вполне конкретный пример опроса датчика температуры, передачу и приём показаний по радиоканалу.
Всего вам доброго! Продолжение следует.
↑ Ссылки
1. Nerd Ralph. nRF24l01 control with 2 MCU pins using time-division duplexed SPIКамрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.