* ПНЯ — Периферия Независимая от Ядра в микроконтроллерах Microchip, известная так же как CIP — Core Independent Peripheral.
Часть 4
Предыдущие статьи [1], [2] и [3] были посвящены Периферии Независимой от Ядра (ПНЯ) микроконтроллеров Microchip: конфигурируемым логическим ячейкам, портам ввода/вывода с функцией ограничения тока и АЦП с вычислителем, были показаны некоторые возможности такой периферии. Напомню, что независимость подразумевается не от типа ядра PIC микроконтроллеров (BaseLine, Mid-Range, Enhanced Mid-Range, PIC18, 16-, 32-bit), а от работы ядра, т.е. независимое выполнение возложенной на периферию задач от состояния ЦПУ. Такая периферия, а в особенности возможность её конфигурирования на совместную работу и синтез аппаратных функций, призвана разгрузить программную часть, снизить энергопотребление.
В этой небольшой статье хочу показать примеры реализации приема «кастомных», нестандартных интерфейсов связи с помощью Периферии Независимой от Ядра.
Весьма часто встречается ШИМ кодирование информации, когда дискретные сигналы, лог.1 и лог.0, закодированы шириной импульса. Рассмотрим вариант приема и декодирования таких сигналов с помощью Периферии Независимой от Ядра PIC контроллеров.
Декодирование ШИМ сигнала датчика AM2302
В DIY проектах часто применяется датчик температуры и влажности DHT22 (AM2302). Датчик имеет 3 вывода, информация передается по одному проводу. В ответ на запрос (низкий уровень длительностью примерно 1ms), датчик отвечает стартовым битом, а затем последовательностью из 40 бит, где информация закодирована в длительности импульсов: лог. «0» – импульс 30мк сек, лог. «1» – 70мк сек (типовые значения). Ответ от датчика содержит 5 байт: 2 байта данных о влажности, 2 байта – температуры и 1 контрольный байт.
Рис.1. Пояснения к принципу формирования сигнала датчика DHT22.
В сети много примеров работы с такими датчиками на Ардуино. Некоторые реализации библиотек используют конструкции типа:
loopCnt = TIMEOUT;
while(PIN) {
if(--loopCount == 0) return ErrorTimeout;
}
if (loopCnt < cntOne) {
// bit =1
…
} else {
// bit =0
…
}
В подобных реализациях мне видятся следующие проблемы:
— программа на все время измерения (>5мс) «висит» в коде измерения;
— возникновение достаточно длинного прерывания порушит чтение данных с датчика;
— потенциальные проблемы с работой на низкой тактовой частоте микроконтроллера;
Алгоритм программы подобных решений имеет примерно такой вид (см. рис.2)
Рис. 2. Алгоритм программного приема и декодирования сигналов датчика.
Ниже рассматривается вариант аппаратного приема/декодирования протокола с минимальными программными издержками.
Идея заключается в выделении синхроимпульсов из битового потока с последующим направлением исходного сигнала и синхроимпульсов на аппаратный модуль SPI. В этом случае программе микроконтроллера остается лишь забирать последовательно 5 байт данных из SPI.
Частью CIP являются таймера с возможностью запуска по событиям (изменению состояния входа или другой периферии). Т.е. изменение состояния входа может запускать таймер, см. сигнал TMR6 на рис.3. Когда таймер достигает заданного значения, его счет останавливается и таймер находится в состоянии TMR6 = PR6 (PR – регистр периода). Состояние таймера может быть входом для Конфигурируемой Логической Ячейки (CLC, см. часть 1).
Таким образом, с помощью таймера и Логических Ячеек мы можем сформировать сигнал, пригодный для подачи на тактовый вход SCK модуля SPI. Для выделения информации длительность такого клока должна иметь среднее значение между длительностью нуля и единицы. Тогда SPI может фиксировать бит по спаду клока (см. рис.3 сигнал SCK).
Сигнал от датчика будет иметь ложные импульсы, формируемые от запросного и стартового импульсов. Для того чтобы эти импульсы не мешали работе, нужно включать SPI только на время информационных импульсов, или отсечь ненужные импульсы. Эту задачу так же можем решить с помощью CIP.
Другой таймер выступает в роли счетчика импульсов с переключением по спаду: в регистр периода записываем число 2, таймер отсчитывает первые 2 импульса (см. сигнал TMR4 на рис.3) и останавливает счет (см. сигнал EN на рис.3), который через блок логических ячеек разрешает выдачу остальных импульсов на вход SPI.
Рис.3. Диаграммы, поясняющие прием сигнала датчика DHT22.
Логическая функция формирования сигнала SCK реализуется на одной логической ячейке (CLC), полная схема в конфигурации И-ИЛИ приведена на рис.4.
Выход логической ячейки подключается ко входу SCK, а сигнал датчика DHT22 подключается к MOSI модуля SPI. Все соединения выполняются внутри микроконтроллера (рис.5). Для контроля и отладки сигналы можно вывести на порты микроконтроллера.
Рис.4. Конфигурация логической ячейки CLC в PIC микроконтроллере.
Рис. 5. Полная структура конфигурации периферии.
Если кажется, что 2-х таймеров на задачу декодирования протокола датчика является расточительством ресурсов, то счетчик до двух можно «собрать» на свободных логических ячейках CLC.
Итого, задача декодирования сводится к очень простому алгоритму: инициализируется микроконтроллер и его периферия, при необходимости измерений включается модуль SPI и формируется запрос на измерение (лог. «0» в течение ~1мсек).
Остается считать данные из буфера при возникновении прерывания от SPI.
Рис.6. Алгоритм работы с датчиком DHT22 при использовании ПНЯ.
Рис.7. Сигналы с портов микроконтроллера. Сигнал SSP1IF – прерывания по приему байта модулем SPI.
На рис.7 приведена диаграммы сигналов, где:
DHT (dat) – сигнал на сигнальной линии датчика – подаем на вход MOSI модуля SPI;
TMR6 != RP6 – выделенный тактовый сигнал – подаем на SCK модуля SPI;
SSP1IF – сигнал прерываний (готовности данных в буфере SPI) – по сути этот сигнал показывает загрузку ядра микроконтроллера – считывание данных результата.
Декодирование других ШИМ протоколов
Подобные «однопроводные» ШИМ протоколы используются в ИК пультах управления бытовой техникой. Часто при ИК передаче используется кодирование положением импульса, когда длительность постоянная, а пауза переменная. Этот вариант еще называют «Кодирование методом переменной паузы». По сути это то же самое ШИМ кодирование, но с инвертированным сигналом. При наличии логических ячеек сделать инверсию – не проблема, к тому же ИК-приемники и так инвертируют полученный сигнал. На рис. 8 показаны сигналы после приемника, принятые с двух разных пультов.
Рис.8. Варианты кодирования ИК пультов управления.
Оба пульта имеют различные протоколы, но эти протоколы легко декодируются описанным выше способом, единственное, это необходимо обеспечить определение начала посылки для синхронизации включения SPI, так как ИК приемник может ловить помехи.
Рис. 9. Сигналы декодированные с помощью SPI.
Не все ИК пульты имеют ШИМ кодирование. Часть протоколов, например RC5, имеют фазовое кодирование (манчестерский код, «0» передается как 10, а «1» как 01) [4]. Декодирование манчестерского кода с помощью периферии независимой от ядра мы уже рассматривали ранее в первой части [1].
Итоги
Вместо практически 100% загрузки ЦПУ микроконтроллера для задачи декодирования ШИМ протокола в варианте Arduino (да-да, я в курсе, задачу можно решить эффективнее с помощью модулей захвата или другой периферии), мы перенесли прием информационной посылки в аппаратную часть. Фронт входного сигнала запускает таймер, состояние таймера определяет выход блока логических ячеек, выход логической ячейки подается на SPI.
Использование независимой от ядра периферии позволяет оптимизировать использование ресурсов, часть задач перенести на «железо», упростить код, снизить потребление.
Литература
1. Конфигурируемые Логические Ячейки в PIC контроллерах.
2. 50 оттенков ПНЯ. Порты ввода/вывода
3. 50 оттенков ПНЯ. АЦП и АЦП с вычислителем микроконтроллеров Microchip
4. sbprojects.com/knowledge/ir/rc5.php
Автор: ariz0na