"DVDXpert" - компас в мире Hi-Fi и High End техники и другой stereo и home cinema аппаратуры.

ПРОГРАММЫ И СХЕМЫ ПИШЕМ ПЕРВЫЕ ПРОГРАММЫ

IT & hi-tech
3.6 / 5 (89 оценок)

Первая схема показана на рис. 31. Все приведенные далее учебные программы ориентированы на работу с приведенными в книге схемами и протестированы автором.

Эту схему можно собрать на небольшом кусочке макетной платы или фольгированного текстолита, выполнив соединения тонким проводом МГТФ Схему можно питать от любого имеющегося источника стабилизированного напряжения +5 вольт. В качестве стабилизатора желательно применить микромощный стабилизатор 78LM05 Он предохранит микроконтроллер от повреждения при неправильной установке в панельку или при ошибке в монтаже.

HELLO, WORLD! МИГ АЮЩИЙ СВЕТОДИОД

Простейшая ассемблерная программа, заставляющая мигать светодиод, подключенный к одному из портов, имеет такое же культовое значение, как программа, выводящая строку "Hello, World!" для начинающих программистов на языке С или Perl. Она позволяет ощутить, с чем и как вы работаете, и увидеть воочию результат своего труда. Далее мы приводим листинг этой программы. Если вы будете вводить ее текст в текстовом редакторе, то не обязательно вводить строки комментариев, которые следуют после точки с запятой. Мы очень подробно опишем алгоритм первой программы для тех, кто только начинает программировать, а более подготовленных читателей просим отнестись к этому с пониманием. Далее мы будем двигаться по принципу "от простого к сложному".

Как вы уже знаете, информация о слове состояния процессора, будучи записанной в кристалл, впоследствии может быть изменена только при помощи программатора. Он получает эту информацию автоматически, из выходного hexфайла, но биты слова состояния запрограммированного контроллера вы можете изменить, пользуясь интерфейсом программы, поддерживающей программатор (в нашем случае это PicPro Light).

Как работает программа? Указав ассемблеру тип процессора и подключив соответствующий файл описания p!6F84.inc, мы описываем, в каких ячейках ОЗУ (регистрах общего применения) будут храниться значения наших переменных. Затем приступаем к настройке портов. Сначала обнуляем значения в выходных защелках портов. В нашей программе мы могли бы этого и не делать, но правильный стиль программирования микроконтроллеров РІС требует, чтобы значения в выходных защелках были явно определены перед тем, как

некоторые линии будут настроены на вывод. Давайте привыкать к этому с самого начала.

Затем, установив в 1 бит R.P0 регистра STATUS, мы получаем доступ к регистровому банку 1. Теперь, обращаясь к регистрам PORT А и PORTB, мы обращаемся не к выходным защелкам, а к регистрам состояния этих портов, и настраиваем часть линий на ввод, а часть на вывод, что соответствует схеме. Устанавливаем бит RP0 обратно в О, обнуляем служебную Переменную ledset.

Далее (метка loop) при помощи операции "исключающее или" инвертируем бит <1> переменной ledset, сохраняя значение обратно в ledset (xorwf ledset, f) и, скопировав результат в аккумулятор (movf ledset, w), выводим значение ledset в выходную защелку порта А. На линии RA1 появляется уровень, соответствующий текущему значению бита<1> переменной ledset.

Затем инициализируем переменную внешнего цикла count 1. Внутри этого цикла вложен еще один цикл, с переменной count2. Назначение этих циклов сформировать задержку, в течение которой на выводе порта удерживается установленное значение. Когда задержка исчерпана, в порт выводится инверсное значение и цикл повторяется.

Когда вы введете текст программы, сохраните его под произвольным именем и откомпилируйте. Запишите при помощи программатора полученный hexфайл в память микроконтроллера и установите контроллер в панельку вашего макета. Когда вы подадите питание, светодиод начнет мигать.

Попробуйте увеличить частоту мигания, уменьшая начальные значения переменных couni 1 (movlw OxFF movwf count 1) и count2 (movlw OxFF movwf count2). Но учтите, если вы установите частоту мигания более 20...25 герц, то вам будет казаться, что светодиод горит непрерывно, хотя программа будет работать правильно. Если вы введете во внутренний цикл тричетыре команды NOP, то задержка заметно увеличится, соответственно уменьшится частота мигания.

ПРОГРАММА ГЕНЕРАЦИИ ЗВУКА

Итак, вы опробовали программу, заставляющую мигать светодиод. Теперь сгенерируем звуковой сигнал. Поскольку для генерации импульсов звуковой частоты нужна относительно небольшая задержка, программа будет еще проще, чем для мигающего светодиода. Понадобится сделать небольшие изменения имеющейся программы. Ниже приведен листинг нового варианта программы.

В этой программе мы убрали одну переменную цикла, и оставили только один цикл для формирования импульсов Изменили константу, при помощи которой инвертируется бит в ledset таким образом, чтобы инвертировался бит <4> Значение ledset теперь мы выводим в порт В Начальное значение переменной цикла подобрано так, чтобы при тактовой частоте 4МГц генерировались импульсы с частотой 1000Гц Изменяя значение этой переменной, вы можете изменять частоту звука

ОБРАБОТКА НАЖАТИЯ КНОПКИ

Теперь несколько усложним нашу задачу Построим программу так, чтобы в дежурном режиме мигал светодиод, а при нажатии на кнопку S2, подключенную к выводу RB2, программа генерировала звуковой сигнал Во время генерации импульсов низкой частоты мы будем периодически опрашивать состояние кнопки, и, если она нажата, гызывать подпрограмму генерации звука Таким образом, мы получаем комбинацию ранее написанных программ, из которых одна является главной, а другая вызывается как подпрограмма

ЛИСТИНГ3

Эти проблемы легко устранить, но тогда программа не будет настолько простой и наглядной.

Если вам совершенно понятно, как работает эта программа, исправьте ее самостоятельно, чтобы устранить описанные выше недочеты. Затем сделайте так, чтобы при нажатии кнопки раздавался короткий "beep", после чего программа возвращалась к нормальной работе независимо от состояния кнопки. При отпускании и повторном нажатии все должно повторяться. Затем сделайте так, чтобы звук раздавался синхронно с включением светодиода, но длительности включенного и выключенного состояния были равны. Когда вы напишете эти программы, можете считать, что почти научились программировать микроконтроллеры.

beep

ОБРАБОТКА ПРЕРЫВАНИЯ

Микроконтроллеры PIC16FXX имеют два внешних и два внутренних прерывания. В качестве примера мы рассмотрим внешнее прерывание по входу RB0/INT. Разобравшись с этим примером, вам будет несложно работать и с внешним прерыванием по изменению состояния линий RB4RB7. Обработку внутреннего прерывания по переполнению таймера мы рассмотрим в описании программы часов термометра.

Прерывание по входу RB0/INT может происходить как по нарастанию, так и по спаду входного сигнала. Мы сделаем так, чтобы прерывание вызывалось при нажатии кнопки S1. В исходном состоянии на входе поддерживается высокий логический уровень при помощи внутреннего подтягивающего резистора. При нажатии кнопки происходит переход от высокого уровня к низкому. Поэтому для генерации прерывания в момент замыкания контактов кнопки бит INTEDG регистра OPTIONJR.EG должен быть установлен в ноль.

Кроме этого следует учесть, что вектор прерывания всего один и находится по адресу 0004h. Поэтому с адреса 0004h начинается подпрограмма обработки прерывания, а по адресу вектора сброса OOOOh размещают команду перехода на метку, расположенную после окончания подпрограммы обработки прерывания.

Как видите, теперь после директивы "ORG 0000h" идет команда перехода на метку main, а затем директива "ORG 0004h" Начиная с этого адреса будет располагаться подпрограмма обработки прерывания. Она начинается стандартным фрагментом кода, сохраняющего текущие значения аккумулятора W и регистра STATUS. Затем идет программа генерации звукового фрагмента. От предложенной в листингах 2 и 3 она отличается только тем, что добавлены два внешних цикла, чтобы задать необходимую длительность звукового сигнала Когда все циклы завершены, восстанавливаются сохраненные значения W и STATUS, очищается флагбит прерывания и происходит возврат из прерывания.

В основном фрагменте подпрограммы добавилась настройка служебных регистров OPTIONJR.EG и INTCON Настройка портов и управление светодиодом происходит так же, как и в предыдущих программах

У вас может возникнуть вопрос при замыкании и размыкании кнопки происходит так называемый "дребезг контаков ", т е очень быстрое и хаотическое появление и пропадание контакта В результате на входе RB0/INT реально присутствуют не четкие фронты, а серии хаотичных импульсов при замыкании и размыкании Встроенный триггер

Шмитта не полностью защищает от дребезга Как в этом случае будет обрабатываться прерывание

Хороший вопрос • Дребезг в момент нажатия кнопки устраняется легко Когда процессор переходит на вектор обработки прерывания, автоматически сбрасывается бит GIE, тем самым запрещаются повторные прерывания (у PIC16F84 только один вектор прерывания) При выпочнении команды RETFIE бит GIE восстанавливается Как особо указано в фирменной документации, если происходит событие прерывания, когда прерывания запрещены, то соответствующий флагбит все равно устанавливается Именно поэтому мы программно обнуляем флагбит INTF в конце подпрограммы обработки прерывания Если бы мы обнулили его сразу, как только вошли в прерывание, он мог бы быть вновь установлен изза дребезга контактов, и выйдя из прерывания, контроллер вновь ушел бы в прерывание В нашей программе, пока генерируется звук, дребезг успевает исчезнуть с большим запасом по времени Таким образом, дребезг при замыкании контактов нашей программе не страшен

Другое дело дребезг при размыкании Еспи кнопка разомкнется, пока генерируется звук, ничего не случится Если же разомкнуть кнопку в то время, когда программа вернулась в обычный режим, то изза дребезга вновь может быть сгенерировано прерывание На практике это случается примерно в одномдвух счучаях из десяти размыканий Следовательно, сразу после выхода из прерывания должен быть сформирован некий защитный интервал, в течение которого прерывания по RB0/INT запрещены Попытайтесь самостоятельно усовершенствовать программу

ПОДРОГРАММА ТАБЛИЧНОЙ КОНВЕРТАЦИИ БУДЬТЕ ВНИМАТЕЛЬНЫ!

Табличная конвертация чисел является очень эффективным приемом программирования микроконтроллеров Этот прием удается реализовать благодаря команде RETLW, которая осуществляет возврат из подпрограммы с записью константы в аккумулятор, а также благодаря возможности прямых арифметических операций над программным счетчиком

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

В теле самой подпрограммы первой командой является ADDWF PCL, F Это означает, что после того, как процессор считал эту команду и аппаратно увеличил программный счетчик на один шаг, содержимое аккумулятора суммируется с содержимым регистра PCL, в котором хранятся младшие разряды программного счетчика, и результат записывается в регистр PCL

Таким образом осуществляется прямое принудительное смещение программного счетчика на величину, которая была передана в аккумуляторе, относительного того положения где должен был бы находиться программный указатель после считывания команды ADDWF PCL, F. Если, например, было W=0, то программный счетчик не изменится и будет выполнена следующая команда, retlw b'01010000', которая вызовет возврат из подпрограммы с записью в аккумулятор константы '01010000'. Исходный номер шага 0 будет перекодирован в константу, соответствующую необходимым уровням на выходных портах.

Если, например, W=2, то программный счетчик сместится на команду retlw b' 10100000' и номер шага 2 перекодируется в другую константу.

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

Дело в том, что если не принимать особых мер, то подпрограмма табличной конвертации может оказаться в неизвестном заранее фрагменте физической памяти. Может получиться так, что первые несколько команд RETLW kk работают нормально, а при обращении к другим командам RETLW kk этой же таблицы происходит переполнение двух младших байтов регистра PCL, но реального переноса аппаратно не происходит и программный счетчик "вылетает" на случайное значение адреса, что приводит к сбою программы. То есть возникает отвратительная ситуация, когда сбой происходит только в определенном случае. Найти причину такого сбоя бывает очень тяжело. Поэтому, скомпилировав свою программу, откройте окно "Program Memory" программы MPLAB и убедитесь, что ваша подпрограмма табличной конвертации размещена корректно и нигде на ее протяжении не происходит переноса из второго байта программного счетчика. Если это все же случилось, попробуйте в исходном тексте программы переставить местами ее фрагменты так, чтобы таблица перекодировки располагалась корректно.

Казалось бы, можно применить директиву ORG 0x00, где х старшее число в адресе блока, и поместить ее перед началом подпрограммы конвертации, чтобы заставить ассемблер разместить подпрограмму в нужном месте, но этот метод не работает. По крайней мере, он не работает в контроллерах, выпущенных в конце 1998 года начале 1999 года. В имеющемся у автора экземпляре, при внешней корректности программы, во время табличной конвертации при помощи подпрограммы, размещенной с применением директивы ORG 0x00 периодически "слетал" ...указатель стека! А ведь стек всего лишь должен хранить ранее записанные адреса возврата и никак не реагировать на арифметические операции с текущим значением регистра PCL. На практике процессор нормально входил в подпрограмму, нормально вычислял смещенный адрес и уходил на него, но при возврате по команде RETLW kk записывал константу в аккумулятор и возвращался почемуто не на адрес возврата, записанный в стек, а на адрес ООхх, где хх величина смещения, исходного значения, которое использовалось при конвертации. Этого в принципе не должно быть, но это так.

Проведя серию экспериментов, автор пришел к выводу, что в имеющихся у него экземплярах PIC16F84 вложенная подпрограмма табличной конвертации, то есть вызываемая из другой подпрограммы. нормально работает только тогда, когда она расположена в первом 256байтном блоке адресного пространства. В свою очередь, в фирменном описании сказано, что подпрограмма табличной конвертации должна быть целиком расположена внутри 256байтного блока, но не сказано, что именно первого блока. И если конвертация вызывается не из другой подпрограммы, а из тела основной программы, то табличная конвертация действительно работает корректно в любом блоке. Но, к сожалению, чаще всего подпрограмма конвертации оказывается вложенной. С учетом всех несомненных достоинств микроконтроллеров PIC16F84, вышесказанное подтверждает древний постулат: нет гармонии в подлунном мире.

ПРАКТИЧЕСКИЕ ПРИМЕРЫ СХЕМ И ПРОГРАММ

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

СЕНСОРНЫЙ ДАТЧИК

В схеме применяется достаточно оригинальная идея, предложенная Владимиром Беляевым из Болгарии. В описании микроконтроллеров РІС упоминается о том, для надежной работы устройств необходимо давать в программах небольшую задержку для установления уровней на входах. Это связано с тем, что компоненты схемы и входы микроконтроллера обладают некоторой суммарной емкостью, которая должна успеть перезарядиться. Если в цепи входа включено некоторое сопротивление, то постоянная времени получившейся RC цепочки может быть сопоставима с длительностью машинного такта и даже превысить его. Это явление, в большинстве случаев вредное, в данном случае приносит пользу.

Рассмотрим принцип работы схемы. На рисунке 32 показана схема RCцепочки сенсорного датчика. На ней не показана собственная емкость входа микроконтроллера, т.к. сейчас она не имеет принципиального значения. Чтобы определить, есть прикосновение к этому датчику или нет, выполняются всего две операции. На йыводе OUT выставляется высокий уровень. Сразу же после этого, второй командой считывается состояние входа IN. Если сенсорный контакт свободен, то емкость С1 не оказывает никакого влияния, и сигнал на входе IN нарастает достаточно быстро, хотя его фронт сглажен внутренней емкостью входа

Диаграммы сигналов иа активном датчике

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

Схема показана на рис. 35. Светодиоды LED0 и LED1 предназначены только для индикации срабатывания сенсоров. В схеме, предназначенной для практического применения, их может не быть. Но

миналы резистора и конденсаторов могут потребовать подбора в зависимости от конкретного экземпляра. У автора схема надежно работала при значениях R2=10K и Cl=C2=470pF. Поскольку считывать состояние входа надо не более, чем через 1...2 миллисекунды после подачи высокого уровня на выход, должен применяться кварцевый резонатор с частотой 4МГц. В качестве сенсорных кнопок можно использовать печатные контакты площадью около 1см2. Соединительные проводники до сенсоров должны быть как можно короче, чтобы избежать ложных срабатываний.

В схеме совершенно произвольно, для примера, сенсорные датчики подключены к каналам RBI, RB2. Они могут быть подключены к любым другим каналам.

Программа построена таким образом, чтобы при изменении схемы изменения в программе были минимальными. Ее можно было бы оптимизировать еще больше, но в этом случае пострадала бы наглядность. Изначально установлено, что сенсоры подключены к порту В, выводы 7 и 8, а светодиоды к порту А, выводы 17 и 18. Изменив схему, следует изменить базовые значения SB0 и SB1, означающие номе

ра битов в слове, прочитанном из порта, изменить LED0 и LED1, соответствующим образом изменить INIT_A, INIT_B, SB0_SET и SB1_SET. При этом не понадобится делать изменений в теле программы, что увеличивает ее гибкость. Изменения в программе понадобятся, когда вы удалите светодиоды или подключите сенсоры к порту А. Разумеется, вам понадобится вставить программу взаимодействия с исполнительным устройством или интерфейсную программу в отмеченное рамкой место.

В начале работы программы настраиваются порты вводавывода, затем программа начинает работать циклически. В каждом цикле вызывается подпрограмма проверки состояния сенсоров. Сначала канал RB1 настраивается на ввод, a RB2 на вывод. На выводе RB2 формируется положительный фронт. Тут же, следующей командой, считывается и тестируется уровень на выводе RB1. Если он низкий, значит есть прикосновение к сенсору и выставляется в единицу флаг бит <0> переменной FLAGS. Затем оба канала настраиваются на вывод, на канал RB2 подается низкий уровень и конденсатор разряжается, чтобы надежно определить следующее прикосновение. Попутно разряжаются внутренние емкости входных цепей микроконтроллера. Если бы мы не разряжали конденсатор, то к моменту следующего тестирования он был бы уже заряжен, сглаживание фронта не произошло бы, и программа сделала бы ошибочный вывод, что прикосновения к сенсору нет.

УПРАВЛЕНИЕ ШАГОВЫМ ДВИГАТЕЛЕМ

Следующая программа предназначена для управления шаговым двигателем. За основу взята свободно распространяемая программа для PIC12C509, которую написал Слав Славов (Slav Slavov) из Болгарии Программа переписана для микроконтроллера PIC16F84, добавлен фрагмент кода, фиксирующий ротор двигателя после включения питания. Шаговые двигатели имеют различные параметры, и характеризуются количеством шагов на 360°, количеством фаз (2 или 4) и т.д. Существуют двигатели с точностью 100 шагов/рад, 200 шагов/рад и другим количеством шагов на один радиан, но принцип работы у всех одинаков.

Наша программа предназначена для управления 4фазным двигателем, для подключения двигателя понадобится пять проводов. Двигатель может иметь либо пять выводов, если общие выводы каждой пары обмоток соединены вместе, либо шесть, если общие выводы пар выведены раздельно. Для экспериментов можно разобрать старый дисковод 5,25" и взять моторчик, перемещающий головку. При помощи тестера, или разобрав мотор, определите разводку выводов. На рисунке 37 показана схема включения мотора LI, L2 и L3, L4 представляют собой пары рабочих обмоток, имеющих по одному общему выводу. Эти пары абсолютно равнозначны и, если поменять их местами, изменится только направление вращения. Направление вращения также изменится, если поменять местами выводы у одной пары.

Таким образом, чтобы мотор начал вращаться по часовой стрелке, надо, чтобы уровни на соответствующих выводах микроконтроллера изменялись в соответствии с порядком шагов 1, 2, 3, 4, 1,.... Для обратного вращения порядок следования шагов должен быть обратным : 4, 3, 2,1,4, ...

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

Схема включения микроконтроллера показана на рис. 36, а транзисторные ключи, управляющие током в обмотках, на рис. 37

При нажатии кнопок L и R мотор вращается соответственно либо против часовой стрелки, либо по часовой стрелке. Транзисторы работают в режиме насыщения и практически не нагреваются, поэтому им не нужны радиаторы. Защитные диоды предохраняют транзисторы от пробоя выбросами обратного напряжения на обмотках, которые возникают в момент отключения тока в обмотке. Вместо транзисторов можно использовать очень распространенную микросхему, набор ключей ULN2003A Она может оказаться в том же дисководе, из которого вы вынули двигатель. Микросхема имеет встроенные защитные диоды.

Программа циклически опрашивает состояние кнопок и, если одна из кнопок нажата, выполняет процедуру перемещения ротора на один шаг. Если нажаты две кнопки одновременно, то кнопка вращения вправо имеет приоритет. Поскольку опрос кнопок происходит быстро, то при нажатии кнопки двигатель будет вращаться, пока вы не отпустите кнопку.

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

Поэкспериментируйте с имеющимся у вас двигателем, изменяя величину задержки в базовом значении del программы. Программа, текст которой приведен в листинге 6, очень проста и ее работа вполне понятна из комментариев. Если будете изменять схему и подключите кнопки к порту А, не забудьте про внешние подтягивающие резисторы. Можете использовать программу обработки сенсоров из предыдущего примера.


Еще по теме:
 СИНТАКСИС ИСХОДНОГО ТЕКСТА
 Экспресс.
 ОСТАНОВ ПО УСЛОВИЮ
 «Рекьявик» - новая фишка Яндекс
 РАСШИРЕННЫЕ ОТЛАДОЧНЫЕ ФУНКЦИИ MPLAB

Добавить комментарий:
Введите ваше имя:

Комментарий:

Защита от спама - решите пример: