Свежие обсуждения
Микроконтроллеры

Ликбез по программированию PIC

1 33 99

Zandy: "не в свои сани не садись"
Zandy, скорее всего Вы настолько привыкли объяснять всё другим, что сами забыли что значит самому изучать материал как в студенческие годы. У меня тоже, наверное такой же диагноз. Раньше, помнится смотрел я на таблицу истинности какой-нибудь микросхемы и в уме уже чертил схему без всяких там графов (и "князей" тоже)... А теперь, сомневаюсь, смогу ли?
Удачи!

 

Zandy: Может быть на входе? Не описка?
Вот блин, описка, разумеется. Уже исправил.
задавать любые вопросы - это я всячески приветствую, одобряю, и по возможности на них отвечаю в меру своих знаний и опыта.
Надо проверять наличие 0 на входе два раза с паузой 100 мс. Если оба раза 0, идем далее. Это я понимаю, как желание заказчика Это не совсем "желание заказчика". Заказчику начхать - наличие чего и на чём программист будет проверять. Хоть жизни на Марсе Ему важно, чтоб устройство правильно работало - если кнопка до 100 мс нажата - не запускать, свыше 100 мс - запускать. А уж как это в программе реализовать - это забота программиста.
Ничего у меня не получится Ага Осталось убить себя апстену На велосипеде умеете кататься? А теперь вспомните, как учились? Да что там велосипед - все мы и ходить когда-то не умели. И ... впрочем, молчу

 

Zandy На Вас вся pro-radio.ru смотрит.
Нет назад ходу! Совсем нет!...

 

Vlad_Petr: Если дальше этой задачки с кнопками не мыслить и считать это верхом искусства, - тогда здравой логики хватит. В более сложной задаче человек часто ошибается.
Согласен, что в сложной задаче человек может ошибаться, но... только если будет пытаться решить всю задачу одним махом. Вот здесь главное научиться разделять большую задачу на подзадачи и решать их поотдельности. Как раз этому и надо учиться! А для этого не надо пытаться написать всю программу сразу. Вот и предлагаю начать написание программы по частям с подробным разбором каждой части и окажется, что программа любой сложности складывается как дом из кирпичей.

 

Zandy, наш мудрый народ не зря придумал выражение "будь проще". И одна мудрая девушка в своё время донесла до моего понимания сермяжную правду этих слов, за что большущее ей спасибо. Зачем ставить перед собой туманную цель и с упорством до фанатизма стремиться к ней? Не лучше ли постепенно находить конкретные ответы на конкретные вопросы? Предельно конкретные. Об этом вот и SAK говорит.
"Я должен сделать это устройство так, чтоб оно работало правильно" - это порочный подход к решению задачи, способный довести человека до исступления и поколебать его уверенность в собственных силах.
Воспринимайте это как своеобразную игру - и всё упростится. Никакой ответственности ни перед кем Вы в данном случае не несёте. В том числе и перед самим собой (это очень важно). "Бойцовский клуб" смотрели? Победа - не главное!!!
А когда всё упростится - многое вдруг начинает проясняться само по себе. В конце концов, вся наша жизнь - игра...
Ладно, отъехал я от темы чего-то...

Итак, попробуем задать себе конкретные вопросы.
1. Какое состояние является исходным для нашего устройства? Ответ прост - обе кнопки отпущены, светодиоды погашены, на обоих выходах нули.
2. В каком и только в каком случае должен произойти пуск нашего устройства? Этот вопрос порождает следующий - а какие случаи вообще возможны в исходном состоянии? Промежуток времени нас пока не интересует, анализируем мгновенное состояние - чтобы не думать раньше времени о дребезге. Подумаем.
Прежде всего определимся - а что такое пуск. Пуск - это когда контроллер устанавливает лог.1 на соответствующем выходе и переходит к выдаче на светодиоды "бегущего огня" (во время которого кнопки не опрашиваются). Теперь рассмотрим возможные случаи. Что для начала следует сделать? Ответ - проверить состояние кнопок. А сколько всего случаев может быть? Четыре, т.к.кнопок всего две.
Случай А - обе кнопки отпущены, на обоих входах R и L лог.1. Не спешим развивать тему, анализируем другие возможные случаи!
Случай В - нажата только кнопка L, на входе L лог.0, на входе R лог.1.
Случай С - нажата только кнопка R, на входе R лог.0, на входе L лог.1.
Случай D - нажаты обе кнопки, на обоих входах R и L лог.0. Такое возможно? Возможно! Значит, и этот случай учтём.
Закономерно возникает следующий вопрос - а что контроллер вообще должен делать в этих случаях?
А - тут делать ничего не надо, ждём-с. Т.е. вернуться к проверке состояния кнопок. Но сначала светодиоды погасить (см. разбор ситуации D ниже).
В - на нажатие кнопки контроллер должен отреагировать. А если это помеха - случайный короткий импульс (или - не побоюсь сказать это страшное слово - дребезг)? Следует ли произвести пуск? Нет, т.к. по техзаданию кнопка должна удерживаться нажатой не менее 100 мс. Вот и следующий вопрос - а что нужно будет сделать через 100 мс? Ответ - убедиться в том, что эта и только эта кнопка всё ещё нажата. И если это действительно так - то выполнить пуск! (влево)
С - и опять вопрос - а чем этот случай отличается от случая В? Только тем, что кнопка другая. Должны ли отличаться действия контроллера от тех, которые выполняются в случае В? Только тем, в какую сторону выполнить пуск. Значит, рассуждаем аналогично. Следует ли произвести пуск? Нет, т.к. по техзаданию кнопка должна удерживаться нажатой не менее 100 мс. Вот и следующий вопрос - а что нужно будет сделать через 100 мс? Ответ - убедиться в том, что эта и только эта кнопка всё ещё нажата. И если это действительно так - то выполнить пуск! (вправо)
D - и тут вопрос - а когда вообще такая ситуация может возникнуть? Подумаем. Допустим, обе кнопки могли быть нажаты до включения питания. Возможно такое? Вполне. А ещё? Вообще-то кнопки могут быть и в любой момент нажаты почти одновременно, тогда при считывании данных мы получим два нуля. (исправленному верить, сначала ошибочно две единицы написал) А ещё? Возможно, что это помеха.
Что делать в этой ситуации? Зажечь два средних светодиода. А потом? А потом скорей вернуться к проверке состояния кнопок, потому что это могла быть короткая помеха (импульс, например). Или ошибка пользователя. А как светодиоды гасить после того, как это состояние сменится на другое? Ответ: например, в ситуации А. Кроме того, нужно будет предусмотреть гашение светодиодов перед началом "бегущего огня".

Вот и готов ответ на вопрос 2. Пуск влево должен произойти в том и только в том случае, если при первом считывании состояния кнопок было выявлено нажатие только на кнопку L, и при повторном считывании состояния кнопок через 100 мс также было выявлено нажатие только на кнопку L. Пуск вправо должен произойти в том и только в том случае, если при первом считывании состояния кнопок было выявлено нажатие только на кнопку R, и при повторном считывании состояния кнопок через 100 мс также было выявлено нажатие только на кнопку R.

Как вам такой подход, уважаемые участники? Прошу критиковать и задавать вопросы.

 

Неплохо было бы начать всё с начала, но с поэтапным решением подзадач и по ходу их разбором. Что бы не быть голословным начну сам с попытки решения предыдущей задачи через прерывания. В задании не определена тактовая частота контроллера, но есть требования к временным интервалам. Поэтому надо определиться с частотой. Предлагаю использовать внутренний генератор (Fg=4МГц). Теперь надо выбрать частоту прерываний. Насколько помню все временные интервалы кратны 50 мс, потому и предлагаю использовать это значение, т.е. Fi=1/0,05=20 (Гц). Теперь надо выбрать коэффициенты для предделителя (d) и счетчика тймера (t) для выполнения условия Fg/(4*d*t)=Fi, при этом d выбирается из (2, 4, 8, 16, 32, 64, 128, 256), а t =255. В нашем случае только один вариант d=256, t=195.

Итак первый шаг - инициализация режима прерываний:
org 0
goto Init
;--------------------
<Здесь будет описание процедуры прерывания>
;--------------------
Init
;-----
<начальная настройка>
;-----
banksel OPTION_REG
movlw B'00000111' ; presc=7(1:256), T0CS=0, PSA=0, RBPU=0
movwf OPTION_REG
banksel INTCON
movlw B'10100100'
movwf INTCON ; прерывание от таймера разрешено
...........

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

Шаг второй - тело прерывания:
org 4
movwf _Save_W ; Сохранение W
swapf STATUS,W
movwf _Save_STATUS ; Сохранение STATUS
movlw -195 ; Значение для счетчика таймера
movwf TMR0 ; Установка счетчика таймера
bcf INTCON,T0IF
;..................
<обработка прерывания>
;..................
swapf _Save_STATUS,W ; восстановление STATUS
movwf STATUS
swapf _Save_W,F
swapf _Save_W,W ; восстановление W
retfie

Здесь _Save_STATUS и _Save_W - переменные (их объявление я опустил).
Замечу, что лично для меня удобнее если числа по умолчанию принимаются в десятичной системе, поэтому в начале программы я указываю:
radix dec

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

 

Ну я же не думал, что состояние D нештатное, и в задании вроде об этом не сказано.
Значит вариант, который предложил Vlad_Petr не катит? Нельзя делать накопительный регистр на каждую кнопку? Получается, что это противоречит случаю D?
Так все-таки, могу я доработать свою программу или не могу? Несмотря на то, что я не учел все требования задания, программа то вроде работает и основные функции выполняет.
Что-то пока о графах никто не высказался, несмотря на то что все твердят об их полезности.
picmaniac: Ему важно, чтоб устройство правильно работало - если кнопка до 100 мс нажата - не запускать, свыше 100 мс - запускать.
Так я об этом и толкую. Что именно таково желание заказчика, а к подавлению дребезга или помех каких это имеет косвенное отношение, а вопрос дребезга (мозгов ) пока открытый и мы им займемся позже. Так?

 

SAK, а зачем прерывание? Вы сразу начали шаблон программы прописывать, а логика работы-то какая?
SAK: Насколько помню все временные интервалы кратны 50 мс
А почему так?

 

SAK, всё-таки хотите сразу программу писать?

Zandy, при проверке работоспособности программы обязательно следует подавать на входы проверочные "ложные" сигналы длительностью менее 100 мс. И смотреть - что при этом будет происходить.
Насчёт составления графа всё же говорить пока немного рановато, сначала разберём работу автомата на словах. Так будет легче. А то составление графа большинству участников в новинку, и мне в том числе. Запутаться легко.

Кстати, Zandy совершенно верно подметил ещё на 28-й странице:
Но вот при удержании немного не понятно. Здесь опрос кнопок будет редкий, с паузами на время пробегания бегущего огня. И если вдруг проскочит фальшивая 1 (ослабится давление на кнопку) и это событие совпадет по времени с опросом кнопок, основная программа перестанет выполняться и опять зациклится в малое кольцо опроса кнопок. Фальшивая 1 пропадет, и программа пойдет выполняться далее, как и положено. Все бы ничего, но в момент попадания в малое кольцо опроса кнопок, на выходе L (R) может кратковременно проскочить 0, а это противоречит заданию.
Тут есть над чем подумать. Противоречит ли это техзаданию? С одной стороны вроде бы да - кнопка вроде как нажата, а на выходе ноль проскакивает. А с другой стороны вроде бы и нет - а нефиг пользователю "давление ослаблять" на кнопку. А вдруг это помеха проскочила, и пользователь не причём? С другой стороны, при нажатой кнопке вход контроллера фактически закорочен на "общий", поэтому помеха маловероятна.
В общем, неоднозначность получается. К разбору этой ситуации мы, думаю, ещё вернёмся, когда будем рассматривать действия контроллера по окончании "пробегания огня".

 

Vlad_Petr: Zandy На Вас вся pro-radio.ru смотрит.
Нет назад ходу! Совсем нет!...

Во напали-то на человека!
А как хорошо и тихо было в "Радиоприеме" . Ничего, потерпите немного, все образуется. Мне было проще, потому что учитель здесь был один (picmaniac), да еще литература.