Pull to refresh

Comments 21

Конечно стоит писать продолжение!
Я тоже очень люблю protothreads, но с удовольствием прочитаю еще одну реализацию на них (кстати я не часто вмжу ее использование)


Писал что-то похожее но на STM32 с поддержкой DMA для чтения знаений из DHT22, единственный минус был в используемой памяти: ибо на 1 бит использовался 1 байт. Зато было полностью ассинхронно.

Ну вот, у меня тоже вышло продолжение для STM8. Там два основных варианта реализации: только по прерыванием с экономией памяти и с использованием DMA для экономии времени CPU.

Доступ к публикации закрыт :(

Была проблема с проверкой на высокоуровневых функциях, грешил на ошибку в алгоритме. Оказалась ошибка в значениях тайминга. Исправил, публикацию снова открыл)
Я правильно понял, что вы предлагаете задействовать таймер, 2 прерывания, три линии ввода-вывода микроконтроллера, простыню текста в программе и все ради того, чтобы обеспечить какую-то асинхронность?!
По-моему, обмен не выгодный. Наибольшая ценность в AVR — это как раз порты ввода-вывода, и тут у вас проигрыш троекратный. В большинстве популярных микроконтроллеров таймеров тоже не изобилие, и выделять практически монопольно 16-битный таймер (который чаще всего один, редко два) под не первичной важности задачу — это, с моей точки зрения, тоже не совсем верный подход.

Возможно, я не вижу преимуществ — так и расскажите о них! То, что вы в восторге от Protothread, не аргумент: преимущества должны быть объективными.

В моей практике было впихивание протокола 1-wire в attiny13. Сумеете при вашем подходе повторить (при том, что ICP и Phase Correct PWM вообще отсутствуют в attiny13)?
Пожалуй — соглашусь. 2 прерывания — пусть, они всё равно есть. А вот три вывода — это, конечно, излишество.
Как вариант, думаю, — можно завязать всё на один вывод ICP, записывая выходные данные «вручную» в прерываниях таймера. Получающийся «джиттер» на пару десятков тактов F_CPU всё ещё останется существенно меньше 120 тактов F_CPU (15 мкс при F_CPU = 8 МГц).
Если бы пару десятков тактов… Одновременно идет обмен по USART (это точно), по SPI (ну это как управляющему контроллеру в CPU взбредет), по линиям регистрации событий (как фишка ляжет). Сейчас задумываюсь по поводу переноса некоторых I2C устройств с управляющего контроллера на AVR-ку. С выполнением на ней же некоторой предварительной обработки. Чтобы «наверх» передавать только чистые данные.

P.S. А если кто-нибудь воткнет быстродействующее 1wire-устройство? Работать с ним, как и с медленными? Здесь уже формирование PWM по прерываниям никак не спасет на 8MHz.

По моему всё супер и именно так и нужно делать как у вас.
А впихнуть 1-wire в attiny13 ну так проблем я в этом не вижу, всё на nop'а на крайняк всегда можно сделать и такты посчитать. А делать это нужно только в крайних случаях когда места мало.


А вот полностью ассинхронный код почти на голой аппарутуре — это круто, надёжно и стабильно.

Наибольшая ценность AVR в умении разработчика использовать возможности оборудования для решения имеющейся задачи ;).
В моем проекте AVR-ка выполняет следующие функции:
— через UART выполняет обмен данными по шине eBus (высокоуровневый, управляет устройством в реалтайме в зависимости от заданных параметров). Т.е. имеем конечный автомат приблизительно с 10 состояниями (уровень протокола обмена) и еще один с 15 состояниями (логика управления). Каждый из них требует 1 или 2-х независимых таймера (с точностью ± несколько миллисекунд, а не микросекунд).
— через PWM/ICP обеспечивает обмен с устройствами по шине 1-wire (собирает данные). А еще надо бы отследить появление новых устройств и исчезновение старых. Вообщем, добавляем задачу device discovery. Discovery должна выполняться периодически (вот еще один таймер), да и данные с датчиков будем собирать через некоторые интервалы времени (и еще таймер).
— всякая мелочевка типа подсчета событий по другим пинам. А вот события терять нельзя, ибо получим расхождения между фактической ситуацией и ситуацией с точки зрения софтины.
— обмен по SPI (где AVR выступает slave) с контроллером более высокого уровня. Ибо параметры управления должен кто-то выдать, а результаты датчиков надо бы куда-то девать. И этот высокоуровневый контроллер не должен ждать ~750ms результатов измерений, ему надо дать ответ сразу. Ну пусть данные и будут устаревшими на те же самые 750ms, но они будут доступны немедленно.

Реализовать 1wire в attiny при помощи bitbang особого ума не надо, все описано в appnotes. Тайминг команд посчитать не трудно. Аналогично и про USART, читай appnote и тупо копируй. Вот только проблема в том, что я для обслуживания 1wire не хочу ставить ставить отдельный кристалл. А все остальные задачи должны жить асинхронно и независимо. Т.е. прерывания должны быть разрешены максимально возможное время. Что убьет тайминг в bitbang. А второго USART-а у меня на кристалле нет.

Преимущества protothreads? Да никаких, кроме более наглядной реализации требуемого алгоритма в программном коде. А имея набор примитивов, живущих по прерываниям, очень просто и наглядно реализуется целевая задача. Ладно, раз просят продолжение, оно будет. Может быть у кого-нибудь и изменится мнение по поводу полезности многопоточного программирования в слабеньких микроконтроллерах ;)…
Т.е. прерывания должны быть разрешены максимально возможное время. Что убьет тайминг в bitbang.
Для bitbang-реализации 1-wire прерывания надо запрещать где-то на 10-15 микросекунд в начале таймслота. Не представляю, как это может помешать высокоуровневым протоколам.

И этот высокоуровневый контроллер не должен ждать ~750ms результатов измерений, ему надо дать ответ сразу. Ну пусть данные и будут устаревшими на те же самые 750ms, но они будут доступны немедленно.
Это речь сейчас о датчиках типа DS18x20? Задержка в 0,75 с никак не связана с bitbang-ом или иным способом реализации интерфейса 1-wire, это более высокий уровень абстракции, так что в данном контексте не в тему вообще.
А нолик как передавать будем? С разрешенными прерываниями? А если в этот момент идет активный обмен по SPI, I2C и UART? Передача нолика может превратится в передачу RESET ;).

0.75с относилось к protothreads. Т.е. высокоуровневые задачи должны выполняться в фоне, а не «приняли запрос с SPI, выдали команду на 1wire, ждем 0.75с, прочитали ответ с 1wire, ответили на запрос по SPI». И высокоуровневая задача не одна, а несколько.
Нет, я не буду брать распиаренные сейчас STM32 — зачем стрелять из пушки по воробьям!?

Ну STM32 ладно, но почему не взять STM8? Тем более, что они стоят сейчас дешевле даже attiny13, а по возможностям на уровне AtMega328P (которая в 3-4 раза дороже).
STM8 тоже вполне подойдет. Идея статьи показать реализацию 1wire в случае, когда bitbang не подходит, а свободного USART нет. Насколько я знаю, такой вариант в appnotes отсутствует.
Зачем? На Али платка с STM32F103C8T6 стоит меньше двух баксов — примерно как Arduino Mini!
Если, конечно, устройство будет выпускаться не миллионными тиражами, где есть смысл экономить каждый цент.
STM32 не проходит по энергопотреблению. Ибо сетевое питание иногда пропадает и приходится долго жить на АКБ.
Так у STM32 и STM8 же развитые режимы сна + предусмотрено резервное питание от батарейки. Вы уверены, что они будут жрать больше AtMega328P?
Ну платы на базе STM8S103F3P6 на том же ali вообще стоят по 65 центов (это поштучно и с бесплатной доставкой), если брать десяток то будет центов по 45.Так что зачем платить больше, если достаточно решения в 4 раза дешевле?
Так никто и не спорит, что STM8 тоже подходящий вариант. Но и на ней только один UART, который будет задействован на другой задаче. Т.е. решение аналогичное: PWM + ICP.
Sign up to leave a comment.

Articles