Главная » Микроконтроллеры
Призовой фонд
на январь 2018 г.
1. Осциллограф DSO138
Паяльник
2. 1000 руб
PCBWay
3. 150 руб.
От пользователей

Похожие статьи:


Идеальная программа на С для МК - продолжение

Введение в продолжение

В мы начали разработку программы для МК некоторого устройства. Мы получили первую версию алгоритма работы этого устройства записанного в С-подобном стиле. Также мы провели анализ этого алгоритма и наметили проблемы и/или ошибки которые нужно решить, а также некоторые теоретические вопросы связанные с общим пониманием построения алгоритма, такие как идентификация состояний и сущностей которым эти состояния принадлежат.

Мы пишем первую версию (и все промежуточные версии) программы не для того чтобы решить поставленную заказчиком программы (устройства) задачу! Сначала мы должны убедиться, что задача правильно (корректно) сформулирована и мы ее правильно поняли! Поэтому первая задача которую мы решаем и, соответственно, должна решать наша программа это демонстрация возможностей и идентификация, измерение параметров, значения которых и будут составлять  окончательные технические требования к устройству и его встроенной программе.

Разработка ПО тем более встроенного ПО всегда включает в себя этот этап верификации и уточнения задания. Будь оно сформулировано по всем правилам как техническое задание или выражено в виде некоторых пожеланий-предположений о требуемой функциональности устройства оно все равно требует проверки РЕАЛИЗУЕМОСТИ (feasibility по английски).

Уточнение понимания работы управляемой системы, ловушка очевидности

Когда мы начинаем изобретать алгоритм управления некоторой системой, мы исходим из некоторого понимания внутренних принципов функционирования этой системы. Самой большой проблемой является нежелание проверить свое понимание этих принципов, которое обычно, мотивировано вот так:

Система работает вот таким образом <здесь приводится "очевидное" описание>, потому что по другому сделать нельзя!

По крайней мере мой опыт показывает что никогда нельзя опираться на непроверенное представление о работе системы подлежащей управлению. Это значит что мы не только должны иметь представление о работе системы, которой мы собираемся управлять. Мы должны придумать, как проверить это свое представление!

В случае с этой задачей я как раз попал в такую ситуацию, когда мое исходное представление о способе управления реле прерывателя оказалось неверным.

Я исходил из того что реле прерывателя включается только с подрулевого рычага, и поэтому параллельный ключ, который добавляет наше устройство не включит прерывания! Переключение режима работы прерывателя изображено на Рис.1.

Это неверное предположение достаточно сильно повышало сложность алгоритма управления, который я пытался реализовать-запрограммировать в предыдущей статье. Более того ошибки которые я нашел анализируя написанную версию алгоритма в большинстве своем потеряли актуальность после изменения представления о способе работы управляемой системы, хотя способ построения алгоритма остался прежний (код в конце статьи).

В конце концов я выяснил у автора задачи что прерыватель включается при появлении напряжения в цепи ламп поворотников (любых). То есть замыкание дополнительного ключа также включает прерыватель! Рис.2

Про состояния или проблема терминологии

В нашем случае можно определить:

  • состояние управляемой системы (назовем его RLC) которое МК получает ввиде 3-х битного слова по линиям inL, inR, inC;
  • состояния устройства которое МК формирует на выходах outR, outL;

Дело в том что вот это значение RLC кодирующее положение подрулевого рычага мы взяли и обозвали «состоянием», а это тянет и уводит нас в какие-то высшие сферы, дальние дали абстрактных мат.теорий о машинах состояний. Я предлагаю забыть слово состояние, и обзывать это значение «параметром» нашего алгоритма, это позволяет сосредоточиться на практических аспектах решения конкретной задачи!

Тем более есть глобальные состояния устройства, которые действительно важно различать:

  • это активное состояние устройства, когда устройство замкнет хотя бы один дублирующий ключ, таким образом обеспечивая вмешательство в работу управляемой системы(активность проявляя), и
  • пассивное состояние – это ожидание активирующего устройство события (событие включения поворотника здесь).

Код с состояниями

Автор задачи выложил здесь вот такую реализацию управляющей программы с использованием состояний.

Я бы main() написал вот так:

uint8_t rlCode;
uint8_t rlCodeSaved;
uint8_t count_pause;

int main(void)
{
   port_ini(); //инициализация портов

StartPoint:
   //начинаем с отключенными ключами устройства:
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
   count_pause = 0;
   do{//ждем нажатия поворотника:
   rlCode = get_code();
   } while (!(rlCode == command_Right || rlCode == command_Left));
   //устройство переключается в активное состояние-замыкает дублирующий ключ,
   //который закодирован в rlCode:
   if (rlCode == command_Right) { PORTB |= (1 << RIGHT_OUT); }
   if (rlCode == command_Left) { PORTB |= (1 << LEFT_OUT); }
//мы продублировали замыкание цепи от подрулевого рычага!
   rlCodeSaved = rlCode;
   while (1)// цикл отсчета продленного кол-ва "морганий поворотника"
   {//--->LOOP
   do{//ждем переключения поворотника или паузу от прерывателя
   rlCode = get_code();//дребезг=command_Error тоже игнорируем:
//мы продублировали замыкание цепи от подрулевого рычага, поэтому
//если рычаг вернется в нейтральное положение условие все равно будет выполняться:
   } while (rlCode == rlCodeSaved || rlCode == command_Error);
   if (rlCode != command_Pause) goto StartPoint;
   count_pause++;//считаем разы продленного "моргания" на каждой паузе!
   if (count_pause == TURN_COUNT)
   {//rlCodeSaved хранит инфу о том какой поворотник мы включили!
   //но мы можем просто выключить оба здесь!
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));// отключили дублирование
// NO goto StartPoint; теперь мы должны дождаться когда отключат этот поворотник!
//чтобы повторно не включить удлиннение нажатия поворотника
   }
   do{
   rlCode = get_code();//ждем окончания паузы
   } while (rlCode == command_Pause || rlCode == command_Error);
//возвращаемся в //начало циклА отсчета продленного кол-ва "морганий поворотника"--->LOOP
   }
}

Идеальная программа???

Я наверно всех разочарую, потому что в конце концов вынужден написать банальную вещь:

Идеальной программа станет только тогда, когда будет проверена ее стабильная работа в реальном "железе", и ее работа удовлетворит пожелания заказчика разработки устройства, в какой бы форме эти пожелания не выражались!

К счастью я придумал второй критерий идеальности, который кажется на совсем банальный:

Идеальная программа должна легко (то есть достаточно быстро) позволять удовлетворять вновь возникающие пожелания заказчика (в ограниченной области функциональности, конечно), неизбежно возникающие от прикосновения ко вновь обретенным возможностям автоматизации его скучных-нудных операций :) !

Мне кажется мой вариант программы удовлетворяет обоим этим критериям!

Теги:

Опубликована: 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (42) | Я собрал (0) | Подписаться

+1
andro #
Раз уж затронули эту тему, то по Вашему каким Вы считаете идеальным средством для разработки программ? Атмел студио отпадает, так как жрёт много ресурсов...
Ответить
0

[Автор]
ruhi #
Я с 1999 года работал в Атмел студии, меня она вполне устраивает. Сейчас работаю с 32-битными- SAME70 например, тоже в Атмел студии.
Особенно полезным был режим симуляции программ в процессоре. Очень помогает понять работу процессора.
Но 32-е процессоры и программы на них уже слишком сложны для симуляции.
Ответить
0
vavaav #
В замен Атмел студии я пользовался вот такой связкой. Для простых проектов очень простое решение.
Ответить
0

[Автор]
ruhi #
Это тоже: простое решение для тех, кто разгадал множество не простых секретов!
Ответить
+1
andro #
Тогда ещё был АВР Студио и он наверное не требовал столько ресурсов, но сегодняшний Атмел Студио очень прожорлив...
Ответить
0

[Автор]
ruhi #
Для симуляции, да, слабоват. Но на более менее больших проектах в симуляции уже нет смысла.
А для компиляции какая разница сколько ему ресурсов надо???
У меня комп хороший я не замечаю недостатка.
Или вы про что???
Ответить
+1
Goodefine #
Идеальная программа не должна содержать goto...
Ответить
0

[Автор]
ruhi #
Не уверен, что без goto код будет лучше, сравните:

...
while(1)//придется добавить этот цикл!
{
StartPoint:
//начинаем с отключенными ключами устройства:
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
count_pause = 0;
do{//ждем нажатия поворотника:
rlCode = get_code();
} while (!(rlCode == command_Right || rlCode == command_Left));
if (rlCode == command_Right) { PORTB |= (1 << RIGHT_OUT); }
if (rlCode == command_Left) { PORTB |= (1 << LEFT_OUT); }
rlCodeSaved = rlCode;
while (1)// цикл отсчета продленного кол-ва "морганий поворотника"
{//--->LOOP
do{//ждем переключения поворотника или паузу от прерывателя
rlCode = get_code();//дребезг=command_Error тоже игнорируем:
} while (rlCode == rlCodeSaved || rlCode == command_Error);
if (rlCode != command_Pause) break;
count_pause++;//считаем разы продленного "моргания" на каждой паузе!
if (count_pause == TURN_COUNT)
{//rlCodeSaved хранит инфу о том какой поворотник мы включили!
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));// отключили дублирование
}
do{
rlCode = get_code();//ждем окончания паузы
} while (rlCode == command_Pause || rlCode == command_Error);
}
}
...
Ответить
0
Goodefine #
Не уверен, что без goto код будет лучше, сравните:
То что не лучше, так это не из-за отсутствия goto, а по некоторым другим причинам. Название громкое, а по факту тут идеальной программы даже близко нет.
Скорее наоборот - руководство, как не надо писать программы.
Например, подобные вещи:
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
Надо прятать за макросами. Смешанная стилистика написания:
rlCode, command_Right, StartPoint...
Комменты и код все в одной куче, без вменяемого форматирования (типа код компактный).
И если скажете что это придирки, то что скажете на этот шедевр:

do{//ждем нажатия поворотника:
rlCode = get_code();
} while (!(rlCode == command_Right || rlCode == command_Left));
И чего, если нужно добавить задачу контроллеру, типа еще кнопку опросить или диодом помигать, как из этого вечного цикла выходить.
Ждать пока rlCode правильным не станет? Переписывать всю логику? Легко модидифицируемая, ничего не скажешь.
В статье есть ссылка на код (с автоматом состояний), вот там уже вполне зрелая программа. А эту под таким заголовком
я бы постеснялся даже показывать
Ответить
0

[Автор]
ruhi #
Например, подобные вещи:
Надо прятать за макросами. Смешанная стилистика написания:
Вообще то я намеренно оставил конструкции из программы, которую вы назвали зрелой, что бы легче было сравнивать.
А чем вам не нравится ШедевР в трех строчках, не совсем понятно, зачем из этого цикла выходить что бы
еще кнопку опросить или диодом помигать
???
Ответить
0

[Автор]
ruhi #
Самое интересное, на мой взгляд, в этом коде, то что состояния кодируются последовательностью циклов while - каждый следующий while следующее состояние программы - не нужно заводить переменную, что бы хранить это состояние. Состояние задает позиция в программе - номер исполняемой строки!
И благодарю за анализ!
Ответить
0

[Автор]
ruhi #
Надо прятать за макросами...
...как из этого вечного цикла выходить.
Кстати, даже эти циклы-состояния можно макросом оформить, с передачей условий как параметра, но это следующий этап совершенствования кода, до которого обычно не доходит, когда код заработает! :)
Отредактирован 09.01.2018 10:48
Ответить
0
Goodefine #
Вы сами написали, что один из критериев - это:
Идеальная программа должна легко (то есть достаточно быстро) позволять удовлетворять вновь возникающие пожелания заказчика
В вечном цикле (и не одном по коду) программа тупо висит и ждет чего-то. И если заказчик попросит вас прикрутить еще какую-нибудь элементарную операцию, придется переделывать всю логику программы.
Самое интересное, на мой взгляд, в этом коде, то что состояния кодируются последовательностью циклов while - каждый следующий while следующее состояние программы - не нужно заводить переменную, что бы хранить это состояние.
Ну конечно, вместо гибкого автомата состояний будем просто висеть и чего то ждать. Они не кодируются этими циклами, эти циклы просто завешивают программу в этих местах.
Ответить
0

[Автор]
ruhi #
Что это за аргумент:
Они не кодируются этими циклами, эти циклы просто завешивают программу в этих местах.
непонятно!
Исходный "автомат состояний" также "завешивает программу в этих местах"!
Только при таком оформлении "эти места" четко видно, видна их последовательность, а в СВИЧЕ последовательность произвольная, никак не связана с реализуемым алгоритмом.
Эта произвольная последовательность это не гибкость, это бардак!
Отредактирован 10.01.2018 06:46
Ответить
0
Goodefine #
Вы простите, но у меня, чем дольше длится диалог, тем больше укрепляется мысль, что вашу статью нужно было назвать "Моя первая программа на Си".
В каком месте автомат завешивает программу? Автомат является частью вечного цикла, а не вечным циклом, например:

...
while(1)
{
state_machine();
//другой код, который выполнится
//в любом случае, независимо от состояния
//автомата
...
}
Пробежались по состояниям автомата, сделали что надо и дальше работать, а не висеть
Ответить
0
Goodefine #
а в СВИЧЕ последовательность произвольная, никак не связана с реализуемым алгоритмом.
Эта произвольная последовательность это не гибкость, это бардак!
Как раз наоборот, это очень удобно, разбиваете алгоритм на элементарные состояния, и описываете что делать в них при определенных условиях. И совершенно не важно, в какой они последовательности. Таким образом, очень удобно делать меню, задавать последовательность действий - например, управление внешним устройством по заданной программе, разбор протоколов и т.д. Например, стек TCP/IP (очень сложная штука) разбирается на автоматах состояний. Даже в ООП. А ваше решение - в лоб - вы еще просто не дошли до определенного уровня абстрактного видения задачи. Удивляет что вы отрицаете очевидные недостатки своей программы
Ответить
0

[Автор]
ruhi #
И совершенно не важно, в какой они последовательности.
Я точно знаю что последовательность как раз очень важна, например, ключи надо замыкать только при нажатии поворотника в данной задаче, а не когда вздумается. Если это не понятно то не о чем дальше говорить.
А ваше решение - в лоб - вы еще просто не дошли до определенного уровня абстрактного видения задачи
Я рад что вы "дошли до определенного уровня абстрактного видения задачи":

Вернетесь, поговорим :) !
Ответить
0
Goodefine #
Я точно знаю что последовательность как раз очень важна, например, ключи надо замыкать только при нажатии поворотника в данной задаче, а не когда вздумается. Если это не понятно то не о чем дальше говорить.
Последовательность состояний в свитче. А не последовательность событий приведших к этому состоянию.
Т.е. неважно

case RIGHT: //горит правый поворотник
...
case LEFT: //горит левый поворотник
Или

case LEFT: //горит левый поворотник
...
case RIGHT: //горит правый поворотник

Вернетесь, поговорим :) !
А по сути есть что сказать? По поводу завешивания программы? Это и есть главная "не идеальность". Что-то вы пропустили мимо ушей замечание, что автомат не завешивает программу, хотя напомните, кто писал:
Исходный "автомат состояний" также "завешивает программу в этих местах"!
Ответить
0

[Автор]
ruhi #
Вы передергиваете, там нет другой последовательности кроме последовательности перехода между состояниями! Вы не могли иметь ничего другого ввиду!!!
Вот вы даже состояния не корректные процитировали, не нужно разделять там RIGHT, LEFT, потому что достаточно знать что включилось, а что включено возвращается из предыдущего состояния "ВЫКЛЮЧЕНО" с выходом из этого предыдущего состояния.
То что надо выполнять "всегда", обычно пишется в прерываниях, приведите пример, я смогу ответить вам по существу этого примера!
А пока вопросы (или просто заявления?) не по существу, ответы соответствуют!
Отредактирован 10.01.2018 12:30
Ответить
0
Goodefine #
Вы передергиваете, там нет другой последовательности кроме последовательности перехода между состояниями! Вы не могли иметь ничего другого ввиду!!!
Точно не читатель:
Как раз наоборот, это очень удобно, разбиваете алгоритм на элементарные состояния, и описываете что делать в них при определенных условиях. И совершенно не важно, в какой они последовательности.
Я вам написал как строить автомат состояний, саму философию написания. Откройте же шоры с глаз наконец, состояний может быть несколько десятков. А в вашей идеальной программе с каждой новой задачей код будет превращаться в несопровождаемое ...о.
То что надо выполнять "всегда", обычно пишется в прерываниях
О, уже до прерываний дошли. Еще и обычно...
Это плоды "идеального" подхода к завешиванию.
приведите пример, я смогу ответить вам по существу этого примера!
Да хоть добавьте вежливую кнопку, мигающую аварийкой три раза - будете бегать по всей программе.
Ответить
0

[Автор]
ruhi #
Да успокойтесь вы, у меня никогда ничего не висит даже в многопоточных фильтрах под DirectShow.
И еще раз повторяю, если для вас не важен порядок перехода между состояниями или он вообще для вас не существует, то разговаривать не о чем :( !
Счастливого пребывания вам, на "определенном уровне абстрактного видения задачи"!
Ответить
0
Goodefine #
... у меня никогда ничего не висит даже в многопоточных фильтрах под DirectShow.
Речь не о фильтрах или прочей лабуде. Как космические корабли бороздят просторы Вселенной рассказывать не надо.
Есть конкретная статья, с конкретным кодом и громким названием. Код не соответствует вами же предложенному критерию, поскольку полностью выключает из работы основной вечный цикл, и вместо того, чтобы в будущем при необходимости просто добавить новую задачу в тело while(1), придется трогать (и не слабо) код уже написанной и отлаженной задачи. Более того, код противопоставлен добротному коду на автомате состояний (отсюда такое внимание автомату) Так понятно?
И еще раз повторяю, если для вас не важен порядок перехода между состояниями или он вообще для вас не существует, то разговаривать не о чем :( !
Повторяю в третий раз - порядок перехода важен, он задается логикой перехода по состояниям автомата. И в автомате прекрасно кодируется порядок перехода - тот же разбор протокола, где каждый одинаковый байт может иметь разное значение, в зависимости от того, какие байты пришли до этого. И автомат с этим прекрасно и наглядно справляется. А неважен сам порядок описания этих состояний. Это позволяет при необходимости просто ниже добавить новое состояние и описать его. Не нужно перелопачивать уже написанный и работающий код. Вы этого не понимаете или притворяетесь?
Счастливого пребывания вам, на "определенном уровне абстрактного видения задачи"!
Имеющий уши услышит, я понимаю и вижу ваш труд по статье, анализ неплохой, но код никуда не годится. Паттерн проектирования, как модно говорить, в корне не верен. Ведь статья для новичков, которые могут перенести шаблон на свои программы, а потом ходить по граблям.
Ответить
0

[Автор]
ruhi #
Речь не о фильтрах или прочей лабуде. Как космические корабли бороздят просторы Вселенной рассказывать не надо.
Вам, значит, можно про TCP/IP рассказывать, а мне вы про фильтры запрещаете.
Может вам легче совсем сайт закрыть, что бы он не раздражал вас чужими мнениями, отличными от вашего?
Вы запросто определяете что тот код добротный, а этот на О, я рад за вас!
Но я так пишу уже больше 10 лет, и точно знаю что если вы действительно попробуете добавить какое то расширение функциональности, в эти два варианта программы, то в моей версии это будет проще и абсолютно прозрачно по отношению к закодированному "порядку перехода между состояниями", которого в ваших CASE-ах надо еще поискать!
Ответить
0

[Автор]
ruhi #
неважен сам порядок описания этих состояний.
Важен порядок ПЕРЕХОДА между состояниями! Я показал как порядок описания этих состояний позволяет кодировать и контролировать и визуализировать порядок ПЕРЕХОДА между состояниями!
Вы всегда должны проверить при добавлении новой функциональности, что эта новая функциональность не мешает правильному переходу между состояниями!
А если вы добавляете новое состояние как вы ищете все состояния из которых будет переход в это новое состояние, и все те в которые будет выход из этого нового состояния, попробуйте ответить?
А еще как добавить разные действия для переходов из одного состояния в разные? А если должно быть определенное действие при входе в данное состояние?
Что важнее иметь возможность реализовать все эти варианты или иметь одну возможность
добавить новую задачу в тело while(1)
?
Ответить
0
Goodefine #
Важен порядок ПЕРЕХОДА между состояниями! Я показал как порядок описания этих состояний позволяет кодировать и контролировать и визуализировать порядок ПЕРЕХОДА между состояниями!
Никто не спорит что порядок перехода важен. Автомат справляется с этим на ура. А визуализация это к программам типа алгоритм билдера. До определенного уровня вроде удобно, потом громоздко, а потом нечитаемо и несопровождаемо.
А если вы добавляете новое состояние как вы ищете все состояния из которых будет переход в это новое состояние, и все те в которые будет выход из этого нового состояния, попробуйте ответить?
Легче один раз показать. Этот код я писал около семи лет назад. Он ни в коем случае не претендует на роль идеального. Распознаваемые протоколы добавлялись последовательно, по мере появления исследуемых пультов. Распознавание делалось на автоматах - там их несколько. Но они прекрасно уживаются между собой и дополняют друг друга. И не мешают вечному циклу, в котором крутится помимо всего прочего обработка задач usb протокола. При распознавании протокола даже прерывания не использовались, только чтение флага - чтобы не мешать критичной по времени обработке usb пакетов. Хотелось чтобы вы на словах рассказали как бы решили эту задачу на методах своей десятилетней практики.
Что важнее иметь возможность реализовать все эти варианты или иметь одну возможность
"добавить новую задачу в тело while(1)"
Реализовать это все можно и без нивелирования вечного цикла, в который может потребоваться необходимость добавить не одну, а десяток задач
Ответить
0

[Автор]
ruhi #
Хорошо! Вообще я вам благодарен за то что вы побуждаете меня писать пояснения!
Никто не спорит что порядок перехода важен. Автомат справляется с этим на ура. А визуализация это к программам типа алгоритм билдера. До определенного уровня вроде удобно, потом громоздко, а потом нечитаемо и несопровождаемо.
Вопрос не в том с чем не справляется или справляется автомат, вопрос как раз с читаемостью и затратами на сопровождение!
Я только могу вас заверить что если писать блоками:

[-действие перед входом в состояние-]
do{
[- и пожалуйста здесь вызов общей для всех состояний функции-]
[-периодическое-постоянное действие в состоянии-]
}while(условие выхода)
[-действие после выхода из состояния-]
[-логика выбора следующего состояния-]
то все очень хорошо читается и сопровождается!
Мог бы показать это на примерах, но это книга получится, а не статья, а я со статьей уже утомился :) !
Отредактирован 12.01.2018 11:02
Ответить
0

[Автор]
ruhi #
кстати, по поводу
в который может потребоваться необходимость добавить не одну, а десяток задач
В этом конкретном решении вы можете заметить, что функция:
get_code()
вызывается в каждом состоянии, то есть ВСЕГДА(как вам и хотелось!), как то что в вашем подходе вы пишите перед свичом! Добавляйте туда все что вам нужно ВСЕГДА!
Расширяй - не хочу, что называется!
Ответить
0
Goodefine #
вызывается в каждом состоянии, то есть ВСЕГДА(как вам и хотелось!), как то что в вашем подходе вы пишите перед свичом! Добавляйте туда все что вам нужно ВСЕГДА!
А как же принцип разделения задач? get_code() подразумевает опрос пинов, аля клавиатура. Если туда пихать все остальное... Ну вы понимаете. Возьму и вставлю туда, ибо больше некуда очередной do-while ))
то все очень хорошо читается и сопровождается!
Если у вас будет время и желание поясните, хотя бы на словах, как бы вы написали код из моей статьи своими блоками do-while. Мне это действительно интересно.
Вопрос не в том с чем не справляется или справляется автомат, вопрос как раз с читаемостью и затратами на сопровождение!
Это называется каждый остался при своем мнении. Что-же, имеем право.
Ответить
0

[Автор]
ruhi #
Ну вы понимаете. Возьму и вставлю туда, ибо больше некуда очередной do-while ))
нельзя туда очередной do-while пихать! внешний не будет работать!
Потом неужели трудно догадаться что не обязательно внутрь get_code() все пихать, есть же места откуда вызываются все функции get_code(), там было:
[- и пожалуйста здесь вызов общей для всех состояний функции-]

Если у вас будет время и желание поясните, хотя бы на словах, как бы вы написали код из моей статьи своими блоками do-while. Мне это действительно интересно.
У меня ваш проект моя Атмел-студия не понимает, беда у них с обратной совместимостью.
Но проект интересный, ЮСБ программно реализован на ассемблере, я попробую расковырять на досуге!
Отредактирован 13.01.2018 13:07
Ответить
0
Goodefine #
нельзя туда очередной do-while пихать! внешний не будет работать!
Естественно нельзя. Потому и говорю. Вы ж сказали, зачем вечный цикл, есть get_code. Тем более, допустим, парадигма do-while понравилась и хочется еще куда-нибудь очередной зависон применить.
Потом неужели трудно догадаться что не обязательно внутрь get_code() все пихать, есть же места откуда вызываются все функции get_code()
Ага, это в каждую из трех do{} дублирующий код писать? Ибо неизвестно где повиснем.
Ответить
0

[Автор]
ruhi #
Кстати, стек TCP/IP не такая уж сложная штука (в библиотеке LWIP, например, не больше сотни файлов).
Так вот СВИТЧ с состояниями (которые вы видимо имели ввиду) там убрался в одной функции, а вся основная работа к нему, в общем то, отношения не имеет.
Ответить
0
Goodefine #
Кстати, стек TCP/IP не такая уж сложная штука (в библиотеке LWIP, например, не больше сотни файлов).
Насмешили. Скажете это когда напишите подобный стек. Пока я вижу блуждание в двух строчках кода.
Так вот СВИТЧ с состояниями (которые вы видимо имели ввиду) там убрался в одной функции
Я думал что читаете вы лучше чем пишите. Там свитчей самых разных, которыми парсятся протоколы и пакеты, более чем в сорока разных файлах
Ответить
0
smack #
Goodefine
Препроцессор повсеместно использовать тоже не есть хорошо. Препроцессор создает поля в глобальной области, как вследствие все будет сидеть в куче-перерасход ОЗУ.
Ответить
0

[Автор]
ruhi #
Что то уж вы загнули:
Препроцессор создает поля в глобальной области
ОЗУ расходуется только (в основном?) при определении переменных. Определения переменных дефайнами никто не вводит (обычно).
Ответить
0
Goodefine #
Директивы препроцессора разные бывают,
если в виде

#define PIN_ENABLE(x) PORTB|=(1<<x)
Может чего и съест, это аналог функции, а в виде

#define LEFT_ENABLE PORTB |= (1 << LEFT_OUT)
накладных расходов вообще нет. Зато можно вынести всю аппаратно-зависимую часть в один файл, со всеми вытекающими плюсами. Да и код легче читается
Ответить
+1
Pauk #
Я задавал вопрос в предыдущей статье, но раз есть продолжение, то повторю здесь, так как кажется никто не понял. Вопрос относится не только к автору, но так же просьба отозваться всем, кто знает. На микроконтроллере нужно организовать несколько элементов И. Как это сделать, что бы было правда идеально, желательно без прерываний. Логика такая: выходной сигнал должен появляться после наличия сигнала одновременно на двух входах, и должен пропадать при исчезновении сигнала на любом из входов.
Ответить
0

[Автор]
ruhi #
Так маленько понятнее!
ДЫк вот эта программа и реализует логическую функцию (более сложную чем элемент И)!
Тут в зависимости от состояния 3-х входных ног/битов меняется состояние 2-х выходных ног/битов.
Вопрос во времени срабатывания этого элемента логической функции,
Логика такая: выходной сигнал должен появляться после наличия сигнала одновременно на двух входах
Через какое время он должен появляться(не более чем)??? То есть как быстро элементы И должны менять выходной сигнал при изменении входных?
5 микро секунд допустимая задержка???
например.
Ответить
+1
Pauk #
Многовато и в моём случае это критично. Максимум 2 микросекунды.
Ответить
0

[Автор]
ruhi #
В принципе можно что то изобразить и на 2 мкс, если тактовая частота процессора 16МГц (а лучше 20 и т.д.) скажем, но будет работать только эта логическая функция, ничего больше запихнуть в основной цикл не получится при таком ограничении по времени, на время работы этой логической функции.
Потом на Xmega -х, кажется, можно такую логику как аппаратную между пинами сконфигурировать для этих целей.
И Интересно было бы узнать исходную задачу, а не то чем вы ее собираетесь решать.
Ответить
0
Pauk #
Нужно два быстрых элемента "И" и одновибратор. Можно использовать серию 155 у которой время срабатывания даже меньше получается, но не подходит по энергопотреблению. Хотелось бы сделать это на Attiny13.
Ответить
0

[Автор]
ruhi #
Можожно сделать так:
loop1:
in reg1, porta; 1-tick
in reg2, portb; 1-tick
and reg1, reg2; 1-tick
right-shift reg1; 1-tick
out portB, reg1; 1-tick
rjmp loop1; 2-tick

На частоте 16 MHz это 7/16 секунды(7 ticks), входы элемента И должны быть на одинаковых пинах условных портов A and B, а выходы след. По старшинству биты-пины
Про одновибратор надо уточнить длину импульса и запускающее событие, можно на счётчике сделать аппаратно-парралельно.
А выход из цикла, для какой то настройки например, по прерыванию от кнопки!
Ответить
0

[Автор]
ruhi #
Тут приведен на ассемблере код, который реализует два «элемента И» на АВР со временем срабатывания около 1мкс(выше пропустил мк, торопился), в зависимости от тактовой частоты МК.
Только сейчас посмотрел про Attiny13, у нее же только 6 ног доступно! Это ж получается только на два элемента И хватит! Про одновибратор тогда совсем не понятно!
И цикл надо переделать на использование только одного порта. (Я там кстати ошибся: in regx, PINx - должно быть, а right-shift это LSR)
В общем на ассемблере можно написать «два элемента И» со временем срабатывания не более 1.5мкс (может даже до 1мкс, ТОЧНО можно!) даже на 10МГц при произвольном расположении ног на одном порту. Можно объявить конкурс для знатоков AVR-ассемблера :). Я бы мог передать запороленный ZIP с ответами, тому кто может предложить свой вариант.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется напряжение?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Pickit 2 - USB-программатор PIC-микроконтроллеров
Pickit 2 - USB-программатор PIC-микроконтроллеров
FM-модуль RDA5807M Мини гравер 125 Ватт
вверх