Текст
                    :13 ПОМОJ!)'Ь fадишиобителю
Гололобов В. Н.
«УМНЫЙ ДОМ»
СВОИМИ РУКАМИ
NT Pгess
Москва


УДК 621 .38 ББК 32.965 Г61 Подписано в печать 22.08 .2006 . Фомат 84х108 1/32• Гар­ нитура «Баскервиль•. Печать офсетная. Усл. печ. л. 21,84 . Тираж 3000 экз. Заказ No 5467. Гололобов В. Н. Гбl «Умный дом» своими руками/ В. Н. Гололобов. - М.: НГ Пресс, 2007.-416с. :ил.-(Впомощьрадиолюбитето). ISBN 5-477 -00484 -3 Книга адресована радиолюбителям, но может быть инте­ ресна всем, кто интересуется электроникой . Описывается со­ здание системы автоматизации дома «Умный дом» на базе микроконтроллера PIC16F628A в программе MPLAB. Компо­ ненты системы и модули отлаживаются на одной макетной плате . Для всех экспериментов, описанных в книге, можно использовать одну и ry же микросхему контроллера. Програм­ матор, работающий с программой PonnyProg2000 , легко соби­ рается и не содержит дефицитных деталей. Компьютер в ла­ боратории радиолюбителя превращается, фактически, в саму лабораторию. Управляющая программа системы (она же - отладочная программа) может быть написана на языке про­ граммирования Visual Basic или на любом другом языке . В зак­ лючительной части приведены справочные материалы по командам микроконтроллера PIC16F628A, схема датчика дви­ жения и программатора для программирования РIС-контрол­ леров. 1!J СКАН - ГРУППА PICBOOK УДК 621.38 ББК 32.965 © Гололобов В. Н . , 2006 © НТ Пресс, 2007
.. ,,.,,... ,,.,,...,,.,,. .... ,,, .. ,,,,,, ....,,. .... ,,. .... ,,..... ,,.,,,.. ,,. .... ,,.,,,.. ОГЛАВЛЕНИЕ Предисловие ............... ........................... .............................. . 6 Зачем нужна эта книга ......................... .... ........................... .. 6 Из чего мы будем создавать систему ..................................... 8 Почему именно микроконтроллер в качестве базы ................... 9 Еще немного о микроконтроллере в качестве базового элемента ... 1О Как мы будем работать.." .................... .. .............................. 11 Несколько предварительных замечаний ................................ 11 Глава• 1 Базовая версия .. .. ... ...... ....... .. .. ... .. ..... ...... ....... .. .. .... ............ 12 «Умный дом» отАМХ иJDS ............................" . .... .. .. .. ... ..... .. 12 Система Landmark ....... ....................... ................................ 13 Система StarGate - Х10 ............................. .......................... 27 «Умный дом» вашего производства ...................................... 33 Темный холл .................................................................• .. . .. 33 Возвращаюсь я с работы...................••.. .. .. ." .. ...............•.. . .. 34 Возвращаюсь я с работы (модификация решения) ..........• . .. .. 35 Создание эффекта присутствия ............................................ 37 Цель проекта ........................... .. .......... .... ..... .........................40 Схема и программа релейного модуля ............................ " .. . 48 Программа модуля на ассемблере ........................................ 51 Программа релейного модуля на языке С ....•.................... . . .. . 66 ·введениевработусMPLAB .." .. ...... ..... ..... ... ........ .• ........•.. " .. 98 Релейный модуль, версия программы на языке С ........... ... 104 Первая сборка на макетной плате ...................................... 109 Схема и программа модуля приема ИК-команд ... ............. . 118 Программа модуля приема ИК-команд на языке С ... " . ... . .. .. . . 1 22 Отладка модуля ............................... " .... . " .. . . .. .. . .. .. . .. .. .. . .. .. . 1 5 4 Схема и программа модуля излучения ИК-кодов ............. " . 1 66 Программа модуля излучения ИК-кодов на языке С •.••. •.•.. . •.. 167 И ЧТО ПОЛучИЛОСЬ? •••••• •••••• ••••••••••••••••••••••• ••••••••••••••••••••• ••••• 201 Модуль считывания ИК-кодов WiпLIRC .... ........................... 202 Программа для управляющего компьютера ... .............. ....... 208 Завтра ..........................•...................... .............•........ . ..... 220 И немного назад ......•..........................." ... .......•.•..•......•.." 226 Текст основной программы на языке Visual Basic •............•• .. . 228 Подведем итоги ......................................... ......... ......... ....... 234 Ода ошибкам..•.•• ...•.......•.. . ...............•.. .•.. ... . ....... ....••.•.. .. "235 . .
4 ' Оглавление Глава• 2 Как расширить систему ................................................... 237 Модуль цифровых вводов ...................... ............................. 239 Программа модуля цифровых вводов на языке С ................ . 241 Модуль с триаком ...................................... ......................... 253 Модуль с плавной регулировкой яркости .. ......................... . 256 Программа регулировки яркости на языке С .. ...... ................ 261 Модуль последовательного интерфейса ... .... .... .... ............ . 269 Модуль аудиокоммутатора ....... " ............ . ........................... 269 Модуль видеокоммутатора ...................... .. ......................... 270 Модуль управляемого усилителя ........... .... ......................... 271 Модуль системного ИК-пульта управления ...................... .. 273 Модуль аналогового ввода для термометра ................ .. ..... 274 Замена проводного канала RS485 ..... .. . .... ... .... .............. .... . 275 Усовершенствование базовых модулей ........ ................... ... 276 Последние замечания .... .. ... ... ....... ........... ... ................ .. ... .. 277 Глава• З То, что рядом с сеУмным домом11 .............. ....................... 280 MULTISIM ............................................................................ 284 Усилительный каскад на транзисторе .. ....... ............. .... .... ... . 289 CircuitMaker 2000 ........ ...... ............ ............... ............... .... .... 297 Electric ...... ..... ..... ... ..... ... ............. .. ......... ............................. 301 Сопряжение управления ............................ ......................... 306 .мешанные системы .......................: .. .. . . . .. ... ... .. ... ... .. ... .. . . . 315 азные подходы к реализации системы .. ........................... 318 rриложение ................. .......................... ... .. : . ... .... .... .... .. . . .. . 330 ИК-датчик движения ............ ............ .......... ........ ...... .... .... ... 330 Таблица команд микроконтроллера PIC16F628A .... ....... ... .. 333 Цоколевка контролrера PIC16F628A .. .. ... ....................... .. .. 336 Программатор ~совместно с PoпyProg) ... ........................... 337 Адаптер для РIС-контроллеров .... " .. . . . " .. . . . . ... ... ... ... ... ... .... .. 338 Внешний вид и параметры модуля общего назначения фирмы Advantech ... ... . ...... ........ .... .. .. ... 339 Практическое применение триака в модулях системы ...... . 339 Дополнительные замечания по ИК-управлению ............ ..... 341 Программа для компьютера в KDevelop ... ......................... . 343 Вторая версия основной программы на языке С++ ....... . " . . .. . 355 Двеполезныесхемы"".." ."""".." .." .." .. .." ...." ..." ..." ....... 363 Разветвитель видеосигнала .... " ....." .. " ....... .... ." ... " ...... " ... 363 Схемы для экспериментов с радиоканалом . "" "..... " .. . . . " .. 3 67
Оглавление 5 Немного о программировании на С++ ................................ 372 Как писать программы на С++ ............................................ 373 Определение и инициализация объектов данных .....• . .•. • ..• .• . 380 Написание выражений .............................................•.. .. .. .• 385 Оператор предшествования ....•.......................................... 389 Написание условий и создание циклов"..•..... " .....•.•.....•...••. 391 Циклы ............................... " ..... •.. ..... " ... .. ..• . .. ... .. ... " ... .. .. .. 39 6 Как использовать массивы и векторы... " ............................. 399 Указатели дают больше гибкости." ....•..... ......•..• ..• .....•••.• .... 404 Запись и чтение файлов .. ................• .. .. ... .. ... .. .. ... .. .. ...• .. .• .. 409 Ссылки на полезные сайты в Интернете ............................413
Преди~nовие Заqем нужна :tта книrа Многие не догадываются, насколько увлекательно занятие электроникой. Гораздо интереснее что-то придумывать и со­ здавать, чем пользоваться готовым. Проделать предлагаемые в книге эксперименты и начать свою разработку? Это инте­ ресно. И может быть полезно. Например. Заработавшись за компьютером дотемна, я ча­ сто, особенно зимой, выхожу по темной комнате в темный коридор, натыкаясь на телефонный столик и книжные шка­ фы. Используя релейный модуль, через который включена лампа на телефонном столике, я с компьютера включаю эту лампу, и теперь синяки от столкновения с мебелью полнос­ тью пропали. ..Например. Я люблю, если чувствую, что устаю от работы, вь- •ить чашечку кофе. Наливаю электрический чайник, вклю­ Ч€ J его. Чтобы не ждаU>, когда он закипит, я возвращаюсь к кr мпьютеру. А когда вспоминаю о чайнике, его, как правило, ~ риходится гр~ть заново. Но система напомнит мне (если я не выключу звук у компьютера), что чайник вскипел. Например. Возвращаюсь я с работы. Система встречает меня - зажигает свет в прихожей, кипятит воду для кофе (увы, чайник я наполняю утром). А когда я перейду в гости­ ную с чашкой кофе, она включит телевизор на программе новостей, чтобы я, усевшись в любимое кресло, посмотрел, что произошло в мире за день. Свет на кухне и в прихожей, который я, конечно, забьш выключить, она выключит сама. Например. После вечерней работы я сажусь к телевизору в любимое кресло. Частенько бывает, что и вздремну. Очнув­ шись от дремы, чтобы не переломать сон, я быстро чищу зубы и спешу в кровать. Но не успеваю еще заснуть, когда система выключает телевизор ·и свет в квартире. Летом она
Зачем нужна эта книrа 7 включает кондиционер, чтобы воздух в спальне стал прохлад­ ным. Но к утру, если температура ниже 24°, система включа­ ет обогрев. Если спать я люблю в прохладе, то вылезать из постели предпочитаю в теплую комнату. Например. Мне нравится, уж так я устроен, принимать го­ стей. Люблю я суету в прихожей, когда, не успев попривет­ ствовать одних своих знакомых и предложить им напитки, я спешу к двери на очередной звонок, чтобы встретить новых путников, забредших «На огонек». И не слишком, как ни ста­ раюсь, я поспеваю всех развлечь. Если бы не система, кото­ рая и свет во время зажигает, и музыку включает негромко, и тем, кто зашел в мой кабинет, предлагает посмотреть фильм. Все эти и многие другие «Например» могут быть реализо­ ваны из доступных деталей своими руками с помощью систе­ мы, описанной в книге. И ничто не помешает применить эти разработки не только в квартире, но и на даче, в гараже или в машине. Мне кажется, это интересно - придумывать, что бы еще система могла сделать цолезного? Экспериментировать, а за­ тем воплощать проекты в жизнь. Строить всегда интересно. Строишь ли ты дом или планы, отношения с коллегами по работе или свою первую электрон­ ную схему. Как мне кажется, электроника - самая удобная сфера применения творческих способностей. Особенно со­ временная электроника. Своими успехами электроника во многом обязана новым технологиям. В частности, появлению компьютерных про­ граммам, позволяющих осуществлять полную разработку уст­ ройств за компьютером. Конечно, чтобы осуществить такую разработку. нужно иметь компьютер. Но если для профессио­ нальной работы следует обзаводиться одной из последних мо­ делей, то радиолюбитель может прекрасно поладить с ранни­ ми моделями, стоимость которых может сравниться со стоимостью приборов в лаборатории радиолюбителя. Люби­ тельский осциллограф (я не говорю о профессиональном) стоит столько же, а то и дороже, чем подержанный Pentium с тактовой частотой 120 МГц. Сами программы (некоторые из них достаточно дорогостоящие) могут быть в демо-версиях,
8 Предисловие которые имеют основное ограничение - невозможносгь сохра­ нения файла. Я сам порою пользуюсь подобными версиями, и это, согласен, неудобно , но если потратить чуть больше време­ ни на продуманный план работы, подобное неудобство пере­ стает быть определяющим. Кроме того, для компьютера сегод­ ня есть операционная система Linux. Одним из основных ее достоинств является доступность по цене и существование большого количества программ, распространяемых бесплатно. Систем «Умный дом», то есть систем автоматизации жи­ лья, в настоящее время множество. Одни рассчитаны на при­ менение в условиях квартиры, другие могут поддерживать работу целых жилых районов. Хотя интересы радиолюбите­ ля могут простираться далеко за пределы его мастерской (у меня - это секретер, у кого-то, может быть, целая комна­ та), начинать эксперименты лучше на столе . Итак, прежде чем начинать работу, определимся в том, что мы намерены сделать. Небольшую систему, к которой, пусть с оговорками, можно применить название «Умный дом». Начав с разработки отдельных компонентов системы, мы объединим их в сеть, заставив работать под управлением компьютера. В первом приближении так построены и мно­ гие коммерческие варианты системы , за исключением, мо­ ЖЕ r быть, специализированного процессора или микроконт­ rоллера в качестве центрального управляющего устройства. Но кто мешает нам загрузить небольшую системную програм­ му в контроллер? Или что может помешать построить моду­ ли так, что они будут «общаться» между собой, не требуя «цен­ ных указаний» от компьютера? Иэ 81el'O мь16удем соэдавать систему Из того, что есть «под рукой». Что доступно. В качестве базового элемента всей системы я предлагаю использовать микроконтроллер фирмы Microchip PIC16F628A Причина, по которой я остановил свой выбор на этом микро­ контроллере, весьма прозаична - стоимость и доступносгь как самого контроллера, так и всего, что необходимо, чтобы микро­ схема, которую вы купили, мог.па быть чем-то полезна. То есть программатор и программа обслуживания программатора,
Зачем нужна зта книга 9 которые позволят загрузить в микросхему вашу разработку. Программа для работы с микросхемой PICl6F628A - это МРLАВ. Она свободно распространяется изготовителями микросхем. Программатор используется самодельный, рабо­ тающий с программой PonyProg 2000, которая также распро­ страняется свободно. Все это программное обеспечение су­ ществует как для Windows, так и для Linux. Почему именно микроконтроппер в качестве базы Не только и не столько « В погоне за модой» , но по нескольким иным причинам. Это удобно и практично. Создав одну из кон­ струкций, описанных в книге, вы легко превращаете ее в дру­ гую, не докупая новых дорогостоящих элементов. Потеряв со временем интерес к данной теме, вы можете не отправлять макетную плату с микроконтроллером в ящик с надписью «Хлам», а использовать ее для построения ряда полезных схем в следующем проекте или сделать микроконтроллер ядром следующей системы. Современные микроконтроллеры - это целый мир электроники, рождающейся из одного элемента. Очень интересной темой, как мне кажется, могла бы стать тема модификации старых конструкций с использованием микроконтроллера. Микроконтроллер PICl6F628A имеет встроенные блоки компараторов и широтно-импульсной моду­ ляции, а также энергонезависимый модуль памяти. Его такто­ вая частота может быть повышена до 20 МГц, а вьmолнение ряда команд за один такт позволит применять микросхему в диапазоне радиочастот. Есть и еще одна причина, заставившая меня написать эту книгу, - обилие новых терминов может оттолкнуть начинаю­ щего. Человек, незнакомый с программированием, может загодя, не пытаясь разобраться, решить , что программирова­ ние - не для него. Я же пытаюсь показать (или доказать), что все не так. И программы, которые вы будете использовать , и языки программирования - это те же молоток или отвертка, только называются они иначе. Это инструменты. Ведь не от­ талкивают вас такие термины, как мультиметр, осциллограф, функциональный генератор, варикап, термистор. Это все средства достижения вашей цели.
1О Предисловие В настоящий момент микросхему PIC16F628A в Москве можно купить в магазине «Чип и Дип» или заказать по почте наложенным платежом на сайте http://www.dessy.ru. Забегая немного вперед, хочу отметить, что я не пожалел о выборе микросхемы, - при налаживании устройств мне пришлось сотни раз перепрограммировать ее. Теряя бдительность, я несколько раз устанавливал ее в панельку неправильно, но она как работала, так и работает. Одно это, как мне кажется, достойно восхищения и уважения. В качестве базового эле­ мента всех предлагаемых разработок можно использовать любой другой микроконтроллер, но это потребует изменения всего комплекса программ и программатора. Если по какой­ либо причине, кроме стратегической, есть необходимость сменить микросхему, попробуйте выбрать ее из серии PIC, поскольку со многими микросхемами этой серии работают программаторы и программы PonyProg2000 и МРLАВ. Еще-немноrоомикроконтроппере в каqеnве 6аэовоrо мемеtnа Когда-то основным элементом при построении схем была вакуумная лампа. С появлением полупроводников транзисто­ ры почти вытеснили ламы. Микросхемы, укрывая в своих гrубинах тысячи транзисторов, изменили подход к разработ­ ь.е .:электронных изделий. Все в большей мере электронные : ·зделия стали превращаться в кентавра - наполовину тран­ зисторы-резисторы, наполовину программы. Микроконтрол­ лер устранил и эту половинчатость. Он - микросхема, работа­ ющая на основе написанной для нее программы, которая и определяет все, что микросхема будет делать (в рамках, ко­ нечно, своих физических возможностей). Сегодня микрокон­ троллеры используются настолько же широко, насколько вче­ ра использовались транзисторы, а позавчера - лампы. Стоимость микросхемы PIC16F628A (в пластмассовом корпу­ се DIP18) - около 100 руб. С одной единственной микросхе­ мой вы можете собрать, проверить, отладить и модифициро­ вать все модули, описанные в книге. Вы можете придумать свои модули и проверить их работу, а также загрузить основ­ ную программу в микроконтроллер и, используя компьютер
Зачем нужна эта кннrа 11 в качестве других модулей системы, проверить работу основ­ ной программы. Для проверки всех схем можно использовать одну макетную плату, добавляя элементы по мере необходи­ мости. И последнее - если вы после макетирования и отладки собрали готовый вариант, спаяв схему полностью, но в про­ цессе эксплуатации нашли изъяны в ее работе, можно пере­ программировать микроконтроллер в готовой схеме, не вы­ паивая его. Как мы будем pa6cmrn. Технология проста - в основном, за компьютером . Когда по­ кажется, что разработка готова, мы перенесем ее на макет­ ную плату. После отладки разработки на макетной плате ее можно, при желании, повторить в виде «готового изделия» с этикеткой «Made in MyLab». При налаживании всех схем я намеренно постарался использовать единственный невирту­ альный прибор - мультиметр. Для этих целей подойдет са­ мый дешевый цифровой мультиметр , и мне жаль, что я не проверил это, но думаю, подойдет и тестер класса «Приз» илиТЛ-4. НескОIJЫС:О nредваритепьныхзамечаний «Умный дом», «Смышленый дом», или «Послушный дом» - за всеми этими названиями будет скрываться ваше желание применить все, о чем говорится в книге , используя собствен­ ные возможности и фантазию, к комнате , квартире, коттед­ жу или дому. «Умный дом» будет умен ровно настолько, на­ сколько вы ему позволите. Основная це~ь этой книги - не столько в описании гото­ вых разработок, хотя все завершенные устройства провере­ ны в макетном варианте, сколько в рассказе об одном из пу­ тей подхода к разработке. Кто-то из вас уже имеет опыт работы с микроконтроллерами. Но кто-то, возможно, не пы­ тался строить свои разработки на базе микроконтроллера, полагая, что это слишком сложно. Однако работать с микро­ контроллером не сложнее, чем с любыми электронными ком­ понентами. Было бы время и желание.
Глава llJ &азовая версия ссУмнь1й дом11 от АМХ и JDS Сколько специал~стов, столько мнений. Я часто повторяю это, поскольку решений может существовать множество, даже после применения всех критериев отбора. Дальнейший выбор происходит на основе личных предпочтений. Систе­ мы автоматизации быта - отнюдь не исключение. Можно до бесконечности спорить, делать ли систему централизованной или децентрализованной, какую сеть использовать - компью­ те~ ную, силовую или специализированную. За основу выбора можно взять надежность, стоимость или доступность готовых устройств, за счет которых в будущем система может расши­ ряться, совершенствоваться, развиваться. Полный обзор существующих систем может занять не одну книгу, поэтому я лишь вкратце расскажу о нескольких систе­ мах, с которыми знаком, и которые находятся, в какой-то мере, на ценовых полюсах систем бытового назначения. Но вначале немного о том, из чего состоит любая система «Ум­ ный дом», хотя можно по-разному подойти и k этому вопросу. Я разделю систему на центральное управляющее устройство, исполняющие модули, средства управления, системную сеть и среду программирования (она же средство отладки) . Базо­ вые исполняющие модули - релейные модули, модули циф­ ровых вводов, диммеры, трансляторы ИК-команд , коммута­ торы сигналов. Средства управления - универсальные пульты ИК (инфракрасный спектр) команд , специализированные
«Умный дом» от АМХ и JDS 13 клавишные пульты и сенсорные панели. Системная сеть - это системный интерфейс и среда передачи системных команд. Это не полный перечень, а, скорее, произвольная выборка, которая нужна в дальнейшем, чтобы определиться с реализа­ цией. Кроме того, все производители систем каждодневно со­ вершенствуют все составляющие своих продуктов. Не успе­ ваешь рассказать о новинках, предлагаемых фирмой, как она выпускает нечто еще более интересное и привлекательное. Вместе с совершенствованием информационных технологий преобразуются подходы к решениям, да и производители бытовой техники все чаще задумываются о возможности включения своих изделий в единую систему, снабжая их стан­ дартными интерфейсами. Система Landmark В настоящее время система поддерживается корпорацией АМХ (РНАSТ, Panja). Почти все модули выполнены в виде печатных плат, пред­ назначенных для установки в конструктив (рис. 1.1). Рис. 1.1 . Конструктив РНАSТдnя установки модулей С перечнем модулей можно ознакомиться на сайте произ­ водителя, но я приведу названия и назначение некоторых модулей из списка, который есть в моем архиве: • PLC-MCU - модуль центрального процессора системы; • РLВ-АМР8 - 8 - канальный усилитель (обслуживание аку­ стических зон);
14 Глава • 1 Баэова11 версн11 • PLB-ASlб - 16-канальный аудио коммутатор (матрица lбхlб}; • PLC-IN7 - модуль с семью цифровыми входами (для под­ ключения датчиков); • PLC-IRIN - модуль с тремя входами для приемников ИК управляющих кодов; • PLC-IROUT - модуль для подключения 4-х ИК-излуча­ телей; • PLC-RL8 - релейный модуль с восьмью исполняющими реле; • PLL-MLC -управляемый диммер-выключатель. В конструктиве (CardFrame) расположен центральный про­ цессор. Конструктив имеет встроенный сетевой концентра­ тор, к которому подключаются сетевые системные устройства (нацример, все выключатели света). Как и компьютерные хабы, он имеет вход и выход для объединения всех сетевых концентраторов. Средства управления в составе системы представлены дву­ мя базовыми решениями. Это настенный клавишный пульт с дисплеем для отображения информации и переносной пульт для ИК-управления. Кроме них система поддерживает работу сеРсорных панелей АМХ с помощью специального модуля. П.хзже появилось множество универсальных ИК-пультов упра- 1 ления, способных запомнить большое количество кодов от пультов управления бытовыми устройствами. Некоторые их них, например фирмы Philips, могут полностью программи­ роваться на компьютере, а затем загружаться через СОМ или USВ-порт. Несомненно, и сенсорные панели АМХ, и пульты Philips очень красивы (рис. 1.2) Вид и работа сенсорных панелей обустраиваются с пом0; щью специальной программы (или программ), которые в пол­ ной мере определяют все необходимое, подготавливая рабо­ чую программу для загрузки в панель. Панели также имеют встроенный редактор, но программировать их удобнее все­ таки за компьютером. Для загрузки панелей, уже установлен­ ных в систему, используется существующая системная сеть. То же можно сказать и о пультах фирмы Philips (рис. 1.3).
«Умный дом» от АМХ н JDS 15 Рис. 1 .2. СенсорнаяnанельАМХ Рис. 1.3 . ПультРrоntоРrо Универсальные пульты для ИК-управления мoryr приме· няться. практически. с любой системой. Некоторые модели поддерживают как инфракрасное управление, так и управ­ ление по радиоканалу. Например, пульты ProntoPro позволя­ ют одни страницы использовать в режиме IR (инфракрасное
16 Глава • 1 Базовая версия управление), а другие - в режиме RF (управление по радио­ каналу). Какой из режимов удобнее в практическом приме­ нении, сказать трудно. С одной стороны, ИК-управление ограничено помещением, в котором оно используется, а уп­ равление по радиоканалу не имеет подобного ограничения. Но с другой стороны, именно возможность ограничить об­ ласть управления оказывается очень важным свойством. В данном случае наилучшее решение зависит от конкретной задачи и условий применения. Да и не следует переоцени- · вать проникающую способность радиоволн. Серьезным пре­ пятствием на их пути может стать развитая силовая сеть или система отопления с большим количеством металличес­ ких труб, скрытых в стенах. Система Landmark имеет удобную и эффективную среду программирования, позволяющую работать как с проектом автоматизации обычной квартиры, так и с автоматизацией многоэтажной постройки. Каждый этаж в последнем случае может быть разбит на помещения, в которых будут распола­ гаться устройства и датчики, бытовая аппаратура. Можно ис­ пользовать строительные поэтажные планы, что дает полное представление о помещениях. Программа, по сути, набирается из необходимых собы­ тий, вызываемых пультами управления, датчиками, или вре· менем суток, и ответных действий системы. Программа ос­ нащена достаточным количеством условий. Приведу пример работы с системой Landmark. После за­ пуска и ввода пароля новый проект выглядит, как представ­ лено на рис. 1.4. Первые клавиши инструментальной панели, ниже основно­ го меню, вполне ясно подскажут, что делать дальше, - опреде­ литься с домом - этажами и комнатами. Рисунок этажа можно взять из проектной архитектурной документации, изобразить в редакторе Paint, встроенном в Windows, в AutoCAD или CorelDraw. Landmark поддерживает множество форматов изоб­ ражений. Щелкнув кнопку в правом углу инструментальной панели, выбрав имя для этажа (поддерживается русский для задания названий, но лучше использовать английский, чтобы при печати иметь как можно меньше проблем) и указав рису­ нок этажа, получаем результат, показанный на рис. 1.5.
«Умный дом» от АМХ и JDS 17 Рис. 1.4. Окно проекта в системе Landmark Рис. 1.5 . Этаж в системе Landmark
18 Глава • 1 Базовая версия На этом рисунке мы расположим помещения проекта, пе­ рейдя на вторую закладку основной панели инструментов «Rooms». Для добавления помещения используем клавишу «Add» меню страницы . Впишем название комнаты. Можно изменить цвет, а можно оставить цвет, предлагаемый про­ граммой. Затем нарисуем помещения, используя левую кноп­ ку мыши для фиксации положения линии. Если впоследствии понадобится поправить положение зафиксированной точки, можно установить курсор на эту точку и, удерживая левую кнопку мыши, переместить опорную точку в нужное место . Продвигаясь дальше по основной инструментальной пане­ ли, можно понять, что необходимо сделать, поскольку следу­ ющая кнопка носит название Design. А пока вид проекта в плане помещений представлен на рис.1.6. Рис. 1.6. Разбивка проекта на комнаты Если теперь перейти на вкладку Design, получим вид про­ екта, изображенный на рис. 1.7. На инструментальной панели страницы (справа) все уст­ ройства, поддерживаемые системой. Их нужно расположить по комнатам, в соответствии с реальным положением дел.
«Умный дом» от АМХ и JDS 19 li 1 ! j L./\ 1 Рис. 1.7 . Проект, nодготоw~енный к размещению оборудования Для начала расставим свет (клавиша с лампочкой). Щелкаем, отыскиваем в подменю лампочку, обозначаем помещение, например «гостиная» и, удерживая левую кнопку мышки, пе­ ретаскиваем лампочку в нужное место (рис. 1.8). ! ~ ! ; ! 1 ! 1 ~./] i Рис. 1.8. Размещение подсистемы управления светом
20 Глава • 1 Баэово11 версн11 После расстановки источников света (люстр, бра, групп светильников), задаем нужные свойства и меняем, если это нужно, обозначения. При использовании диммеров следует обратить внимание на опцию Ramp to level gradually (пере­ ходить на уровень плавно) слева в рубрике On/OffRate (ход включения/выключения). Если не установить эту опцию, плавное включение будет в программе недоступно. Остальные опции позволяют выбрать скорость нарастания яркости - Dim rate (ход выключения), установить уровень яркости в ночное и дневное время, яркость свечения индикаторов в ночное и дневное время и т.д. Задание свойств выключателей подразу­ мевает, что загрузка основной программы в процессор систе­ мы сопровож:1ается передачей всех настроек соответствую­ щим м~дуляы. После идентификации источника света на первой вклад­ ке Control (управление) можно управлять им в интерактив­ ном режиме, когда компьютер подключен к системе. На дру­ гих вкладках можно построить сцены управления светом (вместе с люстрой, щелкнув кнопку ее включения, можно включать потолочную подсветку в спальне и т.п.). Включается меню настроек (свойств - pгoperties) двойным щелчком ле­ вой кнопкой мыши или щелчком правой кнопкой при пози­ ционировании на объекте и выборе в раскрывающемся меню раздела свойства (properties)-pиc. 1.9. Расставив источники света и задав все необходимые свой­ ства, пора заглянуть в раздел основной инструментальной панели Program. В данном случае я раскрыл подменю спаль­ ни (bedroom)-pиc. 1.10. · В левом окне вкладки событий (events) в спальне обозначе­ ны все светильники по их функциональному назначению. Обя­ з~тельно ли это? Нет. Для профессионалов, возможно, даже удобнее иной подход с обозначением помещений 1, 2, 3, а ис­ точников света - 1 Lightl, 1 Light 2 и т.д. , поскольку в рабочей документации будут таблицы соответствия. Однако я считаю удобным сразу обозначать функциональное назначение поме­ щений и оборудования. В дальнейшем это позволит осмыслен­ нее подходить к программированию событий - события в кух­ не и спальне, мне кажется, могут сильно различаться.
«Умный дом» от АМХ и JDS 21 Рис. 1 .9 . Задание свойств модулей управления светом Рис. 1.1 О. Окно программирования системы Landmark
22 Глава • 1 Базовая версия Аналогично в проект добавляются системные устройства управления, аудио- и видеооборудование, датчики и т.п. На этом подготовка к работе с проектом за1с<ончена, можно начи­ нать программирование. Отвлечемся немного от технических деталей. Поскольку все системы, с которыми мне приходилось сталкиваться, в равной мере позволяют осуществить, хотя бы формально, любую программу, самое время определить, а что мы хотим в ней видеть? Посмотрим, насколько просто реализовать в системе Landmark сценарий, приведенный в предисловии под назва­ нием «Возвращаюсь я с работы». Я несколько изменю преды­ дущий вариант конфигурации проекта, оставив прихожую, кабинет, гостиную и кухню. Расставим необходимые элементы (рис. 1.11). 11. • - ! ! •• - ! . ! i L---1 ~,. Рис. 1.11 . Вид проекта в системе L.andmarkдля сценария ·Возвращаюсь я с работы• Во всех комнатах я устанавливаю свет. Везде, кроме каби­ нета, добавляю датчики движения, в гостиной - телевизор и сенсорную панель управления, а на кухне - плиту. В гостиной я поместил и CardFrame (конструктив, в котором располо­ жатся модули). По команде «спецификации» оборудования
«Умный дом» от АМХ н JDS 23 (Spec) программа заполнит CardFrame необходимыми моду­ лями (рис. 1.12). Рис. 1.12. Размещение модулей в системе Landmark Теперь можно перейти к программированию. Опишем события: я прихожу домой, сработавший датчик движения в холле зажигает свет, включает электрочайник, чтобы, пока я переоденусь, вода для кофе вскипела. Конечно, чайник я наполняю водой и ставлю на подставку перед ухо­ дом на работу (рис. 1.13). Переодевшись, я перехожу в кухню, наливаю кофе и иду в гостиную. Программа выключает свет в холле, электрочайник на кухне и включает телевизор в гостиной, едва датчик дви­ жения в гостиной отмечает мое появление (рис. 1.14). Модули, которые программа задействовала самостоятель­ но, - это модуль процес ::.-!>а, модуль, поддерживающий сен­ сорную панель , модуль цифрового ввода. К последнему мы подключим дат .;:ifки движения. Еще система добавила релей­ ный модуль. С помощью этого универсального модуля можно включить и выключить такой бытовой прибор, как электри­ ческий чайник (выключается он сам, но модуль дополнитель­ но отключит его и от сети). Если параметры контактов реле
24 Глава • 1 Базовая версия -, i 1·~ .... •D~ :-'QD- +J~ ~ ...._ , .... ::i Jl:i!e- r.1_" ..,..__ гr_.",....." г,..,....... Рис. 1. 13. Начинаем программировать сценарий •Возвращаюсь я с работы• 'f..Js_... ~ wo- ••- ~ "4- ~ • -.. -t.V" ; --..- ~1 1~ j"............. "..... !t . Uct- • Uct-М.Г...... • Ьсt- 14'1 Рис. 1.14. Завершаем программироватьсценариii •Возвращениедомой•
«Умный дом» от АМХ и JDS 25 не позволяют управлять включением мощной нагрузки, мож· но применить пускатели, и реле будет включать и выключать пускатель. Модуль трансляции ИК-кодов займется управлени· ем телевизора. С помощью сенсорной панели я могу легко управлять всеми бытовыми устройствами квартиры, напри· мер открыть входную дверь и включить свет в холле, если сосед (или соседка) зашел в гости на чашку кофе. · Система Landmark централизованная. Она может работать под управлением компьютера, собственного процессора , в который загружается программа, и переходить от управле· ния с помощью компьютера к управлению от собственного процессора, если компьютер по какой-то причине выключа­ ется. Конечно, она имеет средства организации распределения аудио- и видеосигналов, охраны дома, управления климати· ческими устройствами и т.д. Под «И т.д.» я подразумеваю даль­ нейшее описание работы с системой Landmark. что. однако, в данном случае не является uелью повествования. А вот как среда программирования выглядит в NetLinx Studio - программ е , предназначенной для раб оты с процес· сорами и модулями корпорации АМХ. После запуска програм­ мы можно создать новый проект обычными для Windows средствами (Меню• Файл• Новый), или открыть существу· ющий (рис. 1.15). Язык программирования больше похож на процедурно­ ориентированный язык, что отражается и на среде програм· мирования, хотя не следует забывать, что он ост~ется специ­ ализированным. Встроенный редактор позволит скопировать программу в блокнот из Windows и продолжить программи· рование в блокноте. При наличии готовых программных бло­ ков они легко добавляются в программу. Таким образом, даже достаточно сложную программу можно быстро скомпоновать из рабочего материала предыдущих разработок. Если вы спе· циализируетесь на работе с системой NetLinx, то кроме про­ граммных блоков, предлагаемых производителем, у вас мно­ го своих, надеюсь, сиС1::ематизированных, проверенных и отлаженных. Вот с установкой устройств проблем несколько
26 Гnава • 1 Базовая версия ;(•((f'Sj:OllllU_IW8(rf!O'CUМ S1-1S) •J 't··-····· -·········-··-········-·""......""".".... " .....1 1(• 11н nrt111• ем: •1•12•12 •r ~ 1-.: 1111 : :11! ", ,."""•••" ••".-••"•••••" • ••••""."."•••" .......""••"".......J (• flLl_L•SJ_ " DlflO_W .: •182/l81t •1: t&:ll:'>"f •) c•··-·--·•···--·····- ·-···-•••••••·--•••••••••·•-J {• IWtfflМ_fH(.'1.IJr....J t '") (•-··--·····---·-··--·-·········-···········) , f•ttrlt(••111eм: -• •1 (• 111.• l'lletlNI(; M/82/tмt •1 С• •1 (• n...,иts : •1 С• •J (••···-······ ····-·· - ·- ·· ·· ··- ·····-·-· ··-···· ··-· ' C •))• S s.wlll:t ll'f 'I •1 t··-·; .•"...";..•"_. __ __ " ______________ _ ____________, с•••·••·••-•••••••••--·•••••-••-•-••••••••••••••••-••1 (•:l:yst••fJ111t : IWIH• • •1 ··-····················-····-····-··-·················) 'f•ltf.UHl"Jйfl• : •) 1-··-·····-·········-···················-············-J Рис. 1. 15 . Система ·Умный дом• корnорацииАМХ больше. После начального процесса усгановки устройсrв про­ грамма будет выглядеть, примерно, как показано на рИс. 1.16 . 1r ttr.Nor11_s1111tC (IW•.1) ... •• •_,(1)· • ) (• 1r ,." . , , •t ( s1J11e11 с••·•.ч~н ( ""' ( lf" (8«11_ 1(1t" - · ) 8"(1'f "1 .t) ELU:lf(llW • . l(lt" ) OFJ"{llfllf.t) •c•v ·;,·: ( ,, ctttr•_,(1)- · · ) 8fl{ll["1.ZJ f.LSf .lf (ll8'•.l(l)""o ) 8Ff ( ll(lll.,l J Рис. 1.16. Установка оборудования в системе корnорацииАМХ
«Умный дом)) от АМХ и JDS 27 В обеих системах после начального подготовительного процесса, который никак нельзя назвать сложным, мы гото­ вы приступить к программированию. Система StarCate- Х10 Системы, работающие по протоколу XlO, - это другой цено­ вой полюс. Множество производителей выпускают как от­ дельные компоненты, так и законченные системы автомати­ зации. Можно использовать централизованное построение или создать децентрализованную систему. В качестве приме­ ра рассмотрим систему StarGate QDS). Как и предыдущая, она позволяет быстро объединить со­ бытия с реакцией системы, создав программу обслуживания дома. Имеет система и схожий набор устройств, в котором, как и в других системах, есть все необходимое для создания подсистем управления светом, аудио- и видеооборудованием, климатической и охранной подсистемы, подсистемы управ­ ления, например, садовым оборудованием или гаражом. С? перечне модулей, составляющих физическое наполне­ ние системы, можно судить по меню, которое открывается в программе после обращения к разделу Define основного меню (рис. 1.17). При создании нового проекта система добавляет начало и конец программы (рис. 1.18). После запуска программы и выбора New Schedule (через основное меню File или инструментальную панель - первая кнопка) в оглавлении мы готовы перечислить оборудование нашего проекта. Как и в случае с системой Landmark, начнем со света. В основном меню выберем Define • XlО Device... Оrкрывается таблица, в которой можно обозначить все источники света (но не только) . В системах, работающих с сетевым протоколом XIO, адрес устройств состоит из двух знаков: латинской буквы от А до Р и цифры от 1до16. Всего, таким образом, можно адресоваться к 256 устройствам, что достаточно для довольно большой системы. Распишем свето­ вую подсистему (рис. 1.19). Расположение выключателей света можно задать в описа­ нии - Location, назначение - Description.
28 Глава • 1 Базовая верс11я Рис. 1.17 . Меню устанавливаемого оборудования в системе StarGate Рис. 1.18. Создание проекта в системе StarGate Я хочу повторить предыдущий небольшой сценарий «Воз­ вращаюсь я с работы», реализованный в системе Landmark.
.. - ... " " «Умный дом» от АМХ и JDS 29 " -------- -----· -------1J ! ~~§ "'"к·,,..0w в.::: ~ " i Рис. 1.19 . Расстановка адресуемых модулей управления светом Поэтому выберу светильники и добавлю релейный модуль для включения электрического чайника (рис. 1.20). Рис. 1.20. Добавление оборудования для сценария •Возвращаюсья с работы•
30 Глава • 1 Базовая версия Осталось добавить в проект датчики движения, которые будут работать со встроенным модулем цифрового ввода (Define • IR and 10 Devices). Я выбираю модуль ввода-выво­ да, щелкаю кнопку Define и определяю свои датчики движе­ ния (рис. 1.21). • Ри с. 1.21. Добавление датчиков для сценария •Возвращаюсь я с работы• Сохраним выбор, и можно начинать программирование. В редакторе выбираем кнопку New Event, обозначаем первое событие как come_home и к строке if с помощью кнопки Add и выбора из меню Digital lnput выбираем собы­ тие - датчик движения hall_MSl перешел в состояние ON (рис. 1.22). Продолжая этот процесс, с помощью кнопок New Event и Add пишем программу (рис. 1.23). <?бе системы - и Landmark, и StarGate - после загрузки программы в центральное управляющее устройство встретят меня после работы, зажrут свет в прихожей, вскипятят воду для кофе . А когда я перейду в гостиную, включа~ телевизор, чтобы я, усевшись в любимое кресло, посмотрел, что про­ изошло в мире за день.
«Умный дом)) от АМХ и JDS 31 Рис. 1.22. Начинаем nроrраммирование сценария в системе StarGate Рис. 1.23. Завершаем программирование сценария в системе StarGate
32 Глава • 1 Базовая версия К сказанному выше следует добавить, что для управления телевизором обе системы требуют дополнительного устрой­ ства, которое можно назвать модулем считывания ИК-команд. Они предназначены для запоминания ИК-кодов с пультов уп­ равления, чтобы эти коды можно было впоследствии воспро­ извести системным устройством. В системе Landmark это до­ полнительное устройство носит название IRIS. А StarGate работает с IRXpander. Последнее устройство не только прочи­ тывает ИК-команды с пультов и запоминает их, но может рас­ познавать эти команды, оно же воспроизводит их. Задание адреса устройств системы StarGate может произ­ водиться либо переключателями, установленными на уст­ ройстве - один переключает буквы от А до Р, второй цифры от 1до16 - либо программно . В последнем случае, как пра­ вило, требуется помощь компьютера или одного из контрол­ леров Хl О. Беглый обзор двух систем «Умный дом» завершен. Зачем он понадобился? Да чтобы можно было составить представление о 1:0М , как это вьшIЯДит в профессиональных разработках, иметь цель и сравнить сделанное нами с профессиональными разработками. Затем, чтобы вы могли при желании продолжить проект, опи­ санный в книге, до уровня профессиональной разработки. Но не следует забывать - за видимой простотой процесса программирования как в Landmark, так и в StarGate скрыва­ ется система, которая рано или поздно проявит все свои свойства. При первом знакомстве может возникнуть иллю­ зия, что программирование по легкости схоже с игрой в ку­ бики: сложил так - получил домик, переложил иначе - полу­ чаешь паровозик. Подобная иллюзия может стать причиной того, что однажды ... домик запыхтит и поедет. .. И последнее. Что слеДует «подвергать» автоматизации. Вот, как на это смотрят специалисты РНАSТ. Чrо должно авrомаrи~нроваrьс• В принципе, любое электрическое или механическое устрой­ ство, любая подсистема внутри или снаружи вашего дома мо­ жет быть автоматизирована, хотя бы ненамного.
«Умный дом» вашего производства 33 Поскольку количество устройств и подсистем, которые вы мJжете интегрировать с системой домашней автоматизации, огромно, важно выбрать систему достаточно гибкую, расши­ ряемую, обновляемую и оптимальную по стоимости. Это дол­ жна быть система, которая легко устанавливается, програм­ мируется и имеет программный интерфейс, не требующий освоения новой техники программирования каждый раз, ко­ гда вы добавляете в систему новое устройство. Корпорация РНАSТ развивает современную автоматиза­ цию дома, которая полностью отвечает этим требованиям. Заметьте: так как список характеристик, относящихся к раз­ ным системам автоматизации и компонентам, которые могут быть автоматизированы, велик, система автоматизации дома может стать весьма сложной. Для преодоления проблемы вам следует обращаться к системам, с которыми вы лучше всего знакомы. РНАSТ настоятельно рекомендует тщательное изуче­ ние всех незнакомых систем или устройств, прежде чем вы примете решение о внедрении их в систему Landmark. ссУмный ДOMJJ вawero nроизводсrва В первую очередь рассмотрим, как могут выглядеть решения, о которых упоминается в предисловии . Темный XOIUI Сценарий решения: работая за компьютером дотемна, чтобы выйти в темный холл, не натыкаясь на мебель, я с компьюте­ ра включаю бра в холле. Для реализации этого решения мне нужен релейный мо­ дуль, имеющий одно реле, и простая основная программа на компьютере, которая отправляет команды « включить свет » и «выключить свет», адресованные этому модулю (рис. 1.24). Аналогичное решение можно применить с небольшой мо­ дификацией (можно и со значительной) и для случая , когда ночью приходится вставать, чтобы зайти на кухню попить или выйти в туалет. Ночной светильник в холле избавит вас от опасности споткнуться по дороге, но не будет резать таза после темноты в спальне. Модификация в данном случае
34 Глава • 1 Базовая версия Компьютер с основной программой СОМ-порт Блок питания =128 КОNoертер RS2Э2-RS485 Лампа в холле -2208 Релейный модуль с одним реле Рис. 1.24. Структурная схемасистемыдnя щенария •Темный холл• относится к тому, чтобы в программе, заложенной в контрол- . лер релейного модуля, один из выводов порта предназначал­ ся к присоединению кнопки. Эту кнопку (клавишу, выключа­ тель) вы можете расположить возле прикроватной тумбочки или на ней. Нажатием кнопки вы включаете и выключаете реле без участия компьютера. Кнопок можно сделать не­ сколько, если вы в доме не один. Когда я говорил о значительной модификации, то имел в виду, что кнопку возле кровати можно снабдить радиопере­ датчиком, а релейный модуль - радиоприемником. В этом случае вам не понадобится добавлять провода в квартире. Воэвращаюсья с ра6оть1 Сценарий решения: по возвращении домой я открываю вход­ ную дверь. Система зажигает свет в прихожей, кипятит воду для кофе. Когда я перехожу в гостиную с чашкой кофе, она включа­ ет телевизор, выключает свет на кухне и в прихожей (рис. 1.25). Для реализации этого решения мне потребуется модуль цифровых вводов, к которому подключаются герконовые дат­ чики - первый, установленный на входной двери, и второй - на двери в гостиную. Мне понадобится релейный модуль с тремя реле, одно из которых включает свет в прихожей, второе - свет на кухне, третье - электрочайник. Задейство­ ван будет также модуль излучения ИК-команд с излучающим светодиодом, расположенным возле телевизора..Основная
«Умный дом» вашего производство 35 программа на компьютере будет иметь программные блоки, оjслуживающие системные модули. Компьютер с основной программой СОМ-порт Блок питания = 128 Электрический Лампа в Лампа чайник прихожей на кухне .....-----~ Релейный модуль стремя реле -2 208 Системная сеть Конвертер RS232-RS485 Модуль излучения ИК команд Модуль цифровых вводов ~ ИК светодиод на телевизоре в гостиной 1-1 1 1 1 1 '-·-~J Герконовый датчик на двери гостиной 1- 1 1 1 1 1r-r1 '----- Герконовый датчик на входной двери Рис. 1 .25. Структурнаясхемасистемыдпясценария•Возвращаюсьясработы• Основным событием для программы, работающей на компь­ ютере, в данном решении становится изменение состояния герконового датчика на входной двери. Это событие иницииру­ ет включение света в прихожей и на кухне, включение электро­ чайника (выключается он сам, когда !}Ода закипит). Следующим событием становится срабатывание герконового датчика не двери гостиной. По этому событию программа выключает свет в прихожей, на кухне, выключает электрочайник (не обязатель­ но). Затем через модуль излучения ИК-команд отправляется код включения телевизора (многие телевизоры включаются коман­ дой выбора конкретного канала) на выбранную программу. Возвращаюсь• с ра6оты (модификаци• реwени•) Сценарий решения остается прежним (рис. 1.26). Мне не нравится держать компьютер, на котором работа­ ет псновная программа, весь день включенным только для
36 Глава 8 1 Базовая версия Электрический чайник -2 208 Блок питания = 128 Релейный модуль стремя реле Конвертер RS232-RS485 Модуль излучения ИК команд ~ ИК светодиод на телевизоре в гостиной Системная сеть Модуль цифровых вводов - 11- 1 1 11 1 1 11 1 ,_,_...!J L!.._• _1 Герконовый Герконовый датчик на датчик на двери входной гостиной двери Рис. 1.26. Структурная схема системы для модификации предыдущего сценария того, чтобы вечером он управлял работой системы. Я моди­ фицируЮ модуль цифровых вводов. Теперь при сраба1Ъ1вании герконового датчика входной двери он сам отправляет коман­ ды включения релейному модулю. А при срабатывании дат­ чика на двери гостиной он отправит команды выключения релейному модулю и команду включения телевизора модулю излучения ИК-команд. После модификации постоянно включенным оказывается только маломощный блок питания, обеспечивающий модули постоянным напряжением 12 В, и сами модули, потребляю­ щие очень маленький ток. Если мне не хочется по какой-то причине устанавливать гер­ коновый датчик на двери гостиной, я могу использовать клави­ шу пульта, закрепленного на стене в прихожей рядом с выклю­ чателем света. Проходя мимо пульта, я нажимаю эту клавишу, что инициирует продолжение работы того же сценария. Вмес­ то герконового датчика на двери в гостиную можно использо­ вать датчик движения, установленный в гостиной или замок с цифровым кодом на входной двери, который подаст команду
«Умный дом» вашего производства 37 «Встретить хозяина». Никаких переделок в системе для выпол· н:ния сценария мне делать не нужно. И, естественно, для по­ добного решения не нужен конвертер RS232-RS485 (как и в последующих решениях), но подразумевается, что компьютер вы все-таки используете , например, для выполнения первого или других сценариев, которые придумаете или сочтете инте­ ресными. Поэтому конвертер остался в системе. Создание эффекта nр11сутnв11я Практически все системы автоматизации жилья позволяют реализовать подсистему охраны. В отличие от специализиро­ ванных систем охраны, основным достоинством которых кроме высокой надежности является возможность стандарт· ного подключ ения к централизованным пультам охранных ведомств, системы автоматизации жилья позволяют создать эффект присутствия. Посмотрим, как может выглядеть сце­ нарий подобного решения, например, на вашей даче зимой, когда вы там не живете . Сценарий решения : рано утром на террасе включается свет, который спустя несколько минут гаснет. Следом вклю· чается свет в одной из комнат. Включается радиоприемник. Через полчаса он выключается. В комнате слышатся голоса, зажигается свет в другой комнате. Через час в доме наступа· ет тишина. Но ненадолго. Через час или два в доме вновь слышны голоса. Включается и выключается свет. Включается и выключается радиоприемник (рис. 1.27). Для реализации решения мне понадобится модифициро­ ванный релейный модуль. Я использую транзисторный радио­ приемник и кассетный магнитофон с пленкой, на которой за· писаны обычные домашние шумы и разговор. В данном случае сеть используется, если управление светом удобнее разнести по дому. В такой модификации один из релейных модулей бу· дет модифицирован, остальные останутся универсальными. Модификация релейного модуля No l сведется к тому, что будут использованы таймеры для задания интервалов време· - ни, которые становятся событиями системы, а отклик систе­ мы на события (сигналы таймеров) инициируется модифици· рованным релейным модулем, который отправляет команды
38 Гnааа • 1 Базоаа11 аерси11 Блок питания =12 в Конвертер RS232-RS485 Релейный модуль No1 с одним реле Системная сеть Релейный модуль No2 с одним реле Релейный модуль NoЗ с одним реле Радиоприемник Магнитофон Рис. 1.27. Структурная схема системы для сценария •ЭффектприсутствЙЯ• включения и выключения релейным модулям No2 и No3. Контакты реле, конечно, разрывают питающее напряжение. Если вы действительно не живете на даче, но хотите исполь­ зовать подобную подсистему, для имитации присуrствия можно подумать, например, о применении вместо силового освеще­ ния низковольтных маломощных светильников, работающих от батареек. Можно добавить сигнализацию, добавив модуль цифровых вводов, к входам которого подключить герконовые датчики, реагирующие на открывание дверей и окон. А в каче­ стве устройства тревоги использовать сирену. Бесспорно, вов­ се не обязательно для реализации сценария задействовать сис­ тему. Но, если вы будете использовать систему, то в летнее время, когда вы живете на даче, можете возложить на нее обя­ занности ежедневного полива огорода, включения света на крыльце в ночное время и т.д. К одному из внешних проявлений гибкости систем «Ум­ ный дом» я бы отнес тот факт, что трудно говорить о каких­ либо решениях без привязки к конкретным объектам, к кон­ кретным условиям, и даже к конкретным людям. Если вы дочитаете книгу до конца, пусть и не последова­ тельно, а выборочно, то сможете собрать все необходимые модули, модифицировать их и соединить. Обойдется это руб­ лей в 200-500 (без учета стоимости сирены, радиоприемника и магнитофона) . Вы проверите работу системы на столе и убедитесь в ее работоспособности. В один из выходных
«Умный дом» вашего производства 39 дней вы поедете на дачу и установите систему на месте. Про­ ве.rJите ее в работе. Убедитесь в том, что она работает. Осталось убедиться в том, что система нужна вам именно в том виде, в каком описана в сценарии, включая сирену, сра­ батывающую при открывании дверей и окон. Если ваш дачный участок охраняется, то да. Имитация присуrствия может отпугнуть нежелательных визитеров, а сирена, если они все-таки решат нанести визит, не только отпугнет их, но и привлечет внимание сторожа. Если дачный участок не охраняется, то нет. Имитация присуrствия отпугнет тех, кто будет наблюдать за вашей да­ чей длительное время, прежде чем отважится на посещение. Да и то в том случае, если не выпадет снег. Люди в доме, не оставляющие следов на снегу, скорее убедят наблюдателя в том, что его пытаются обмануть. Сирена, которая воет на весь поселок без появления людей, «поднятых по тревоге», тоже не слишком убедительна. Если дверь, на которую вы установили герконовый датчик для защиты от вторжения, не ходит ходуном под ветром, то да. В противном случае, нет, даже, если дачный поселок охра­ нят сторож. При перемещениях двери датчик будет срабаты­ вать, а сторож, привыкший к ложным срабатываниям систе­ мы, перестанет обращать внимание на сирену. Да и саму систему, если поселок охраняется, следует, на мой взгляд, сильно видоизменить. Модули цифровых вводов и си­ рену поставить в каждый дом поселка, соединив их между со­ бой, а лампу тревоги (или любой индикатор) разместить в доме сторожа. Если сторож время от времени будет оставлять «сле­ ды на снегу», то эффект присуrствия окажется полезен. Как видно из вышесказанного, конкретное решение сле­ дует выбирать только с учетом всех обстоятельств и особен­ ностей применения. Это же касается и, например, реализации описанных моду­ лей в квартире. Если вы достаточно опытны в работах с элект­ ричеством, можно эксперимент довести до конца, подключив к релейному модулю (или модулю с триаком) торшер или на­ стольную лампу. Если нет, лучше остановиться на применении светодиода. Тем более что сейчас появились светодиоды, обла· дающие очень большой светоотдачей. Их света вполне может хватить для подсветки темного коридора или холла.
40 Глава • 1 Базовая аерсия Цеnь nроекта Цель проекта - разработка любительской системы автомати­ зации жилья. За основу возьмем системы, о которых говори­ лось выше. Если не вдаваться в тонкости реализации разных концепций, на первом этапе будущую систему можно предста­ вить в виде центрального управляющего устройства и набора модулей, выполняющих разные функции, но подчиненных одной задаче - следить за состоянием датчиков и устройств управления, чтобы на основе их состояния включать, выклю­ чать и переключать бытовую технику (рис. 1.28). Центральное управляющее устройство (ЦУУ) Герконовый датчик Модуль цифровых вводов Термостат Модуль приема ИК команд Системная сеть Модуль излучения ИК кодов Релейный модУль Структура простейшей системы Рис. 1.28. Структура простейшей системы с базовыми модулями В качестве средств управления в системе промышленно­ го производства используются сенсорные панели и универ­ сальные ИК-пульты с запоминанием кодов. Не готов утверждать, что любительская разработка подоб­ ного рода устройств управления столкнется с непреодолимы­ ми трудностями, но если серийно производимое устройство оценивается в продаже в тысячу (и несколько тысяч) долларов, то и в любительской разработке оно может стоить не дешевле. По этой причине разработку средств управления подобного типа лучше пока оставить за профессионалами. Мы постараем­ ся реализовать простую систему, в которой компьютер бμет
Цепь проекта 41 v.rрать роль центральноrо управляющеrо устройства (и, в ка­ кон-то мере. устройства управления), и которая будет иметь несколько базовых модулей: релейный модуль, модуль приема системных ИК-команд, модуль излучения ИК-кодов и модуль цифровых вводов. Каково назначение каждоrо из этих модулей? Релейный модуль. Получая команды центральноrо управ­ ляющеrо устройства, он включает и выключает соответству­ ющее реле. С помощьiо контактов реле можно включать и выключать настольную лампу, торшер (и с'вет в комнате, уста­ новив модуль на место обычноrо выключателя, но я не сове­ тую делать это, если вы не профессиональный электрик), телевизор или музыкальный центр. Контактами реле может включаться и выключаться электрический чайник и утюr (возможно, пона,1.1обится добавить более мощный контактор). С ero же помощью можно «перемещать музыку», подключая к музыкальному центру rромкоговорители, установленные в разных помещениях. Одним словом, с помощью контактов реле можно включать и выключать все, что можно включать и выключать в принципе . Модуль приема системных ИК-команд. Системой хочет­ ся покомандовать. И не только с компьютера. Используем ста­ рый пульт управления от видеомагнитофона или телевизора, который завалялся на полке, и применим ero коды для управ­ ления системой. Модуль излучения ИК-кодов. Чтобы управлять с помощью системы телевизором или видеомагнитофоном необходимо иметь устройство, которое излучает ИК-коды управления ими. Модуль цифровых вводов - будет соединяться с датчика­ ми, например, rерконовыми и по запросу центральноrо управ­ ляющего устройства будет передавать состояние датчиков. В качестве сетевого интерфейса (дверка, за которой начи­ нается дороrа ко всем модулям системы) используем двухпро­ водный интерфейс RS485. Длина линии может достигать 1000 м, все системные устройства включаются параллельно, линия мало подвержена влиянию наводок и сама не наводит шумов на другие линии. Если для экспериментов применить четырехжильный провод, то по двум оставшимся проводам
42 Глава • 1 Базовая версия можно передавать напряжение питания для всех системных устройств. Этого достаточно для наших целей. Тем более что в плане деталей, которые нужны для создания интерфейса, это одна микросхема и один резистор. Какие схемы нам потребуется собрать до начала работы? Программатор, работающий с программой PonyProg2000 (упрощенная схема, более полная схема для PIC контролле­ ров будет приведена в Приложении), показан на рис. 1.29. В оригинальной версии есть примечание - микросхему стабилизатора напряжения LM2936-Z5 не советуют менять на стабилизаторы серии 7805. Поскольку рекомендуемая мик­ росхема есть в продаже, я не стал пренебрегать советом, хотя, по отзывам многих, собиравших программатор, этим советом можно пренебречь. Список необходимых для сборки программатора составляющих приведен в табл. 1.1. Таблица 1.1 . Спецификация проrрамматора No Обозначение Издеnие Коnичество Цена(р.) Примечания 1U1 Панелька 1 21 OIP18 2U2 LM2936-Z5 1 68 Не исnоль- зовать 7805 3 02,аз КТЗ15Д 2 10 401 КТЗ61Д 1 5 5 01-03 КД522 3 3 6 Z1-ZЗ КС147 3 6 7Z4 КС213 1 3 8R1 10 кОм 1 0.5 0,25 Вт 9 RЗ,R8-R10 4,7 кОм 4 2 0,25 Вт 10 R4 100 кОм 1 0.5 0,25 Вт 11 R2,R7 1 кОм 2 1 0,25 Вт 12 R5 2,2 кОм 1 0.5 0,25 Вт 13 С1,С2,С5 100нФ 3 30 14 сз 1нФ 1 5 15 С4,С6 47мкФ16В2 20 16 J1 (ОВ9) Разъем, 1 10 гнездо
R4 100k R2 1k ~ С1 100nF 14 12 Z1 5V1 Рис. 1.29 . Проrрамматордля работы с микроконтроллером PIC16F628A РС Serial por1 J1 DB9FEMALE ~ w
44 Гnава • 1 Базовая версия Ориентировочная стоимость элементов-186 руб., макет­ ная плата 100 руб. Всего 286 руб. Программатор подключается к СОМ-порту (я подключал его к СОМ2, отведя COMl для конвертера). При точной и аккуратной сборке схема работает сразу. В качестве соединительного кабеля между программато­ ром и компьютером я использовал несколько проводов плос­ кого ·кабеля, которые были «под рукой». Думаю, подойдет ка­ бель от старой «Мышки» или отрезок с витыми парами для компьютерной сети. Длину этого отрезка лучше сделать не­ большой, чтобы с программатором бьшо удобно работать. Если купить макетную плату достаточных размеров, часть ее можно использовать для программатора, а часть пригодит­ ся для конвертера RS232-RS485 . Остатка же хватит на макет­ ную плату для прототипов всех модулей . У меня программа­ тор свободно разместился на плате 90х40 мм. Конвертер RS232-RS485 - нужен для общения компьюте­ ра со всеми модулями системы. Он также несложен в сборке, поскольку представляет собой пару микросхем с небольшим количеством дополнительных элементов. Я использовал толь­ ко один резистор 120 Ом в линии. При длинной линии (в сотни метров) такой же резистор желательно поставить на конце линии, выполнив ее витой парой (рис. 1.30). Необходимые элементы конвертера приведены в табл. 1.2. Табnица 1.2 . СnецмфикаЦМ11 конвертера No Обозна- Изделие Количество Цена Примечания чение (р.) 1 DA1 МАХ232АСРЕ 1 80 2 DA2 МАХ1483 1 96 зR1 120 Ом 0,25 Вт 1 1 4 С1-С5 0,1 мкФ 5 5 5 DАЗ LM78L05 1 68 6Сб 47 мкФ 1 20 7 089 Разъем гнездо 1 10 8 Х1-Х2 Клеммник 1 10 Любой на 6 конт.
РССОМ-nорт С1 16 МАХ232А С2 RS232 DB9 интерфейс female СЗ R~~§2·~ TDЗ GND 5 15 DA1 +58 + 12В 1---.. ... ...- -. 1 _L ti_ Т-З! LМ78L05 c5:r: I Х1 С6 1 DАЗ_1_2 2 6 :J_C4 :r: slDA2 ~ МАХ148З RS485 интерфейс 16 ·1 Х2 системная сеть 2 1 ' -- 1 •·2 _, 1 7 sг---1 GND -----е-~-- ·З ...,.. ___ ___ ___ __._ __ _,.. ___ __ ___ _., ___4 Рис . 1.30. Схема конвертера RS232-RS485 .i:i.. c.n
46 Глава • 1 Базовая версия Ориентировочная стоимость изделий - 290 руб. Клеммник я использовал для подключения линии, внеш­ него (и общего для всех модулей) источника питания 12 В и проводов передачи питания на макетную плату, куда уста­ новлен 4-контактный клеммник. Таким же образом можно подключать все модули, соединяя их последовательно. При этом следует учитывать, что по мере удаления от общего ис­ точника питания напряжение может понижаться за счет па­ дения напряжения на проводах. Это сказывается на работе удаленных релейных модулей. Реле с рабочим напряжением 12 В может потреблять ток порядка 50 мА. Обе микросхемы конвертера подключены к источнику питания 12 В через микросхему стабилизатора 7805 так же, как микросхемы мо­ дулей. Некоторые параметры микросхемы МАХl 483 и цоко­ левка показаны на рис. 1.31и1.32. МАХЗО82/МАХЗО85/МАХЗ088 TRANSMIТТING INPIJТS OUТPUTS RE DE 01 B/Z А/У х 1 1 о 1 х 1 о 1 о о о х High-Z High-Z 1 о х Shutdown RESEIVJNG JNPUTS OUTPUT RE DE А-В RO о х ' 1:0.05V 1 о х S?0.02V о о х Open/shorted 1 1 1 х High-Z 1 о х Shut down Рис. 1.31 . Табnица состояний микросхемы МАХ1483 На этом приготовления к началу работы можно считать законченными, если вы установили на компьютере програм­ мы МРLАВ и PonyProg2000.
TOPVIEW DIP/SO Vcc в А GND I0,1mF МАХЗО82 DIP/SO Рис. 1.32. Типовая схема включения микросхем МАХЗО82 (МАХ1483) DE D1 RO о1:1о .....
48 Глава • 1 Базовая версия Первую разработку проведем «На бумаге», точнее в редак­ торе программы МРI.АВ. После программирования контрол­ лера «на бумаге» перейдем к его налаживанию в программе МРLАВ. Схема и nроrрамма репейноrо модупя Функциональная схема модуля состоит из интерфейса, кон­ троллера и адресного селектора, образующих базу для пост­ роения остальных модулей, а отличительной особенностью данного модуля является использование реле (рис. 1.33). Реле я включил через транзисторный ключ . В зависимости от кон­ кретного реле, которое вы выберете, транзисторный ключ может оказаться лишним. Системная сеть Uпит+12В .--------т--1 Стабилизатор 1-~--- Интерфейс RS485 Микроконтроллер PIC16F628A Адресный селектор Реле= 128 Рис. 1.33. Функциональная схема репейного модуля Я не стал устанавливать реле на макетной плате. Реле - эле­ мент достаточно дорогой, и нет нужды покупать его без твер­ дого намерения использовать. Вместо него к выходам микро­ контроллера были подключены красные светодиоды АЛ307. Как выяснилось позже, получилось очень полезное решение при наладке и разработке других модулей (рис. 1.34). При сборке макета потребуются не все элементы, обозна­ ченные в табл. 1.3.
+ 128 001 8 С1_l_ 002 14 1:J:7 6 МАХ1483 PIC16F628A 17 4 8 1 - j (") х ~ 2 3 6 Q х ::::1 51 1 1" -· 1 :::з sl l_ 5 'О о... 'О Q ~Q'Оф :::. ф Х< % Рис. 1.34. Принципиальная схема релейного модуля о... о ~ '~~i• . i:. (О
50 Глава • 1 Базовая версия Табnица 1.3. Спецификаци. релейноrо модуля N2 Обозна- Изделие Количество Цена Примечания чение (р.) 1 DD1 МАХ1483 1 96 2 DD2 PIC16F628A 1 100 Установить на панельку 3 DDЗ LM2936-Z5 1 68 4 vт1 ктsозг 1 5 5 VD1, АЛ307 2 3 VD2 6 VDЗ КД522 1 3 7 VD4 АЛЗ07 1 3 8Р1 12В, 5д/-220 В 1 170 10 R1 -RЗ 1 кОм 0,25 Вт 3 1 11 R4-R7 10 кОм 0,25 Вт 4 1 12 R8 2,2 кОм 0,25 Вт 1 1 13 С1, С2 0,1 мкФ 2 5 14 сз 100мкФ16В 1 20 15 Х1 Кл. 6 конт. 1 10 16 51 Пер.2пол.4нап. 1 50 17 soc DIP18 1 21 Ориентировочная стоимость элементов - 558 руб. В целях экономии я отказался от установки на макетную плату реле и переключателя для организации адресного се­ лектора, распаяв соответствующие выводы, чтобы получить один адрес. На схеме показано одно реле, но их количество можно увеличить до 7-8, используя все свободные выводы портов А и В. Это определяется конкретными соображения­ ми по применению модуля. Например, если вы планируете использовать релейный модуль в своей комнате для включе­ ния торшера или настольной лампы, достаточно одного реле. Для безопасного включения лампы я советую использовать закрытую розетку со стандартным сетевым проводом. Одна из жил этого провода должна разрываться контактами реле. Настольная лампа включается в розетку, которая, в свою оче­ редь, подсоединяется к сети -220В. При замыкании контак­ тов реле напряжение подается на лампу. Поскольку неизвест­ но, какой из проводов вы коммутируете: нулевой или фазный, все работы лучше пр~изводить без напряжения.
Схема и проrрамма релейноrо модуля 51 После тщательной изоляции розетки и всех соединений включите лампу в вашу розетку, подключите мультиметр в режиме измерения сопротивления к вилке вашего провода и включите реле. Мультиметр должен показать такое же сопро­ тивление, что и настольная лампа, если измерить ее сопро­ тивление. После команды выключения реле тестер должен показать обрыв. В любом случае при первом включении сле­ дует соблюдать осторожность, а релейный модуль сразу поме­ стить в любую подходящую пластмассовую коробку. Команды, на которые модуль должен реагировать: • включить - Rxx$xN; • выключить - Rxx$xF; • передать статус - Rxx$xS . При передаче статуса используем следующую символику: • включено - Rxx#xN; • выключено - Rxx#xF. Здесь Rxx$xN означает: R - релейный модуль, хх - два сим­ вола адреса от 00 до 15, $ - символ команды ( # - символ стату­ са), х - номер реле от О до 7, N - включить (F - выключить). Набор и формат команд вы можете переопределить по своему вкусу или сообразуясь с целями. Для этого достаточно внести изменения в исходные коды, приводимые ниже . Для адресации используются четыре бита порта В (RВ4- RВ7), что позволяет адресоваться к 16 модулям. Для тех, кому не терпится опробовать готовые решения, кому это не интересно или не нужно знать, как программиро­ вать модуль, я сразу приведу текст программы модуля на ас­ семблере, текст программы на языке программирования С и НЕХ-файл для загрузки в программатор. · Проrрамма модуn• наассем6nере list p=lб f 628a #include plбf628a.inc Инициализация мо.цуля. ВСF STAТUS, RPl ; Выбор банка О.
52 Гnава • 1 Базовая версия ВСF STAТUS, RPO CLRF PORTA MOVLW Ох07 MOVWF СМСОN ВСF STAТUS, RPl BSF STAТUS, RPO MOVLW ОхВО MOVWF TRISA MOVLW ОхFб MOVWF TRISB BCF STAТUS, RPl ВСF STAТUS, RPO CLRF PORTB Настройка порта А. Выбор банка 1 . Настройка порта В. Выбор банка О. ;Настройка приемопередатчика USART BSF RCSTA, SPEN BCF RCSTA, RX9 BSF RCSTA, CREN BCF STAТUS, RPl BSF STAТUS, RPO BCF TXSTA, ТХ9 ВСF TXSTA, SYNC BSF ТХSТА, BRGH MOVLW Охlб MOVWF SPBRG ВСF STAТUS, RPl ВСF STAТUS, RPO CLRW ADI:Yf/F PORTB, О ANDLW OxFO MOVWF Ох20 SWAPF Ох20, 1 битами. CALL adrsim ; Настройка приемника. Выбор банка 1 . ; Настройка передатчика. ; Выбор банка О. Считывание собственного адреса. Прочитаем порт В. Нам не нужны младшие биты. Сохраним адрес в 20h. ; Нам не нужна работа с младшими Преобразуем его в символьный вид. ; прочитаем из EEPROM ЗОh - состояние реле. BSF STAТUS, RPO ВСF STAТUS, RPl MOVLW ОхОО MOVWF EEADR BSF EECONl, RD ; Выбор банка 1. Адрес считываемого регистра. Чтение.
MOVF EEDATA,W ВСF STATUS, RPl ВСF STAТUS, RPO MOVWF ОхЗО СОМF ОхЗО,1 CLRW ADDWF ОхЗО,О MOVWF PORTA Схема и программа репейного модуля 53 w = EEDATA. Выбор банка О. Будем хранить в EEPROM в инверсном виде. А в регистре ЗОh в прямом. Перепишем ЗОh в порт. ; вачало работы, ожидание команды, отработка первой команды. CLRW ; Очищаем аккумулятор, ждем ком~нды по USART. start: ВТFSS PIRl, RCIF ; Ждем прихода первого символа команды . GОТО start ВСF STAТUS, RPl ; Выбор банка О. ВСF STAТUS, RPO CALL cmnd обработку . . ;С приходом первого символа начинаем GОТО start NOP ; Обработка команды - проверка адреса, определение команды . cmnd: BCF STAТUS, Z MOVF RCREG, О XORLW Ох52 Проверим, наш ли МОдУЛЬ R (52h). BTFSS STAТUS, Z ; Если нет, вернемся REТURN inl: BTFSS PIRl, RCIF ; Ждем прихода первого символа адреса. GОТО inl Если совпадает, прододжим. MOVF RCREG, О ВСF STATUS, Z XORWF Ох21, О BTFSS STAТUS, Z Первый символ адреса. in2 : BTFSS PIRl, RCIF ; Ждем прихода второго символа адреса. GОТО in2 ; Если совпадает, продолжим.
54 Глава • 1 Базовая версня MOVF RCREG, О BCF STAТUS, Z XORWF Ох22, О BTFSS STAТUS, Z RE'IURN Второй символ адреса. inЗ : BTFSS PIRl , RCIF ; Ждем прихода символа. GОТО inЗ ; Если за адресом следует символ команды, продолжим. MOVF RCREG, О BCF STATUS, Z XORLW Ох24 Быполнение $ !i4h) . BTFSC STATUS, Z CALL swtch RE'IURN Вызываем подпрограмму выполнения. ;Подпрограмма перевода адреса в символы, их храним в 21h, 22h. adrsim: CLRW Если адрес 1, запишем символы 01 (30h и Зlh). 32h). ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох31 МOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Oxl BTFSC STATUS, Z REГURN CLRW Если адрес 2, запишем символы 02 (30h и ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох32 MOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Ох2 BTFSC STAТUS, Z
Схема и программа релейного модуля 55 REТURN CLRW Если адрес 3, запишем символы 03. ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW ОхЗЗ MOVWF Ох22 MOVF Ох20, О ВСF STATUS, Z XORLW ОхЗ BTFSC STATUS, Z REI'URN CLRW Если адрес 4, запишем символы 04. ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох34 MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Ох4 BTFSS STAТUS, Z REWRN CLRW Если адрес 5, запишем символы 05. ADDLW ОхЗО МOVWF Ох2 1 CLRW ADDLW Ох35 MOVWF Ох22 MOVF Ох20, О ВСF STATUS, Z XORLW Ох5 ВТFSS STAТU S , Z REWRN CLRW Если адрес 6, запишем символы Об. ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW ОхЗб
56 Гnава • 1 Базовая версия МOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Охб BTFSS STAТUS, Z REТURN CLRW Если адрес 7 , запишем символы 07 • ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох37 МOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Ох7 BTFSS STAТUS, Z REТURN CLRW Если адрес В, запишем символы ОВ. ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW ОхЗВ MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW ОхВ BTFSS STAТUS, Z REТURN CLRW Если адрес 9, запишем символы 09. ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW Ох39 МOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Ох9 BTFSS STAТUS, Z REТURN
Схема н программа релейного модуnя 57 CLRW Если адрес 10 (А) , запишем символы 10. ADDLW Ох31 MOVWF Ох21 CLRW ADDLW ОхЗО MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW ОхА ВТFSS STAТUS, Z RE'ItJRN CLRW Если адрес 11, запишем символы 11. ADDLW Ох31 МOVWF Ох21 CLRW ADDLW ОхЗl МOVWF Ох22 МOVF Ох20, О ВСF STAТUS, Z XORLW ОхВ BTFSS STAТUS, Z RE'IURN CLRW Если адрес 12, запишем символы 12. ADDLW ОхЗl MOVWF Ох21 CLRW ADDLW Ох32 MOVWF Ох22 MOVF Ох20, О ВСF STATUS, Z XORLW ОхС BTFSS STAТUS, Z RE. ' I'URN CLRW Если адрес 13, запишем символы 13 . ADDLW Ох31 MOVWF Ох21 CLRW ADDLW ОхЗЗ МOVWF Ох22 MOVF Ох20, О
58 Глава • 1 Базовая версия ВСF STAТUS, Z XORLW OxD BTFSS STATUS, Z REТURN CLRW Если адрес 14, запишем символы 14. ADDLW Ох31 МOVWF Ох2 1 CLRW ADDLW Ох34 MOVWF Ох22 MOVF Ох20, О ВСF STATUS, Z XORLW ОхЕ BTFSS STAТUS , Z REТURN CLRW Если адрес 15, запишем символы 15. ADDLW Ох31 МOVWF Ох21 CLRW ADDLW Ох35 MOVWF Ох22 MOVF Ох20, О ВСF STATUS, Z XORLW OxF BTFSS STAТUS, Z REТURN Подпрограмма включение реле по номеру . cmdset: CLRW ADDWF Ох23, О ВСF STATUS, Z XORLW ОхО BTFSC STAТUS , BSF ОхЗО, О CLRW ADDWF Ох23, О BCF STATUS, Z ; Запишем в ЗОh (установить бит) . Реле О. z XORLW Oxl Реле 1. ВТF SС STAТPS, Z BSF ОхЗО, 1
CLRW ADDWF Ох23, о ВСF STAТUS, z XORLW Ох2 BTFSC STAТUS, BSF ОхЗО, 2 CLRW ADDWF Ох23, о ВСF STAТUS, z XORLW ОхЗ BTFSC STAТUS, BSF ОхЗО, 3 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Ох4 BTFSC STAТUS, BSF ОхЗО, 4 CLRW ADDWF Ох23, О ВСF STAТUS, Z Схема и программа релейного м0Ауn11 59 Реле 2. z Реле 3. z Реле 4. z XORLW Ох5 Реле 5. ВТFSС STAТUS, Z BSF ОхЗО, 5 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Охб Реле 6. BTFSC STAТUS, Z BSF ОхЗО, 6 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Ох7 Реле 7. ВТFSС STATUS, Z BSF ОхЗО, 7 REТURN Подпроrрамма выключения реле по номеру. andrese t : CLRW ADJ:МF Ох23, О ВСF STAТUS, Z ; Запишем в ЗОh (сбросить бит) .
60 Гnава • 1 Базовая версия XORLW ОхО ; Реле О. BTFSC STATUS, Z BCF ОхЗО, О CLRW ADDWF Ох23,О BCF STAТUS, Z XORLW Oxl Реле 1. BTFSC STATUS, z BCF ОхЗО, 1 CLRW ADDWF Ох23,О BCF STAТUS, Z XORLW Ох2 Реле 2. BTFSC STATUS , z BCF ОхЗО, 2 CLRW ADDWF Ох2),О ВСF STAТUS, Z XORLW ОхЗ Реле 3. BTFSC STAТUS, z BCF ОхЗО, 3 CLRW ADDWF Ох23 , О ВСF STAТUS, Z XORLW Ох4 Реле 4. BTFSC STAТUS, z ВСF ОхЗО, 4 CLRW ADDWF Ох2 3,О BCF STAТUS, Z XORLW Ох5 Реле 5. BTFSC STAТUS, z ВСF ОхЗО, 5 CLRW ADDWF Ох23 , О ВСF STATUS, Z XORLW Охб Реле 6. BTFSC STATUS , z ВСF ОхЗО, 6 CLRW ADDWF Ох23 , О BCF STAТUS, z XORLW Ох7 Реле 7.
Схема и программа релейного модуля б1 BTFSC STATUS, Z ВСF ОхЗО, 7 RJmJRN Подпрограмма определения команды N (включить), F (выключить) ; или S (состояние) . swtch: CLRW in4: BTFSS PIRl, RCIF GОТО in4 ; Ждем прихода символа. MOVF RCREG, О MOVWF Ох23 MOVLW ОхЗО SUBWF Ох23, О MOVWF Ох23 in5: BTFSS PIRl, GОТО in5 MOVF RCREG, О MOVWF Ох24 ВСF STATUS, Z Прочитаем номер реле. Сохраним номер реле в 2Зh. Запишем ЗОh в аккумулятор. ; Переведем символ в номер. Сохраним номер реле в 23h. RCIF ; Ждем прихода символа. Прочитаем команду N-включить F-выключить . Сохраним команду в 24h. XORLW Ох4Е Включение N (4Eh). BTFSC STATUS, Z; Если не включить, то пропустить. CALL cmdset MOVF Ох24, О Перепишем из 24h в аккумулятор. ВСF STATUS, Z XORLW Ох46 Выключение F (46h). BTFSC STAТUS, Z; Если не выключить, то пропустить. CALL cmdr eset MOVF Ох24, О Перепишем из 24h в аккумулятор. BCF STATUS, Z XORLW Ох53 S (53h) запрос статуса . BTFSC STATUS, Z; Если не запрос статуса , то пропустить. CALL stat Сохраним состояние всех реле в энерrонезависимой памяти. CLRW ; Запишем ЗОh - состояние реле BSF STAТUS, RPO ; Выбор банка 1 . ВСF SТAТUS, RPl MOVLW ОхОО Запишем Oh в аккумулятор. в EEPROM. MOVWF EEADR Запишем адрес Oh в реrистр адреса.
62 Глава 8 1 Базовая версия ВСF STAТUS, RPl; Выбор банка О. ВСF STAТUS, RPO CLRW ADDWF ОхЗО,О СОМF' ОхЗО,О BSF STAТUS, RPO ; BCF STAТUS, RPl MOVWF EEDATA Запишем содержимое ЗОh в аккумулятор. Инвертируем перед сохранением. Выбор банка 1 . BSF EECONl , WREN ; Разрешить запись . ВСF INТCON, GIE; Запретить прерывания. MOVLW Ох55 MOVWF EECON2 MOVLW ОхАА MOVWF EECON2 BSF EECONl, WR BSF INТCON, GIE ; ВСF EECONl, WREN ВСF STAТUS, RPl ; BCF STAТUS, RPO Записать 55h. Записать AAh. ; Установить флаг для начала запись. Разрешить прерывания. ; Запретить запись. Выбор банка О. chkwr: ВТFSS PIRl, EEIF GОТО chkwr Проверка завершения записи. CLRW ADDWF ОхЗО, О MOVWF PORTA BCF PIRl, EEIF REТURN Перепишем ЗОh в порт. Сбросим флаг. Подпрограмма передачи статуса реле. stat: ВСF STAТUS, RPl ; Выбор банка О. ВСF STAТUS, RPO CLRW Проверим реле О. ADDWF Ох23, О BCF STAТUS, Z XORLW ОхО Реле О. BTFSC STATUS, Z CALL relO CLRW ADDWF Ох23, О BCF STAТUS, Z Проверим реле 1. XORLW Oxl Реле 1. BTFSC STATUS, Z
CALL rell CLRW ADIМF Ох23, О ВСF STAТUS, Z Схема и программа релейного модуля 63 Проверим реле 2 . XORLW Ох2 Реле 2. BTFSC STATUS, Z CALL rel2 CLRW ADIМF Ох23, О ВСF STAТUS, Z Проверим реле 3. XORLW ОхЗ Реле З• BTFSC STAТUS, Z CALL relЗ CLRW ADIМF Ох23, О BCF STAТUS, Z Проверим реле 4. XORLW Ох4 Реле 4. BTFSC STAТUS, Z CALL rel4 CLRW Проверим реле 5 . ADDWF Ох23, О ВСF STAТUS, Z XORLW Ох5 Реле 5. BTFSC STAТUS, Z CALL rel5 CLRW ADIМF Ох23, О BCF SТAТUS, Z Проверим реле 6. XORLW Охб Реле 6. BTFSC STATUS, Z CALL relб CLRW ADDWF Ох23, О ВСF STAТUS, Z Проверим реле 7. XORLW Ох7 Реле 7. BTFSC STAТUS, Z CALL rel7 Теперь это все отправим в передатчик. BSF PORTB, О Переключим драйвер . RS485 на передачу. ВСF STAТUS, RPl; Выбор банка 1. BSF STAТUS, RPO
64 Глава • 1 БаэоваА вереи~ BSF TXSTA, TXEN; Разрешаем передачу . BCF STAТUS, RPl; Выбор банка О . BCF STATUS, RPO MOVLW Ох52 MOVWF TXREG ; Отправим символ МОдУЛЯ . BCF STAТUS, RPl; Выбор банка 1. BSF STAТUS, RPO outdatO: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdatO ВСF STAТUS, RPl; Выбор банка О. ВСF STAТUS, RPO CLRW ADDWF Ох21,0 MOVWF TXREG Отправим первый символ адреса. BCF STAТUS, RPl; Выбор банка 1. BSF STATUS, RPO outdatl: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdatl BCF STAТUS, RPl ; Выбор банка О. ВСF STAТUS, RPO CLRW ADDWF Ох22, О MOVWF ТXREG ; Отправим второй символ адреса. ВСF STAТUS, RPl ; Выбор банка 1 . BSF STAТUS, RPO outdat2: BTFSS TXSTA, TXIF ; Ждем отпра вки символа. GОТО outdat2 ВСF STAТUS, RPl; Выбор банка О . BCF STAТUS, RPO MOVLW Ох23 MOVWF TXREG ; Отправим символ статуса. ВСF STAТUS, RPl ; Выбор банка 1. BSF STAТUS, RPO outdatЗ: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdatЗ BCF STAТUS, RPl; Выбор банка О. BCF STAТUS, RPO CLRW ADDWF Ох23,О
Схема н программа релейного модуля 65 ADDLW ОхЗО MOVWF ТXREG Оrправим символ номера реле. ВСF STAТUS, RPl; Выбор банка 1. BSF STAТUS, RPO outdat4: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdat4 ВСF STAТUS, RPl ; Выбор банка О. BCF STAТUS, RPO CLRW ADIМF Ох25,О MOVWF TXREG , Отправим символ состояния реле. ВСF STAТUS, RPl ; Выбор банка 1 . BSF STAТUS, RPO outdat5: BTFSS TXSTA, RCIF ; Ждем отправки символа. GОТО outdat5 ВСF TXSTA, TXEN; Запрещаем передачу. BCF STATUS, RPl ; Выбор банка О. BCF STAТUS, RPO BCF PORTB, О Переключим драйвер RS485 на прием. RE'IURN ;Подпрограмма обработки статуса реле. relO: BTFSC ОхЗ О, О CALL sostn BTFSS ОхЗО, О CALL sostf RE'IURN rell: BTFSC ОхЗО, 1 CALL sostn BTFSS ОхЗО, 1 CALL sostf RE'IURN rel2: BTFSC ОхЗо' 2 CALL sostn BTFSS ОхЗО, 2 CALL sostf RE'IURN relЗ: BTFSC ОхЗО, З CALL sostn BTFSS ОхЗО, З
66 Глааа • 1 Базовая версия CALL sostf REТURN rel4: BTFSC ОхЗО, 4 CALL sostn BTFSS ОхЗ О, 4 CALL sostf REТURN rel5: BTFSC ОхЗО , 5 CALL sostn BTFSS ОхЗО, 5 CALL sostf REТURN relб: BTFSC ОхЗО, 6 · , CALL sostn BTFSS ОхЗО , 6 CALL sostf REТURN rel7: BTFSC ОхЗО, 7 CALL sostn BTFSS ОхЗО, 7 CALL sostf REТURN Подпрограммы образования символов состояний . sostn: MOVLW Ох4Е ; Состояние - включено. MOVWF Ох25 REТURN sostf: MOVLW Ох46 Состояние - выключено. END MOVWF Ох25 REТURN Проrрамма peneiiнoro модуn• на А3ыкеС Фаiiп заrоповка #define MODULNAМESIM "R" #define CМDSIM "$ " #define Ьitset(var,bitno) ((var) 1= 1 << (bitno)) #define bitclr(var,Ьitno) ((var ) &= -(1 << (bitno )))
Схема н программа релейноrо модули 67 void putch(unsigned char); unsigned char getch (void) ; int init_comms (); int sirn_num _adr(); int cm:l(); int rel_on (int num) ; int rel_off(int nurn); int rel_stat(int num); Основной файл #include <piclбf62xa.h> #include <stdio.h> #include "reley_c .h" unsigned char input; регистра. 11 Для считывания приемного / / Первый символ адреса мо.цуля. //Второй символ адреса мо.цуля. / / Символ реле. unsigned char MOD_SIMl; unsigned char MOD_SIМ2; unsigned char REL_SIM; unsigned char command_reciev KOМillЩЬI. int Z.ЮD_ADDR; int sim_end_nurn = О; МОдУЛЯ. [6]; //Массив для полученной //Заданный адрес МОдУЛЯ, как число. / / Полный символьный номер int МOD_NUМ; // Полученный адрес МОдУЛЯ, как число. int REL_NUМ; //Номер реле. unsigпed char RELSTAT = О; 11 Статус реле (позиционно): 1-вкл,о - выкл. int i; 11 Получение байта. unsigned char getch() { while( !RCIF) continue; return RCREG; //Устанавливается, когда регистр не пуст. 11 вывод ОДНОГО байта . void putch(unsigned char Ьуtе) {
68 Гnава • 1 Базовая версия while( !ТXIF) continue; TXREG = Ьуtе; //Устанавливается , когда регистр пуст. //Преобразуем символьный адрес в число. int sim_num_adr() { sim_end_num = О; MOD_SIMl = coпunand_reciev [1]; //Первый символ номера. MOD_SIМ2 = coпunand_reciev [2]; //Второй символ номера. MOD_SIMl = MOD_SIMl - ОхЗО; //В виде числа. MOD_SIM2 = MOD_SIM2 - ОхЗО; sim_end_num = MOD_SIMl*OxOA + MOD_SIM2; return sim_end_num; // Получение и выполнение команды. int cmd() { REL_SIМ = command_reciev (4]; REL_NUМ = REL_SIM - ОхЗО; switch (command_reciev [5]) case "N": rel_on (REL_NUМ) ; break; case "F": rel_off (REL_NUМ); break; case • s •: rel_stat(REL_NUМ); break; //Выполнение команды включения заданного реле. int rel_on(int num) { Ьitset (RELSTAT' REL_NUМ) ; PORTA = RELSTAT; EEADR =ОхО; //Запишем состояние реле в EEPROM. EEDATA = -RELSTAT; WREN = 1; GIE =О; EECON2 = Ох5 5;
EECON2 = ОхАА; WR =1; while (WR); GIE=1; WREN = О; Схема н программа реленноrо модуля 69 //Выполнение команды выключения заданного реле. int rel_off(int nшn) { } Ьitclr (RELSTAT. REL_NUМ) ; PORTA = RELSTAT; EEADR =ОхО; EEDATA = -RELSTAT; WREN = 1; GIE =О; EECON2 Ох55; EECON2 = ОхАА; WR =1; while (WR); GIE=1; WREN = О; //Запишем состояние реле в EEPROM . 11 Выполнение команды передачи состояния заданного реле. int rel_stat(int nшn) { cornmand_reciev[O] "R"; cornmand_reciev[l] = МOD_SIMl+OxЗO; coпunand_reciev[2] = MOD_SIМ2+0x30; command_reciev [З] = "#"; coпunand_reciev[4] = REL_SIM; if {(RELSTAT>>REL_NUМ)&OxOlJ coпunand_reciev[5] = "N"; if (!((RELSTAT>>REL_NUМ)&OxOl)} command_reciev[5] = "F"; CREN =О; / / Запрещаем прием. RBO=1; //Переключим драйвер RS485 на передачу. TXEN = 1; / / Разрешаем передачу. for (i=O; i<б; ++i} putch(command_reci ev[i]); for (i=O;i<lOOO;i++J; //Задержка для вывода for (i=O; i <б ; ++iJ command_reciev {i] = • "; RBO=О; / / Выключаем драйвер RS485 на передачу. TXEN = О; / / Запрещаем передачу. CREN =1; 11 Разрешаем прием.
70 Глава • 1 Базова11 верси11 int init_comms () / / Инициализация мо.цуля. { PORTA = ОхО; //Настройка портов А и В . CMCON = Ох7; TRISA = ОхО; TRISB = OxFE; RCSTA = ОЬ10010000; TXSTA = ОЬ00000110; SPBRG = Ох68; 11 Настройка приемника. 11 Настройка передатчика. RBO=О; 11 Настройка режима приема-передачи. //Выключаем драйвер RS48~ на передачу. //Прочитаем состояние реле из EEPROM. EEADR = ОхО; RD =1; RELSTAT = - EEDATA; PORTA = RELSTAT; } void main(void) { init_coпrns (); 11 Инициализация мо.цуля. for (i=O; i<б; ++i) command_reciev [i] =" "; cornmand_reciev [О] = "R"; //Прочитаем и преобразуем номер модуля. MOD_ADDR = PORTB; // Номер мо.цуля в старших битах . МOD_ADDR=МOD_ADDR»4; 11 Сдвинем на четыре бита. 11 Начинаем работать. start: CREN =1; input = getch(); switch (input) { case "R": //Если обращение к релейному модулю. for (i=l; i<б; ++i) // Запишем коман.цу в массив. { input = getch(); command_reciev [i] i nput; МOD_NUМ = sim_nUЛLadr () ; 11 Чтение из сети. if (MOD_NUМ != MOD_ADDR) break; 11 Если не наш адрес . else if (command_reciev [З] = "$") cmd (); //Если команда.
Схема и программа реnейноrо модуля 71 default: goto start; goto start; НЕХ-файл 1111• эаrррки в nporpaммarop :10000000830100308AODD428203084003830DD201D :100010008301392B04068001840A0406031DOA2883 :020020000034АА :1004E20083018ClE712AlA0808008301B700831247 :1004F20003130ClE782A370899DOOBOOF401F5014D :10050200031DFЗDCF20CD31CBD2A7008F407710817 :100512000318710AF5070310FDDDF1DD7208730448 :1005220003190034812A8301850107309F00831655 :100532008501FЕ30860090308312980006308316СЗ :100542009800683099008312061083169B011Cl4DO :100552001A098312A200850008008301AD01AE01Dl :100562003008АО003108А100DОЗОА007А1070АЗ04Е :10057200F200F3012008FOOOF1017F222108740744 :10058200AD0075080318750AAEOOF1002DOBFOOOE1 :1005920008000130F000831203132908F100F10A68 :1005A200D42A0310FOODF10BD22A7008A2042208FВ :1005В200850083169В018312220983169А001С155В :1005C2008B1355309D00AA309D009C149C18E72A7D :1005D2008Bl71Cll831208000130F00083120313El :1005E2002908F100F10AF72A0310FOODF10BF52AAO :1005F2007009A2052208850083169B018312220935 :1006020083169A001C158Bl355309DOOAA309D004D :100612009C149C1 80A2 B8B171C118312080083014F :100622003308AЗOODOЗOFOOOFF30F1002308700738 :10063200А90071080318710ААА002Е2В2908В50017 :100642002А08Вб00СА2А2908В5002А08В600ЕD2АЕ7 :100652002908В5002А08В6008С2В3408463А0319ЗВ :10066200242ВОВЗА03191F2В1DЗАО31D0800292ВВЕ :100672009422АВ0 1АС01462В2 В082FЗЕ8400831ЗЗЕ :1006820020308000АВОА0319АСОА2СОВВОЗАFОООЗЗ :100692008030700 2 063003192В02031СЗD2 В52 3 0АЕ :1006A200AF000608A500A6010430F000260DA60C36 : 1006В200А50СFООВ572В852ВАВ01АВОААС012С0818 :1006C200803AF00080307002063003192B020318C2 :1006D200762B7 1 22A4002B082FЗE8400831324085A : 1006Е2008000АВОА0319АСОА602ВАЕ2 27008А70087
72 Глава • 1 Базовая версия :1006F2007108A8002606031D802B25082706031D66 :10070200852В24ЗОВ200102318167122А40052ЗАОD :1007120003195D2В852В52308301АF002008ЗОЗЕЗВ :10072200В0002108ЗОЗЕВ1002ЗЗОВ2002308ВЗООЕС :100732002208F0002908F100F10AA12B0310FOOCA5 :10074200F10B9F2B7008F000701CA92B4E30B400E7 :100752002208F0002908F100Fl0AВ12B0310FOOC75 :10076200Fl0ВAF2B7008F0007018B92B4630B400BЗ :1007720018120614831698168312АВ01АС012С08СА :10078200803AF00080307002063003192B02031801 :10079200D42В2В082FЗЕ8400831300087622АВОА49 :1007А2000319АС0АСО2ВАВ01АС012С08803АFО0053 :1007В200В3307002Е83003192В020318Е42ВАВОАD2 :1007C2000319ACOAD62ВAВ01AC012C08803AF0001D :1007D20080307002063003192B020318FA2B2B0803 :1007Е2002FЗЕ8400831320308000АВОА0319АСОА29 :OE07F200E62B061083169812831218160800C4 :OOOOOOOlFF С теми, кому интересно провести эксперименты, не имея опыта работы с микроконтроллерами и программным обес­ печением или желая более детально ознакомиться с модулем, мы продолжим разговор о том, как это все устроено. Требования к модулю: • модуль должен иметь реле, контакты которого позволят подключить нагрузку с параметрами: -220В, IOA (мощ­ ности нагрузки - 2 кВт) ; • модуль должен иметь сетевой интерфейс RS485 (сис­ темная сеть); • по отношению к системной сети модуль должен быть пассивным, то есть его основным режимом работы бу­ дет прослушивание сети и выполнение команд, полу­ ченных по сети, если они адресованы модулю; • адрес модуля задается установкой переключателя в со­ ответствующее положение. Поскольку контроллер PIC16F628A имеет встроенный USART, мы используем его для работы с интерфейсом RS485. Адресный селектор можно организовать на микрокон­ троллере различным образом. Для начала используем наибо­ лее очевидный способ - выводы порта, включенные на ввод
Схема н программа реnенноrо модуля 73 информации, соединим с контактами переключателя, кото· рый устанавливает их в состояние - «1» или «О». В дальней· шем мы обсудим другие способы задания адреса. Четыре бита дают возможность адресоваться к 16 устройствам. Для подачи сетевых команд используем СОМ·порт компь· ютера с передачей байта {рис. 1.35). Биты данных Пауза ст. (линия свободна) (msb) мл. " (lbs) g.; ".о'=. 1 Высокий ! U ! . . . :•• 5" '.· 5" '.· 2 ':: 3'4' 5'6 ':.7 ::: !(.)!(.)! Низкий оо о ! 4мкс фрейм данных - 44 мкс Рис. 1.35. биты данных RS232 из статьи на сайте http://measure.chat.ru Каждый бит имеет длительность 4 мкс {при данной скорости). Для обращения к релейным модулям используем дополни· тельный адресный префикс «R ». Практически , мы определились со всем необходимым, чтобы приступить к построению релейного модуля. Команды, которые будет принимать наш модуль: • включить - Rxx$xN; • выключить - Rxx$xF. Я добавлю команду передачи модулем состояния реле: • передать статус - Rx x$xS. При передаче статуса используем следующую символику: • включено - Rxx#xN; • выключено - Rxx#xF. Здесь Rxx $xN означает: R - релейный модуль, хх - два сим­ вола адреса от 00 до 15, $ - символ команды (# - символ стату­ са}, х - номер реле от О до 7, N - включить (F - выключить). Уточним, как мы будем использовать ресурсы контролле­ ра. Для ввода информации используем встроенный в кон· троллер USART.
7 4 Глава 8 1 Базовая версня Использование порта В: • RВО -управление передатчиком (микросхема МАХI483). • RВI - прием (приемник USART). • RВ2 - передача (передатчик USART). Для ввода заданного адреса используем четыре старших бита порта В (RВ7-RВ4) . Использование порта А:. • для подключения реле используем биты порта А (RAO- RA7), что предполагает использование восьми реле; • при необходимости увеличить количество реле можно использовать свободные (если они есть) биты порта В. Мы готовы приступить к написанию программы. Основные блоки проrраммы: • инициализация (конфигурация контроллера); • ожидание и прием команды (ожидание активности в сети, чтение команды, проверка адреса, и, если адрес совпадает с адресом устройства, выполнение команды, возвращение к ожиданию команды) ; • выполнение команды. Распишем это поподробнее. Иmщиализация. В этом блоке мы должны задать конфигурацию контрол­ лера, переход в режим низкого энергопотребления (SLEEP) и условия выхода из этого режима. В блоке инициализации мы прочитаем адрес, задаваемый адресным переключателем. Ожидание и прием команды. Этот блок программы является основным, поскольку в сети модуль играет пассивную роль, то есть ожидает прихода и выполняет команду, адресованную ему. При активации сети команда прочитывается. Если префикс совпадает с префик­ сом модуля, а адрес - с адресом устройства, команда выполня­ ется, в противном случае модуль переходит в режим ожида­ ния следующей сетевой команды. Адрес в слове команды сравнивается с ранее прочитанным (при инициализации) за­ данным адресом модуля .
Схема и программа релейного модуля 75 Выполнение команды запроса статуса. Этот блок программы отличается от предыдущего, начи­ ная с момента получения символа S вместо N или F. Про­ грамма должна определить состояние соответствующего вывода порта, переключить USART на передачу и передать статус в формате Rxx#xN, если соответствующий вывод порта - в состоянии «l», или Rxx#xF, если он в состоянии «О>>. После этого программа переходит к ожиданию следую­ щей команды. Блок инициализации контроллера. В первую очередь, определим, нужен ли нам режим «SLEEP», который переводит контроллер в состояние с уменьшенным энергопотреблением. Режим очень удобен и важен в тех случаях, когда контроллер используется в услови­ ях батарейного питания. Переход в режим «SLEEP» продле­ вает срок службы батарей или время работы без подзарядки аккумулятора. В нашем случае нет необходимости в поддер­ жании этого режима, поскольку модуль получает питание от блока питания. Часть конфигурирования необходимо выполнить при программировании контроллера. Это относится к слову кон­ фигурации по адресу 2007h. Здесь h после цифр означает НЕХ, hexadecimal (шестнадцатеричное число). В слове кон­ фигурации устанавливаются (или не устанавливаются) биты защиты, выбирается режим работы тактового генератора и некоторые параметры, относящиеся к режиму питания конт­ роллера. Вот первый вариант слова конфигурации для тактовой частоты 16-20 МГц: • Бит 13 устанавливаем в « 1» - выключаем защиту кода. • Бит 8 устанавливаем в «l» - выключаем защиту EEPROM. • Бит 7 устанавливаем в «О» - вывод RB4 работает как цифровой канал ввода-вывода. • Бит 6 устанавливаем в «О» - запрещаем сброс по сниже­ нию напряжения питания. • Бит 5 устанавливаем в «О» - вывод RB5 работает как цифровой канал ввода-вывода.
76 Глава • 1 Базовая версия • Бит 4 устанавливаем в «О» - режим HS генератора, кварц к выводам RA6 и RA7. • Бит 3 устанавливаем в «О» - выключаем режим включе­ ния по таймеру. • Бит 2 устанавливаем в «О» - выключаем режим работы сторожевого таймера. • Бит 1 устанавливаем в « 1 » - режим HS генератора, кварц к выводам RA6 и RA7. • Бит О устанавливаем в «О» - режим HS генератора, кварц к выводам RA6 и RA7. Слово конфигурации будет выглядеть так - 3FOAh. Для работы внутреннего тактового генератора следует использовать кварцевый резонатор с параллельным резонан­ сом на 16-20 МГц (рис. 1.36). OSC1 С1 0ХТАL Sleep :;:.o .- - Fosc С2 PIC 16F627д/628А/648А Note 1: А series resistor may Ье required for АТ strip cut crystals. 2: SееТаЫе 14-1andTaЫe14-2forrecomendedvaluesof С1 andC2 · Рис. 1.36. Типовая схема включения кварцевого резонатора для PIC16F628A Для частоты 16 МГц рекомендованные значения 10-22 пФ конденсаторов Cl и С2. Давайте подумаем, а не использовать ли встроенный в кон­ троллер генератор. Будем ли мы выполнять какие-либо опе­ - рации, требующие стабильной тактовой частоты? На стабиль­ ность частоты внутреннего генератора, в первую очередь, влияет температура и напряжение питания. Будут ли они
Схема и программа реnейноrо модуля 77 значительно меняться? Если мы не планируем использовать модуль в уличном исполнении, температура меняется мало. Если же после входного напряжения 12 В мы поставим стаби­ лизатор на 5 В, питающее напряжение будет изменяться еще меньше. В данный момент я больше склонен отказаться от кварцевого резонатора и использовать внутренний тактовый генератор . В этом случае есть два варианта на выбор. Для использова­ ния режима ER (3,6 МГц) к выводу RA7 микросхемы подклю­ чается резистор (не более 40 кОм). Вывод RАб может исполь­ зоваться для ввода-вывода. Второй вариант слова конфигурации: • Биты 13-10 устанавливаем в «l» - выклю ~ аем защиту кода. • Бит 8 устанавливаем в «1» - выключаем защиту EEPROM. • Бит 7 устанавливаем в «О» - вывод RB4 работает как цифровой канал ввода-вывода. • Бит 6 устанавливаем в «О» - запрещаем сброс по сниже­ нию напряжения питания. • Бит 5 устанавливаем в «О» - вывод RB5 работает как цифровой канал ввода-вывода. • Бит 4 устанавливаем в « 1" - режим ER, резистор 40 кОм подключается к RA7. • Бит 3 устанавливаем в «О» - выключаем режим включе­ ния по таймеру. • Бит 2 устанавливаем в «О» - выключаем режим работы сторожевого таймера. • Бит 1 устанавливаем в « 1" - режим ER генератора, ре­ зистор подключается к RA7. • Бит О устанавливаем в «О» - режим ER генератора, ре­ зистор подключается к RA7. Слово конфигурации будет выглядеть так - 3F1Ah. Еще более удобный вариант - использование внутреннего генератора без внешних элементов INTRC (4 МГц). Слово конфигурации в этом случае - 3F18h.
78 Глава • 1 Базовая версия Здесь я хотел бы сделать замечание, или признание - как вам угодно. Я впервые буду использовать контроллер PIC16F628A и пользоваться средой программирования контроллера MPLAB . Может возникнуть закономерный вопрос - а чему я могу на­ учить кого-то, если сам впервые это делаю? Если вас смуща­ ет данный аспект. можете обратиться к многочисленной ли­ тературе по программированию контроллеров, пропустив дальнейшее, что и решит проблему. Но мне кажется, что, имея большой опыт работы, основательно забываешь труд­ ности, с которыми столкнулся в начале. А если сам только начинаешь работать, эти трудности налицо. В блоке инициализации контроллера необходимо, в пер­ вую очередь, установить конфигурацию портов А и В. Нам потребуется установить биты порта А 0-6 на вывод, бит 7 - на ввод (к выводу RA7 порта подключается резистор в режиме ER) или все выводы порта А - на вывод для режима генератора INTRC. Для Этого в регистр TRISA необходимо записать "1 » для входных выводов и «О» для выходных. Ниже приведен при­ мер инициализации для порта А, взятый из руководства: CLRF PORTA ;Initialize PORTA Ьу setting output data latches ; (инициализация установкой защелок данных) MOVI.W Ох07 ;ТUrn comparators off and еnаЫе pins for I/O functions MOVWF CMCON ; (выключение компараторов для I/O функций) BCF STAТUS, RPl BSF STAТUS, RPO ;Select Bankl (выбор банка 1) MOVLW Ох80 ;Value used to initialize data direction MOVWF ТRISA ;Set RA<4:0> as outputs TRISA<5> always read as '1'. ;TRISA<7:6> depend on oscillator mode ; (в данном случае все на вывод , 7 ввод) Здесь Ох07 означает, что число 7 - шестнадцатеричное. Инициализация порта В связана, прежде всего, с необходи­ мосrью использования USART. Необходимо установить RВО на
Схема и программа реленноrо модуля 79 вывод и записать в него «О» (при передаче записывается «l»). Затем: • RВI устанавливается на ввод, а RВ2 - на вывод; • RВ3 установим на вывод (для управления микросхемой МАХ1483); • RВ4-RB7 устанавливаем на ввод для организации адрес­ ного селектора. CLRF PORTB latches ;Initialize PORTB Ьу setting output data ;(инициализация установкой защелок данных) MOVLW OxF2 ;Value used to initialize data direction MOVWF TRISB Запишем необходимые данные в регистр управления при­ емника USART - RGSTA (адрес 18h): • Бит 7- «1» - модуль включен; • Бит6-«О» - 8-битный прием; • Бит 5 - не имеет значения; • Бит 4- «l» - прием разрешен; • Бит 3 - не имеет значения; • Бит 2 - только на чтение; • Бит 1 - только на чтение; • Бит О - только на чтение. Операции записи побитовые: BSF RCSTA, SPEN ВСF RCSТA, RX9 BSF RCSTA, CREN Аналогично запишем данные в регистр передатчика USART - TXSTA (адрес 98h}: • Бит 7 - не имеет значения; • Бит 6 - «0 » - 8-битная передача; • Бит 5 - «l » - разрешение передачи; • Бит4- «О» - асинхронный режим работы; • Бит 3 - не используется;
80 Глава • 1 Базовая версия • Бит 2 - « 1» - высокоскоростной режим; • Бит 1 - только чтение; • Бит О - проверку четности мы не используем. BCF TXSTA, ТХ9 ВСF TXSTA, SYNC BSF TXSTA, BRGH BSF TXSTA, TXEN (эта команда появится , когда мы начнем передачу ста'!)'са) . Кроме того, необходимо задать скорость работы в регистре SPBRG. Для первого варианта тактового генератора (SYNC =О, BRGH = 1, 16 МГц): MOVLW Ох67 MOVWF SPBRG Для второго варианта тактового генератора (SYNC =О, BRGH = 1, 3,6 МГц): MOVLW Охlб MOVWF SPBRG В результате блок инициализации (для второго варианта) будет выглядеть следующим образом: list p=16f628a #include p16f628a.inc ;Инициализация модУля ВСF STAТUS, RPl ; Выбор банка О ВСF STAТUS, RPO Если посмотреть раздел организации памяти контроллера, видно, что часть регистров, которые мы используем, находит­ ся в банке «О>>, а часть в банке «1 ». Если забыть переключиться, команды могут не выполняться , а среда программирования МРIАВ напомнит, выводя в окне Output на странице МРLАВ SIM напоминания при трансляции программы. Это были пер­ вые грабли, на которые я часто наступал. CLRF PORTA ; Настройка порта А. MOVLW Ох07
Схема и программа релейного модуля 81 MOVWF СМСОN BCF STAТUS, RPl Выбор банка 1. BSF STAТUS, RPO MOVLW Ох80 MOVWF TRISA MOVLW ОхFб Настройка порта в. MOVWF TRISB ВСF STAТUS, RPl Выбор банка О. ВСF STAТUS, RPO CLRF PORTB ;Настройка приемопередатчика USART. BSF RCSTA, SPEN ВСF RCSTA, RX9 BSF RCSTA, CREN BCF STAТUS, RP l BSF STAТUS, RPO ВСF TXSTA, ТХ9 ВСF ТХSТА, SYNC BSF ТХSТА, BRGH MOVLW Охlб MOVWF SPBRG BCF STAТUS, RPl BCF STAТUS, RPO CLRW ADDWF PORTB, О ANDLW OxFO MOVWF Ох20 SWAPF Ох20, 1 CALL adrsim ; Настройка приемника. Выбор банка 1. Настройка передатчика . Выбор банка О. Считывание собственного адреса. Прочитаем порт В. Нам не нужны младшие биты. Сохраним адре с в регистре 20h . Нам не нужна работа с младшими битами. Преобразуем его в символьный вид. Чтобы сравнить адрес , задаваемый переключателем, с ад­ ресом в слове команды, нужно преобразовать их к единому
82 Глава • 1 Базовая версия виду. Здесь существует несколько возможностей. Я использую одну из них, вы можете поступить иначе. прочитаем из EEPROM в ЗОh - состояние реле. Необязательно хранить текущее состояние реле в энерго­ независимой памяти. Но это может быть полезно и, кроме того, дает возможность разобраться с механизмом записи в энергонезависимую память. Можно, например, изменить ме­ тод задания адреса. Использовать вместо переключателя в адресном селекторе программную установку адреса - запись адреса в энергонезависимую память контроллера. Так, в част­ ности, устроены некоторые промышленные модули. В этом случае перед первым использованием модуля его переводят в режим установки адреса и программно устанавливают этот адрес. Механизм записи состояния реле и адреса одинаков. BSF STAТUS, RPO ; Выбор банка 1. ВСF STAТUS, RPl MOVLW ОхОО MOVWF EEADR Адрес считываемого регистра. BSF EECONl, RD ; Чтение. MOVF EEDATA,W ; w = EEDATA. ВСF STAТUS, RPl ; Выбор банка О. ВСF STAТUS, RPO MOVWF ОхЗО СОМF ОхЗО, 1 Будем хранить в EEPROM в инверсном виде . CLRW ADJ:МF ОхЗО,О MOVWF PORTA А в регистре ЗОh в прямом. Перепишем ЗОh в порт. Сохранение состояния реле в инверсном виде связано с тем, что в EEPROM по умолчанию записаны единицы. При инициализации прочтение состояния приведет к включению всех реле. Чтобы избежать этого, будем инвертировать про­ читанное. В строке «CALL adrsim» мы вызываем подпрограмму, ко­ торая переводит адреса в символы: Это опять-таки не обязательно делать в данном программ­ ном блоке. Но оставлять в блоке инициализации длинный «ХВОСТ» мне не захотелось. Перевод адреса в символьное
Схема н программа релейного модул11 83 представление можно сделать различными способами, я выб· рал самый очевидный. Поскольку мы используем символьный обмен, я выпишу шестнадцатеричные коды некоторых символов ASCII: «О» -30h; "1" - 3lh; «2» -32h; «3» - 33h; «4» -34h; «5» - 35h ит.д. «R» - 52h;«$» - 24h;...#" - 23h;«N» - 4Eh;«F» - 46h;«S» - 53h Подпрограмма перевода адреса в символ (храним по адресам 21h, 22h). adrsim: CLRW Если адрес 1 запишем символы •о• "1" (30h и Зlh). ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW Ох31 MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Oxl BTFSC STAТUS, Z REТURN CLm>J Если адрес 2 запишем символы •о• •2• (ЗОh и 32h). ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW Ох32 MOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Ох2 BTFSC STAТUS, Z REТURN CLRW Если адрес 3 запишем символы •о• ·з·. ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW ОхЗЗ
84 Глава • 1 Базовая версия MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW ОхЗ BTFSC STAТUS, Z REТURN CLRW Если адрес 4 запишем символы "0" "4" . ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW Ох34 МOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Ох4 BTFSS STAТUS, Z RE'IURN CLRW Если адрес 5 запишем символы •о• "5". ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох35 MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Ох5 ВТFSS STAТUS , Z REТURN CLRW Если адрес 6 запишем символы •о• "6". ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW ОхЗб МOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Охб BTFSS STAТUS, Z REТURN
Схема и программа релейного модуля 85 CLRW Если адрес 7 запишем символы •о• "7" . ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох37 MOVWF Ох22 MOVF Ох20, О ВСF STATUS , Z XORLW Ох7 BTFSS STAТUS, Z REТURN CLRW Если адрес 8 запишем символы •о• "8". ADDLW ОхЗО МOVWF Ох21 CLRW ADDLW Ох38 МOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW Ох8 BTFSS STAТUS, Z REТURN CLRW Если адрес 9 запишем символы •о• "9" . ADDLW ОхЗО MOVWF Ох21 CLRW ADDLW Ох39 MOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW Ох9 BTFSS STAТUS, Z REТURN CLRW Если адрес 10 (Ah) запишем символы "1" •о• . ADDLW Ох31 МOVWF Ох21 CLRW ADDLW ОхЗО MOVWF Ох22 MOVF Ох20, О
86 Г11ава • 1 Базовая версия ВСF STAТUS, Z XORLW ОхА BTFSS STAТUS, Z REТURN CLRW Если адрес 11 (Bh) запишем символы "1" "1". ADDLW Ох31 MOVWF Ох21 CLRW ADDLW ОхЗl MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW ОХВ ВТFSS STAТUS, Z REТURN CLRW Если адрес 12 (Ch) запишем символы "1" "2". ADDLW Ох31 MOVWF Ох21 CLRW ADDLW Ох32 МOVWF Ох22 MOvF Ох20, О ВСF STAТUS, Z ХОЩ,W ОхС BTFSS STAТUS, Z REТURN CLRW Если адрес 13 (Dh) запишем символы "1 " • з•. ADDLW ОхЗl MOVWF Ох21 CLRW ADDLW ОхЗЗ MOVWF Ох22 MOVF Ох20, О ВСF STAТUS, Z XORLW OxD BTFSS STATUS, Z REТURN CLRW Если адрес 14 (Eh) запишем символы "1" "4". ADDLW ОхЗl
Схема и nроrрамма релейноrо модуля 87 MOVWF Ох21 CLRW ADDLW Ох34 MOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW ОхЕ BTFSS STATUS, Z REТURN CLRW Если адрес 15 (Fh} запишем символы "1" "5". ADDLW Ох31 MOVWF Ох21 CLRW ADDLW Ох35 МOVWF Ох22 MOVF Ох20, О BCF STAТUS, Z XORLW OxF BTFSS STAТUS, Z REТURN Программный блок ожидания активности в сети. 1. Проверим бит RCIF в регистре PIRI. 2. Если бит установлен, пропустим следующую команду. 3. Вызовем подпрограмму обработки команды. · 4. Вернемся к началу. Вот и вся программа: start: BTFSS PIRl , RCIF команды. GОТО start Ждем прихода первого символа CALL cmnd С приходом первого символа начинаем обработку. GОТО start Следующая трудность спрятана как раз в этом месте, хотя я умудрился наступить на эти грабли при обработке «inl». Разумная, как мне казалось, конструкция: start: BTFSS PIRl , RCIF ; Ждем прихода первого символа команды. GОТО sta rt
88 Глава • 1 Базовая версия работать в режиме отладки МРIАВ не хотела. Я все перепро­ верил многократно. Все бьто правильно, но анимация про­ граммы безнадежно застревала, я решил, что программа не работает. Понять, в чем здесь дело, помогло обращение к сай­ ту Micгochip, где на форуме этот вопрос уже обсуждался . При­ чина столь не очевидного поведения программы очевидна (когда знаешь). Отладчик в цикле опроса ждет прохождения нескольких тысяч тактов внугреннего генератора, работаю­ щего на частоте в 4-20 МГц до заполнения регистра. которое происходит с частотой примерно 1О кГц. Вдобавок, настрой­ ки отладчика по умолчанию делают анимацию хорошо воспри­ нимаемой (одно или два перемещения в секунду), но дождать­ ся нескольких тысяч таких перемещений лично у меня ума не хватило. Обработку команды я опять оформил в виде подпрограммы. Обработка команды - проверка адреса, определение команды. cmnd: ВСF STATUS, Z MOVF RCREG, О XORLW Ох52 Проверим наш ли МОдУЛЬ R ( 52h) • BTF.SS STAТUS, Z; Если нет вернемся. REI'URN inl: BTFSS PIRl, RCIF ; Ждем прихода первого символа адреса. GОТО inl Если совпадает, продолжим. MOVF RCREG, О BCF STAТUS, Z XORWF Ох21, О BTFSS STATUS, Z REI'URN Первый символ адреса в регистре 21h. in2: BTFSS PIRl , RCIF ; Ждем прихода второго символа адреса. GОТО in2 Если совпадает, продолжим. МOVF RCREG, О ВСF STAТUS, Z XORWF Ох22, О Второй символ адреса в регистре 22h . BTFSS STATUS, Z REI'URN
Схема и программа релейного модуля 89 inЗ: BTFSS PIRl, RCIF ; Ждем прихода символа. GОТО inЗ ; Если следом символ команды, продолжим. MOVF RCREG, О ВСF STAТUS, Z XORLW Ох24 Символ команды "$" (24h). ВТFSС STATUS, Z CALL swtch REТURN Вызываем подпрограмму выполнения. Подпрограмма определения команды N (включить), F (выключить) ; или S (состояние). swtch: CLRW in4: BTFSS PIRl, RCIF GОТО in4 Ждем прихода символа. MOVF RCREG, О MOVWF Ох23 MOVLW ОхЗО SUBWF Ох23, О MOVWF Ох23 ; Прочитаем номер реле. Сохраним номер реле в регистре 2Зh. Запишем регистр ЗОh в аккумулятор. ; Переведем символ в номер. Сохраним номер реле в регистре 2Зh. in5: BTFSS PIRl, RCIF ; Ждем прихода символа. GОТО in5 MOVF RCREG, О ; Разберем N-включить, F-выключить, S- cтa-ryc. МOVWF Ох2 4 ВСF STATUS , Z XORLW Ох4Е Сохраним коман.цу в регистре 24h. Включение N (4Eh) . BTFSC STATUS, z; Если нет, то пропустим. CALL cmdset MOVF Ох24, О Перепишем из 24h в аккумулятор. ВСF STATUS, Z XORLW Ох46 Выключение F (46h). BTF SC STAТUS, Z; Если нет, то пропустим. CALL cmdreset МOVF Ох24, О Перепишем из 24h в аккумулятор. ВСF STATUS, Z XORLW Ох53 S (53h) запрос статуса. BTFSC STAТUS, Z; Если нет, то пропустим. CALL stat
90 Глава • 1 Базовая версия Сохраним состояние всех реле в энергонезависимой памяти. Перепишем регистр ЗОh состояния реле в EEPROM. CLRW МOVLW ОхОО Запишем Oh в аккумулятор. МOVWF EEADR Запишем адрес Oh в регистр адреса. ВСF STAТUS, RPl; Выбор банка О. ВСF STAТUS, RPO CLRW АDТМF ОхЗО,О СОМF ОхЗО,О BSF STAТUS, RPO ; ВСF STAТUS, RPl МOVWF EEDATA BSF STAТUS, RPO Запишем содержимое ЗОh в аккумулятор. Инвертируем перед сохранением. Выбор банка 1. ВСF STAТUS, RPl; Выбор банка 1. BSF EECONl, WREN ; Разрешить запись. BCF INТCON, GIE ; Запретить прерывания. MOVLW Ох55 МOVWF EECON2 .МOVLW ОхАА MOVWF EECON2 Записать 55h . Записать AAh . BSF EECONl, WR Установить флаг для начала запись. BSF INТCON, GIE ; Разрешить прерывания. ВСF EECONl, WREN ; Запретить запись. Запись 55h и AAh относятся к обязательным при работе с ЕЕРRОМ . ВСF STATUS , RPl ; Выбор банка О. ВСF STAТUS, RPO chkwr: BTFSS PIRl, EEIF Проверка завершения записи. GОТО chkwr CLRW ADDWF ОхЗО, О MOVWF PORTA ВСF PIRl, EEIF REГURN Перепишем ЗОh в порт. Сбросим фла г. В этом месте работы с отладчиком я вначале проверил выполнение двух команд подряд. Все работало. Затем я впи­ сал запись состояния реле в EEPROM с проверкой окончания
Схема и программа релейного модуля 91 записи. И, естественно, обнаружил, что вторая команда пере· стала выполняться. Но теперь я быстрее сообразил, что запись занимает время, в течение которого успевает пройти необра· ботанная часть команды. Я не стал «городить огород», вставив между двумя нужными командами третью, ненужную. Хочу еще заметить, что изготовитель микросхем советует осуще· ствить проверку записи в EEPROM, которая вставляется пос· ле проверки завершения записи. Я этого не сделал. Но после создания прототипа я могу переделать программу. удалив из слова команды символьное представление номера модуля и номера реле, могу сделать и программное задание адреса. То­ гда и добавлю проверку правильности записи в EEPROM. 1)Nr подпроrраммы •ыnопнен•• команд ; Подпрограмма включение реле по номеру. ; Запишем в регистр ЗОh (установить соответствующий номеру реле бит). andset: CLRW ADDWF Ох23, о ВСF STAТUS, z XORLW ОхО Реле О. BTFSC STAТUS, z BSF ОхЗО, О CLRW ADDWF Ох23, о ВСF STAТUS, z XORLW Oxl Реле 1. BTFSC STAТUS, z BSF ОхЗО, 1 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Ох2 Реле 2. BTFSC STAТUS, z BSF ОхЗО, 2 CLRW ADDWF Ох23, о BCF STAТUS, z XORLW ОхЗ Реле з. BTFSC STAТUS, Z
92 Глава• 1 Базовая версия BSF ОхЗО, З CLRW ADDWF Ох23, о ВСF STATUS, z XORLW Ох4 Реле 4. BTFSC STATUS, z BSF ОхЗО, 4 CLRW ADDWF Ох23, о BCF STAТUS, z XORLW Ох5 Реле 5. BTFSC STAТUS, z BSF ОхЗО, 5 CLRW ADDWF Ох23, о ВСF STAТUS, z XORLW Охб Реле 6. BTFSC STATUS, z BSF ОхЗО, 6 CLRW ADDWF Ох23, о BCF STATUS, z XORLW Ох7 Реле 7. BTFSC STAТUS, z BSF ОхЗО, 7 REТURN Подпрограмма выключения реле по номеру. Запишем в регистр ЗОh (сбросить соответствующий номеру реле бит) . cmdreset : CLRW ADDWF Ох23,О BCF STAТUS, Z XORLW ОхО Реле 0. BTFSC STAТUS, Z BCF ОхЗО, О CLRW ADDWF Ох23,О BCF STATUS, Z XORLW Oxl Реле 1. BTFSC STAТUS, Z ВСF ОхЗО, 1
Схема и программа релейного модуля 93 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Ох2 Реле 2. BTFSC STAТUS, z BCF ОхЗО, 2 CLRW ADDWF Ох23,О BCF STAТUS, Z XORLW ОхЗ Реле З. BTFSC STAТUS, z ВСF ОхЗО, З CLRW ADDWF Ох23,0 ВСF STAТUS, Z XORLW Ох4 Реле 4. BTFSC STAТUS, z BCF ОхЗО, 4 CLRW ADDWF Ох23,О ВСF STAТUS, Z XORLW Ох5 Реле 5. BTFSC STAТUS, z ВСF ОхЗО, 5 CLRW ADDWF Ох23, О ВСF STAТUS, Z XORLW Охб Реле 6. BTFSC STAТUS, z ВСF ОхЗО, 6 CLRW ADDWF Ох23,О ВСF STAТUS, Z XORLW Ох7 Реле 7. BTFSC STATUS, z ВСF ОхЗО, 7 REI'URN Подпрограмма передачи статуса реле stat: ВСF STAТUS. RPl ВСF STAТUS, RPO ; Выбор банка О. CLRW ; Проверим реле О.
94 Глава • 1 Базовая версия ADDWF Ох23, о BCF STAТUS, z XORLW ОхО Реле О. BTFSC STAТUS, z CALL relO CLRW Проверим реле 1. ADDWF Ох23, о ВСF STATUS, z XORLW Oxl Реле 1. BTFSC STAТUS, z CALL rell CLRW Проверим реле 2. ADDWF Ох23, о BCF STAТUS, z XORLW Ох2 Реле 2. BTFSC STATUS, z CALL rel2 CLRW Проверим реле 3. ADDWF Ох23, о BCF STAТUS, z XORLW ОхЗ Реле З. BTFSC STAТUS, z CALL relЗ CLRW Проверим реле 4. ADDWF Ох23, о ВСF STAТUS, z XORLW Ох4 Реле 4. BTFSC STAТUS, z CALL rel4 CLRW Проверим реле 5 . ADDWF Ох23, о BCF STATUS, z XORLW Ох5 Реле 5. BTFSC STAТUS, z CALL rel5 CLRW Проверим реле б . ADDWF Ох23, о ВСF STAТUS, z XORLW Охб Реле 6. BTFSC STATUS, z CALL relб CLRW Проверим реле 7 . ADDWF Ох23, о
Схема и программа релейного модуля 95 ВСF STAТUS, Z XORLW Ох7 Реле 7. BTFSC STAТUS, Z CALL rel7 теперь это все отправим в передатчик BSF PORTB, О Переключим драйвер RS485 на передачу. ВСF STATUS, RPl Выбор банка 1. BSF STATUS, RPO BSF TXSTA, TXEN ВСF STAТUS, RPl ВСF STATUS, RPO MOVLW Ох52 MOVWF TXREG ВСF STATUS, RPl BSF STAТUS, RPO Разрешаем передачу. Выбор банка О. Отправим символ модуля. ; Выбор банка 1 . outdatO: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdatO ВСF STAТUS, RPl Выбор банка О . ВСF STAТUS, RIJQ CLRW ADiklF Ох21,О MOVWF ТXREG ВСF STAТUS, RPl ВSF STATUS , RPO outdatl : BTFSS TXSTA , GОТО outdatl · ВСF STAТUS, RPl ВСF STAТUS, RPO CLRW ADDWF Ох22, О МOVWF ТXREG ВСF STAТUS, RPl BSF STAТUS , RPO Отправим первый символ адРеса. : Выбор банка 1 . TXIF ; Ждем отправки символа. ; Выбор банка О. Отправим второй символ адРеса . Выбор банка 1 . outdat2: BTFSS TXSTA, TXIF GОТО outdat2 ; Ждем отправки символа . ВС F STATUS, RPl ВСF STAТUS , RPO MOVLW Ох23 ; Выбор банка О.
96 Глава • 1 Базовая версия МOVWF ТXREG ВСF STAТUS, RPl БSF STAТUS, RPO Отправим символ статуса. ; Выбор банка 1. outdatЗ: BTFSS TXSTA, ТXIF GОТО outdatЗ ; Ждем отправки символа. ВСF STAТUS, RPl ВСF STATUS, RPO CLRW ADDWF Ох23,О ADDLW ОхЗО MOVWF TXREG ВСF STATUS, RPl BSF STAТUS, RPO ; Выбор банка О. Отправим символ номера реле. ; Выбор банка 1. outdat4: BTFSS TXSTA, TXIF ; Ждем отправки символа. GОТО outdat4 BCF STAТUS, RP1 ; Выбор банка О. ВСF STAТUS, RPO CLRW ADDWF Ох25, О МOVWF ТXREG Отправим символ статуса реле. ВСF STAТUS, RPl ; Быбор банка 1. BSF STAТUS , RPO outdatS: BTFSS TXSTA, GОТО outdatS ВСF TXSTA, TXEN ВСF STATUS, RP1 ВСF STAТUS, RPO ВСF РОRТБ, О REroRN RCIF ; Ждем отправки символа. Запрещаем передачу. Выбор банка О. Переключим драйвер RS485 на прием. Подпрограмма обработки статуса реле. relO: BTFSC ОхЗО, о CALL sostn BTFSS ОхЗО, о CALL sostf REroRN rell: BTFSC ОхЗО, 1 CALL sostn BTFSS ОхЗО, 1 CALL sostf
Схема н программа релейного модуля 97 REТURN rel2: BTFSC ОхЗО, 2 CALL sostn BTFSS ОхЗО, 2 CALL sostf REТURN relЗ: BTFSC ОхЗО, 3 CALL sostn BTFSS ОхЗО, 3 CALL sostf REТURN rel4: BTFSC ОхЗО, 4 CALL sostn BTFSS ОхЗО, 4 CALL sostf REТURN rel5: BTFSC ОхЗО, 5 CALL sostn BTFSS ОхЗО, 5 CALL sostf REТURN relб: BTFSC ОхЗО, 6 CALL sostn BTFSS ОхЗО, 6 CALL sostf REТURN rel7: BTFSC ОхЗО, 7 CALL sostn BТFSS ОхЗО, 7 CALL sostf REТURN Подпрограммы образования символов состояний. sostn: sostf: MOVLW Ох4Е MOVWF Ох25 REТURN MOVLW Ох46 MOVWF Ох25 REТURN ; Состояние - включено. Состояние - выключено. Если теперь соединить все представленные части про­ граммы, программирование контроллера завершится.
98 Глава • 1 Базовая версия Вставки и примечания, которые я привел выше, 11uяви­ лись позже, при наладке модуля, но я решил привести их «досрочно». Очень часто у меня не хватает терпения дочи­ тать что-то до конца, мне не терпится начать работу. Я пред­ ставил, что подобной чертой характера могу отличаться не только я, и привел все примечания на случай, если и вы уже начали работу за компьютером. Мне очень не хотелось, что­ бы вы полностью разочаровались во всем преждевременно. Мы написали программу для контроллера. Постараемся ее проверить и отладить в программе МРIАВ. Введение в ра6оту с MPLAB После загрузки программы появляется рабочее окно. Вид программы обычен для Windows и, думаю, не требует особых пояснений. Мы создадим новый проект в основном меню Project • New (Проект• Новый). Задаем название relay проекту в пап­ ке Relay, которую я советую создать в основном разделе диска в папке МРIАВ. Неоднократно я сталкивался с проблемой, которая не всегда очевидна. Многие программы, да это и удобно, предлагают хранить проект в папке Мои документы. Проблемы не возникает, если вы пользуетесь англоязычной версией Windows или русскоязычной версией программы. Но многие специализированные англоязычные программы начинают вытворять чудеса, если вы работаете в русскоязыч­ ной версии операционной системы. Впервые я столкнулся с этим, когда одна из сред программирования при компиляции программы стала выдавать ошибку в строке -1 . Что она име­ ла в виду под строкой с отрицательным номером, я не знаю. Но отыскать ошибку в правильно написанной программе ока­ залось не так просто. Ошибка крылась в том, что программа, предлагая сохранить проект в папке Мои документы, при компиляции эту папку распознать не могла. После создания нового проекта появляется окно навига­ тор проекта. Теперь выберем микросхему контроллера в раз­ деле основного меню Configure • Select Device (Конфигура­ ция• Выбор устройства). Выбираем PIC16F628A (рис. 1.37).
Введение· в работу с MPLAB 99 Рис. 1.37 . Рабочее окно программы MPLAB Завершив выбор, следует создать файл основной · програм­ мы. Выбираем File • New (Файл• Новый). Появляется окно редактора. Сохраним файл под именем relay.asm (File • Save As (Файл• Сохранить как".)). Добавим этот файл в проект. Для этого щелкнем правой кнопкой мыши раздел Source Files (Исходные файлы) в окне навигатора. В открывшемся меню выберем Add Files (Добавить файлы) и укажем свой файл. Для начала перенесем в окно редактора небольшой фраг­ мент программы: инициализацию, ожидание команды и две подпрограммы: CALL adrsim и CALL cmnd. Последние подпрог­ раммы - в усеченном виде. В данный момент будем использо­ вать адрес модуля «01». Не забудьте поставить · ЕND в конце программы! adrsirn: CLRW Зlh). ADDLW ОхЗО MOVWF Ох21 CLRW Если адрес 1 запишем символы •о• "1" (30h и ADDLW Ох31 MOVWF Ох22 MOVF Ох20, О
1 00 Глава • 1 Базово11 версия BCF STATUS, Z XORLW Oxl BTFSC STAТUS, Z REТ!.JRN cmnd: BCF STAТUS, Z MOVF RCREG, О XORLW Ох52 Проверим наш ли МОдУЛЬ R (52h) . BTFSS STAТUS, Z; Если нет, вернемся. RE'IURN inl: BTFSS PIRl, RCIF ; Ждем прихода первого символа адреса. 2lh. GОТО inl ; Если совпадает, продолжим. MOVF RCREG, О BCF STAТUS, Z XORWF Ох21, О BTFSS STAТUS, Z RE'IURN Первый символ адреса в регистре in2: BTFSS PIRl, RCIF ; Ждем прихода второго символа адреса. 22h. GОТО in2 Если совпадает, продолжим. MOVF RCREG, О ВСF STATUS, Z XORWF Ох22, О Второй символ адреса в регистре BTFSS STAТUS, Z RE'IURN Для отладки откроем окно наблюдения View • Watch (Вид• Наблюдение), в котором выберем регистры STATUS, WREG, PIRl, EEDATA, RCREG, 20h, 21h, 22h, ЗОh. Необходимые регистры открываются кнопкой с обозначением стрелки вниз, правее располагается названия регистра рядом с кноп· кой ADD SFR (Добавить наблюдаемые). Ее следует щелкнуть после выбора регистра (рис. 1. 38). Регистры без имени (20h, 21h и т. д.) мы добавляем, про­ сто вводя адрес в колонку Address (Адрес) на новой строке. Добавим и EEPROM через выбор View • EEPROM (Вид• EEPROM). Установим в :качестве текущего симулятора про­ граммный (Debugger • Select Tool • МРLАВ SIM (Отладчик• Выбор средства• МРl.АВ SIM)). Создадим два файла input.txt
Введение в роботу с MPLAB 1 О 1 Рис. 1.38. Окно наблюдения Watch и output.txt (File • New (Файл• Новый)) . В файле input.txt, ко­ торый открывается в окне редактора, запишем слово команды ROl $ в виде строки в кавычках. Сохраним этот файл (File • Save (Файл• Сохранить)) . Теперь сделаем установки отладчика (Debugger • Settings••• (Отладчик• Установки ...)): зададим ча­ стоту процессора 4 МГц, на вкладке Uart1 10установим опцию ЕnаЫе Uartl 10, укажем входной файл input.txt (browse) и вы­ ходн~й output.txt. Подтвердим замену последнего файла и уста­ новим опцию Rewind lnput. Изменим значение на вкладке Animation/Realtime на 1 мс. Щелкнем Применить и ОК Вклю­ чим в окна View • Output (Вид• Вывод) . Создадим новый сценарий, который позволит ввести адрес , имитируя пере­ ключатель. Для этого выберем в основном меню Debugger • Stimulus Controller • New Scenario (Отладчик• Управление симуляцией• Новый сценарий). Выберем вывод RВ4 в окне Pin/SFR (Вывод/Наблюдаемые). В окне Action (Действие) выберем Set High (Установить в высокое состояние). Щелк­ нем кнопку со стрелкой вправо в колонке Fire (Запустить).
102 Глава• 1 Базова11 версн11 Сохраним сценарий под именем relay и свернем его (не закро­ ем, а свернем!). Теперь откроем оюю (Configure • Configuration Bits (Конфигурация• Биты конфигурации)), где установим биты, записываемые по адресу 2007h. Должно получиться слово 3F1Ah. Закроем это окно (рис. 1.39). Рис. 1.39. Установки наблюдения и отладки В завершение этих процедур упорядочим окна (Windows• Tde Horizontally (Окна• Расположить горизонтально)), сохра­ ним все (File • Save All (Файл • Сохранить все)) и добавим в проект файл todo.txt, который предварительно создадим и по­ местим в раздел Other Files (Другие файлы) менеджера про­ екта. В файле todo.txt будем вести план работы. Теперь откомпилируем проект Project • Build All (Про­ ект • Компоновать все). Сохраним и вид проекта File • Save
Введение в роботу с MPLAB 1 03 Workspace (Файл• Сохранить рабочую область). Мы готовь~ к отладке программы. После выхода из программы MPLAB и подтверждения сохра­ нения вида проекта, новой загрузки программы и открытия проекта (Project • Open (Проект • Открыть)) мне приходит­ ся обнулять адрес Oh в EEPROM, щелкать Fire (Запустить) в Scenario (Сценарий), и вводить адреса 20h, 21h и т.д. в окне Watch (Наблюдение), которые, как пишет программа, Not Found (Не найдены). Я не уверен, что дернул за все веревоч­ ки, но... пока ничего лучшего не получилось. Если вы правильно перенесли программу, то, щелкнув на инструментальной панели кнопку запуска программы, вы увидите анимацию, а в регистре RCREG {приемный регистр USART) появятся шестнадцатеричные коды символов из строки файла input.txt. Можно вписать в ячейку по адресу Oh EEPROM значение 1h и увидеть, как оно переписывается в регистр 30h. Есть еще несколько полезных возможностей. Одна из них - проверить работу с определенного места . Для этого остано­ вим анимацию (кнопкой паузы на инструментальной панели), установим курсор в нужной строке и щелкнем правой кнопкой мыши. Выберем в раскрывающемся меню Set РС at Cursor (Установить счетчик команд к курсору). Теперь, щелкая зна­ чок Step lnto (Шаг внутрь) на инструментальной панели, мы можем отследить все изменения. В окончательном виде я работаю в среде, которая показа­ на на рис. 1.40 . Кроме написания программы на ассемблере среда МРLАВ поддерживает написание программ на языке С. Существуют компиляторы разных производителей. Я использую демонст­ рационную версию кросскомпилятора Hi-Tech. Посмотрим, не будет ли проще написать программу на языке С?
104 Гnава • 1 Базовая версия ~ ' . t .:." :l'.:o . . ! /~-.ч.-.11, .oXJ!.:"·- ._ . _ _ -.: ~~ ---:• ••• •~t-' ../ _:_... fr • - """"""""""""""""··- - """"""""""""""""··- - """"""""""""""""··-· - """"""""""""""""··-· - """"""""""""""""···· ooto rrпrrrrrr,,.rrrrrrrrrrrr""rrrr •.... - """"""""""""""""··-· ',_ ....,._ _ : ........... : oьttct .... ; u.., ... .. ·~~ .C!N'... Рис. 1.40. Окончательный вид окна проекта Репейный моду11ь, версия nроrраммы на языке С Выбор языка программирования происходит при задании в Project • Select Language Toolsuite (Проект• Выбор языко­ вых средств) - рис. 1.41. Конечно, компилятор Hi-Tech должен быть установлен согласно инструкции. Создадим файл заголовка и основной файл. Добавим в фай­ лы заголовка нужный нам контроллер . Остальная часть рабо­ ты мало, чем отличается от работы на ассемблере. В этой вер­ сии программы я не сохраняю состояние реле в EEPROM. Фаiiп 3аnшовка #define MODULNAМESIM "R" #define CМDSIM "$" #define Ьitset (var ,Ьitno) ( (var) 1= 1 « (Ьitno))
Релейный модуль, версия программы но языке С 1 05 Рис. 1.41 . Установка языка программирования С #define bitclr(var,bitno) ((var) &= - (1 << (bitno))) void putch(unsigned char); unsigned char getch(void); int init_comms (); int sim_nurn_adr(); int cmd(); int rel_on (int nurn) ; int rel _off(int nurn) ; int rel_stat(int nurn); Основноiiфаiiп #include <piclбf62xa.h> #include <Stdio.h> #include •re ley-,c.h" unsigned char input; регистра. unsigned char МOD_SIМl; unsigned char MOD_SIМ2; unsigned cha r REL_SIM; / / Считываем содержимое приемного //Первый символ адреса мо,цуля. / / Второй символ адреса мо,цуля. / / символ реле.
106 Глава • 1 Базовая версия unsigned char СОММАND; int МOD_ADDR; 11 Символ команды. //Заданный адрес модуля, как число. int siml_num = О; int sim2_num = О; int sim_end_num int МOD_.NUМ; О; / / Полученный адрес модуля, как число. 11 Номер реле. int REL_NUМ; int RELSTAT = 0; //Статус реле (позиционно): 1 - вкл, О - выr::~. 11 Получение байта. unsigned char getch() { while( !RCIF) continue; return RCREG; 11 Устанавливается, когда регистр не пуст. 11 Вывод одного байта. void putch(unsigned char Ьуtе) { PORTB = 1; / / Переключим дРайвер RS485 на передачу. TXEN = .1; //Разрешаем передачу. while ( ! ТXIF) / / Устанавливается, когда регистр пуст. continue; TXREG = byte; //Преобразуем символьный адРес в число. int sim_num_adr () { sim_end_num = О; siml_num = getch(); //Чтение первого символа номера. МOD_SIMl = siml_num; / / Сохраним первый символ . sim2_num = getch(); //Чтение второго символа номера . МOD_SIM2 = sim2_num; / / Сохраним второй символ. siml_num = siml_num - ОхЗО; //От первого символа к числу. sim2 num = sim2 num - ОхЗО; / / От второго символа к числу. sim_end_num = siml_num• ~ хОА + sim2_num; //Объединим в одно число. return sim_end_num;
Релейный модуль, версия проrроммы но языке С 107 / / Получение и выполнение команды. int crnd() { input = getch(); REL_NUМ = input; //Номер реле в символьном виде. REL_SIM = REL_NUМ; REL_NUМ = REL_NUМ - ОхЗО; switch (СОММАND = getch()) ( //Номер реле в числовом виде. / / Прочитаем команщ. case "N": rel_on(REL_NUМ); // Если команда включить . break; case "F": rel_off(REL_NUМ); //Если команда выключить. break; case ·s ·: rel_stat(REL_NUМ);// Если команда передать состояние. break; } //Выполнение команды включения заданного реле. int rel_on(int num) { Ьitset (RELSTAT, REL_NUМ); // В RELSTAT побитовое состояние реле. PORTA = RELSTAT; } //Установив бит, переписываем в порт А. //Выполнение команды выключения заданного реле. int rel_off (int num) { А. } Ьitclr (RELSTAT. REL_NUМ); PORTA = RELSTAT; //Сбросив бит, переписываем в порт //Выполнение команды передачи состояния заданного реле . i nt rel_stat(int num) ( putch("R"); putch(MOD_SIMl); putch(МOD_SIМ2); putch( "#"); putch(REL_SIM) ; //Отправляем символ R. //Первый символ номера МОдУЛЯ. 11 Второй символ номера МОдУЛЯ. 11 Символ статуса. //Символ номера реле.
108 Глава • 1 Базовая версия if ((RELSTAT»REL_NUМ) &OxOl) putch ("N") ; / / Установлен ли бит? if { ! ( (RELSTAT»REL_NUМ} &O:x;Ol} } putch{"F") ; / / Сброшен ли бит? putch{OxOA}; /1 толыtо для вывода в файл!!!!!! int init_coпuns (} / / Инициализация модуля. PORTA = ОхО; CMCON = Ох7; TRISA = Ох80; TRISB = ОхFб; RCSTA = Ох90; ТХSТА = Ох4; SPBRG = Охlб; 11 Настройка портов А и В. / / Настройка приемника. 11 Настройка передатчика. // Настройка режима приема-передачи. INТCON=O; / / Запретить прерывания. PORTB = О; 11 Выключим передатчик драйвера RS485. } void main (void} { init_coпщ:; (); //Инициализация модуля. //Прочитаем и преобразуем номер модуля. MOD_ADDR = PORTB; / / Номер модуля в старших битах. MOD_ADDR=MOD_ADDR>>4; // Сдвинем на четыре бита. 11 Начинаем работать . start: input = getch (}; while(input != MODULNAМESIM} input = getch();// Ждем, если не нас. MOD_NUМ = sim_num_adr ( ) ; if (MOD_NUМ == MOD_ADDR} { input =getch(}; if (input == CМDSIM) cmd(); goto start; //Чтение из сети (файла). / / Если наш адрес модуля. //Если символ комаНДЬ1. Это не шедевр программирования на языке С, но работа­ ет. В качестве входного файла ко~анд я использовал input.txt
Первая сборка на макетной плате 1 09 (примечания ниже только для книжного варианта, в файле их делать не следует) такого вида: "noperat• Проверим, не будет ли мешать посторонняя команда "L03$3N" Проверим, не отвечает ли модуль на обращение к другим модулям "Rll$2N" Проверим, не отвечает ли модуль на чужие адреса "R03$2N" Включим второе реле третьего релейного модуля "R01$2S" Проверим, не отвечает ли модуль на чужие адреса "R03$2S" Запросим состояние второго реле третьего релейного МОдУЛЯ "R15$1N" Проверим, не отвечает ли модуль на чужие адреса "R03$1N" Включим первое реле третьего релейного модуля "R03$1S" Запросим состояние первого реле третьего релейного МОдУЛЯ "R03#1F" Проверим, не отвечает ли модуль на передачу состояния "R03$1F" Выключим первое реле третьего релейного мо.пуля "R03$1S" Запросим состояние первого реле третьего релейного МОдУЛЯ "R03$2S" Запросим состояние второго реле третьего релейного МОдУЛЯ Получаем выходной файл output.txt: R03#2N R03#1N RDЗ#lF R03#2N Теперь, пока вы опробуете работу в среде МРLАВ , я, по­ жалуй, прерву работу над книгой. Поеду и куплю все необхо­ димое для сборки конвертора RS232-RS485, программатора и создания прототипа. Затем соберу прототип на макетной плате, а когда закончу и проверю, поделюсь впечатлениями . Первая с6орка на макетной n11ате Пришло время поделиться впечатлениями. Подсчитав свои финансовые возможности, я отказался от некоторых запланированных покупок и решил упростить программатор, поскольку в настоящий момент собираюсь ра­ ботать только с контроллером PIC16F628A Я убрал из схемы
11 О Глава • 1 Базовая версия программатора внешнее питание, из схемы адаптера к про­ грамматору - все панельки, кроме 18-ножечной, и использо­ вал батарейку «Крона» в качестве внутреннего источника питания (для высоковольтного режима программирования) . На макетной плате я тоже установил панельку под микросхе­ му, с тем, чтобы проверить все схемы на одной макетной плате. К схеме конвертера я добавил стабилизатор на 5 В. Кабель от разъема DB9 конвертера RS232-RS485 я распаял на плате конвертера, хотя вначале собирался использовать разъем. После исправления нескольких монтажных ошибок (и эти «грабли» имели место) я решил проверить программатор, поскольку не в полной мере был уверен, что правильно ра­ зобрался со схемой. С программой МРLАВ программатор, естественно, не ра­ ботает. В Интернете- есть схемы программаторов, работаю­ щих с МРLАВ. Они не настолько сложны, чтобы их не исполь­ зовать, но я решил, что лучше воспользоваться программой PonyProg2000, схему программатора к которой собрал. При­ ходится скачивать последнюю версию программы, поскольку в предыдущей нет контроллера PIC16F628A. Рис. 1.42. Программа PonyProg2000
Первая сборка на макетной плате 111 Первое, что я делаю после запуска программы - выбираю устройство в меню Device • Pic 16 micro (Устройство • Pic 16 micro) или в окошках на панели. После выбора устройства проверяю работу порта в меню Setup (lnterface Setup... (Ус­ тановки интерфейса), используя СОМ2-порт), задаю номер порта и SI Prog 1/0. После щечка кнопки Probe (Проба) я получаю сообщение - Test Ok. Затем провожу калибровку (меню Setup • Calibration (Установки • Калибровка)) и опять получаю одобрение. На этом везение заканчивается. Вставляю микросхему в панельку, и первое, на что отважи­ ваюсь - щелкаю кнопку чтения Read Device (Прочитать устрой­ ство) на инструментальной панели. Итог показан на рис . 1.43. Рис. 1.43 . Первое сообщение программы PonyProg2000 Программа не распознает микросхему. Обращаюсь на сайт, С которого «Срисовал» программу. В разделе ТИПОВЫХ вопро­ сов и ответов нахожу похожую ситуацию и рекомендацию воспользоваться кнопкой Ignore (Игнорировать). Что и осу­ ществляю. Процесс проходит успешно, о чем сообщает программа, но в буфере сплошные единицы, а у меня сплошные сомнения - прочитал ли я хоть что-то? Я отключаю разъем от СОМ-пор­ та, получаю сообщение об успешном чтении, но в буфере одни нули, а тест порта не проходит. Появляется надежда, что я что-то читаю. Вторая волна сомнений касается вопроса: работает ли микросхема, если я не записал биты конфигурации, опреде­ ляющие режим работы тактового генератора контроллера, ведь я еще ничего не записывал. Поэтому решаюсь записать биты конфигурации, выбрав режим работы тактового гене­ ратора INТRС (сэкономил, отказавшись от покупки кварца). В меню Command • Security and Configuration Bits...
112 Глава • 1 Базовая версия (Команда• Биты конфигурации и защиты) устанавливаю флажки (рис. 1.44). Рис. 1.44 . Задание СJЮВЗ конфиl)'рации микроконтроллера Сознаюсь, что, не разглядев, как устанавливаются биты, я сде­ лал все наоборот - поставил галочки там, где должны быть нули. Я полагал, что, отметив биты, установлю их в единицу, а в результате закрыл все программирование. Пришлось испра­ вить свою ошибку. Биты конфигурации записались, я сбрасываю их и читаю. Появляется надежда, что вопрос с программированием ре­ шен. Но первые «мягкие» грабли, на которые я наступаю - про­ грамма ведет себя не так, как я от нее ожидаю. Я загружаю в программатор файл, созданный по версии, написанной на языке С. В итоге, я могу записать в контроллер все нули или все единицы. Но стоит м-не попытаться изменить в буфере хотя бы один байт, используя возможность редактирования в меню Edit • Edit Buffer enaЫed (Редактирование • Буфер редактирования доступен), чтобы записать что-то другое, как контроллер полностью обнуляется. С этой проблемой я долго не могу разобраться, поскольку не понимаю, вина ли это про­ граммы, или я что-то делаю не так. Я работаю с программой впервые и, судя по ошибке с установкой бит конфигурации, могу сделать множество ошибок. Конечно, все попытки обой· ти проблему успехом не увенчались. Устав от проб и ошибок, я решаю изменить подход - если я не смогу запрограммировать контршшер, то сама микросхема,
Первая сборка на макетной плате 11 3 которую я так берегу, мне будет не нужна. Либо я смогу ее за­ программировать, либо выброшу сразу. Я решаюсь сделать попытку программировать ее как мик­ росхему другого типа . Удачной оказывается попытка про­ граммирования PIC16X84. И я решаю, что им~нно так я буду ее программировать, а биты конфигурации запишу под эги­ дой PIC16F628. Это неудобно, но не покупать же дорогой про­ грамматор! Итак, я могу записать в микросхему что-то кроме нулей и единиц. Я загружаю НЕХ-файл, созданный программой, написан­ ной на языке С, используя на инструментальной панели кноп­ ку Read Program Memory (FLASH) (Прочитать Память про­ граммы). Вторые «Мягкие» грабли выглядят так - вся программа не занимает и двух строк в буфере. Я в это не верю. Поскольку файл имеет расширение НЕХ, я пытаюсь просмотреть его НЕХ-редактором и не вижу ничего, кроме символьной запи­ си. Тогда я открываю файл блокнотом: : 10000000830100308A0004282030840038300D201D : 1000100083013 92B04068001840A04060 31DOA2883 :020020000034АА :1004E20083018ClE712AlA0808008301B700831247 :1004F20003130ClE782A370899000800F401F501 4D :100502000310F30CF20C031C8D2A7008F407710817 :100512000318710AF5070310F00DF10D7 2087304 48 :10052200031 90034812A8301850107 309F00831655 :100532008501FЕ308 6 0090308312980 0 0 630 8316СЗ :100542009800683099008312061083169B011Cl4DO и т. д. Признаться, не ожидал. Пришлось углубиться в руковод­ ства и понять, что этот файл предназначен для загрузки в программатор и формат файла имеет вид: :ВВААААТГННR.. ННСС Где ВВ - количество байт в строке файла, АААА - адрес за­ писи данных, ТТ -указатель типа строки (00 - данные, 01 - конец файла, 02 - адрес сегмента, 04 - линейный адрес), ннн". нн - собственно данные, а се - контрольная сумма строки .
114 Глава • 1 Базова11 верси11 И данных в файле, конечно, больше, чем я получаю в бу­ фере. В чем причина? После того как я понял, что после пер­ вых строк идет безусловный переход по адресу, находящему­ ся в ко.нце программной области, а первый адрес после перехода лежит вне буфера, стало понятно, почему я не по­ лучил в буфере ничего интересного. Первой приходит мысль исправить адреса в файле НЕХ. Но это потребует изменения контрольных сумм, которые придется либо рассчитывать на калькуляторе, либо писать программу пересчета. Сущность же проблемы состоит либо в том, что файл подготовлен под загрузку в программатор, работающий с МРLАВ, ~ибо в том, что срок действия демон­ страционной версии компилятора языка С закончился. В размышлениях - купить компилятор (каким-то образом) или найти знакомых, работающих с микроконтроллерами и «Напроситься в гости», чтобы поработать некоторое время на чужом компьютере (меня эти походы изрядно «притомили»), я решаю поступить иначе. Делаю последнюю попытку - компилирую программу в МРLАВ для микросхемы PIC16F627A, которая имеет объем памяти программы вдвое меньше, чем моя PIC16F628A. Теперь, загружая НЕХ-файл в программу PonyProg2000, я вижу больше пары строк в буфере. Записываю этот файл (для микросхемы PIC16X84), используя кнопку Write Program Memory (FLASH) (Записать память программы). Записываю биты конфигурации (для микросхемы PIC16F628). Проверяю в меню Command • Verify АН (Команда• Проверить все) и получаю подтверждение правильности записи, затем перено­ шу микросхему на макетную плату. где собран интерфейс и установлены светодиоды. С этого момента опять начинаются «железные» грабли. Ничего у меня, естественно, не работает. Первое, что следует сделать, - определиться, что у меня работает, а что нет. Уверен ли я, что программатор у работа­ ет? Нет. Уверен ли я, что программа написана правильно? Нет. И т.д. Я понимаю, что «нет» - это самое определенное, что я получил к настоящему моменту.
Первая сборка на макетной плате 11 5 Тогда я решаю последовательно удалять эти «нет». В Ин· тернете нахожу пример программирования на языке С для микроконтроллеров PIC - простая программа, которая за· ставляет светодиод мигать. #include "piclбf62xa.h" #define Ьitset (var ,Ьitno) ( (var) 1= 1 « (Ьitno)) #define Ьitclr(var,bitno) ((var) &= -(1 << (Ьitno))) main() { unsigned int k; CMCON = Ох07; TRISA = ОЫ1111110; repeat: //Компараторы вЬ1КЛЮченьr. //RAO выход. for (k=O; k<45000; k++); //"Пустой" цикл для временной задержки. bitset(PORTA, 0); for (k=O; k<45000; bitclr(PORTA, 0); goto repeat; } //Выставить на RAO высокий уровень. k++); //Выставить на RAO низкий уровень. //Повторить ещё раз . Я компилирую ее и программирую микросхему. После уста· новки на макетную плату и включения питающего напряжения я получаю первое «да». Светодиод мигает. По меньшей мере, программатор работает. Теперь я хочу проверить работу конвертера RS232-RS485 . Удобнее всего было бы использовать осциллограф. Но у меня нет ничего кроме мультиметра с набором обычных функций измерения напряжения, тока, сопротивления. Кое-что я, все-таки, проверить могу. Для этого мне потре· буется программа работы с СОМ-портом. Можно написать на любом из языков программирования то, что работало бы с СОМ-портом. Но это займет время (позже это приходится сделать). Нахожу в Интернете программу под названием RS232Pro, в которой я смогу 25 дней поработать бесплатно. Есть, правда, предложение зарегистрировать программу, но сайт, где предлагается ее зарегистрировать, отсутствует. Ду­ маю, 25 дней - это срок, когда я либо получу положительные результаты, либо откажусь от всего.
116 Глава • 1 Базовая версия Проверяю, вЮiючив мультиметр, на измерение постоянно­ го напряжения на пределе 20 В входные напряжения от СОМ-порта. Некоторое время уходит на то, чтобы понять, что нужно щелкать кнопку RTS OFF в программе RS232Pro, но, наконец, я делаю и этот решительный шаг. Затем отправ­ ляю в порт последовательность символов 12345, и вижу, что у меня меняется напряжение на выводе TXD. Меньше, но ме­ няется напряжение на выводе 3 микросхемы МАХ! 483. Хоте­ лось бы проверить линию RS485. Для этой цели я пытаюсь передать простой текстовый файл с помощью программы RS232Pro, встав мультиметром на линию (в режиме измерения постоянного напряжения на пределе 20 В). Напряжение заметно меняется. Это убеждает меня, что конвертер, может быть, и не совсем правильно, но работает. I1орт Ц. модуль я настраиваю на скорость 9600, 8 бит дан­ ных, 1 стоповый бит без бита четности . Первым делом, я упрощаю программу релейного модуля, оставив только один символ R на прием, который сразу зажигает светодиод. Мо­ дуль не работает, но обращение к документации на микросхе­ му контроллера PIC16F628A заставляет меня задуматься в правильности выбора скорости. Я проверяю, меняя значение регистра SPBRG, разные скорости (соответственно, каждый раз перепрограммируя контроллер}, пока не зажигается све­ тодиод. Скорость оказывается равной 2400 (я даже не уверен, что ее не следует снизить до 1200). Модуль начинает реагиро­ вать на команды, передаваемые с компьютера. В данный момент мне кажется, что дальше все образуется само собой, и модуль заработает. Но получается не совсем так. Мне даже удается получить ответ от модуля на запрос о со­ стоянии реле. Ответ немного странный, но, хотя бы какой­ то, он есть. Теперь беда другая. Одно выполнение команды, один ответ на запрос о состоянии реле, и модуль «Виснет». Он не реагирует больше на команды до момента вЮiючения пос­ ле сброса питания. Я человек терпеливый, но и мое терпение истощается по мере продвижения к выполнению поставленной задачи. Главная
Первая сборка на макетной плате 117 беда - я не уверен, что программа RS232Pro подходит для ра­ боты. По этой причине отправляюсь к знакомым, чтобы на­ писать программку для работы с модулем. Думаю, я так надо­ ел им, что они дарят мне старенькую версию Visual Basic (не совсем полную), которую кто-то из них получил на презента­ ции во время одной из конференций. Мне важно, что версия работает. Итак, я создаю заготовку для среды программирования (о чем речь пойдет в конце этой части книги), куда добавляю три кнопки: одну - для отправки команд, другую - для полу­ чения команд и последнюю - для того, чтобы полученные команды отобразить. Используя оба варианта работы с СОМ-портом, я посте­ пенно начинаю понимать, что после получения команды зап­ роса состояния реле модуль начинает передавать ответ, но одновременно читает все, что есть на линии RS485. Прочи­ тав же обращение к релейному модулю, свой номер модуля, он пытается реагировать на эти события. То естъ, при переда'Че моду.мм в сеть хшких-либо данных нужно дать время на переда'Чу - это во-первых, и отк.л:ючить на время переда'Чи приемних - это во­ вторих. Не с первого раза получилась и запись состояния реле в EEPROM - скоро сказка сказывается, да не скоро дело дела­ ется. Вот такие впечатления, которыми я обещал поделиться, остались у меня после посещения магазина и попытки пре­ творить в жизнь компьютерную версию разработанного мо­ дуля. Когда я написал, что отправляюсь в магазин, и поделюсь впечатлениями, я и сам не ожидал, что впечатлений будет так много. Конечно, отсутствие опыта, не совсем подходящие средства разработки, разница между тем, что нарисовано на бумаге, и тем, что будет создано на основе этого рисунка - все так, но... Я не ожидал, что столько «Граблей» окажется на пути реализации достаточно простой конструкции. Однако продолжим создание запланированных модулей.
118 Глава 8 1 Базовая версия Схема и nроrрамма модуnя nриема ИК-команд Первый вопрос - зачем нам нужно что-либо, имеющее отно­ шение к инфракрасным кодам? Домашняя аппаратура - телевизоры, музыкальные цент­ ры и т. п . - управляется с помощью пультов дистанционного управления, излучающих команды в ИК-диапазоне . Чтобы управлять аппаратурой с компьютера (программно), нам по­ требуется излучатель ИК-кодов - модуль, который по коман­ де компьютера будет излучать необходимые ИК-команды. Для работы этого модуля нам потребуется еще и считыватель ИК-кодов. Кроме того, пора подумать об устройствах управ­ ления в системе , причем хотелось бы иметь нечто достаточ­ но дешевое. Одним из устройств управления, как мы решили, станет компьютер. Можно подумать о создании устройства управле­ ния с использованием клавиатуры: нажатие клавиши отправ­ ляет в системную сеть команду управления . Но и у компьютера, и у клавишного модуля есть небольшой недостаток: их удобно держать на стене или на столе, но не на кресле, где мы проводим достаточно много времени. Воп­ рос о клавишном модуле управления пока отложим и рассмот­ рим возможность управления с помощью старого пульта от видеомагнитофона или телевизора, которые давно отправи­ лись бы на свалку, если бы не завалялись на полке. В этом слу­ чае нам нужен модуль приема инфракрасных кодов. Что собой представляют инфракрасные коды, излучаемые пультами управления? Не вдаваясь в теоретические тонкости, можно сказать так: когда на пульте управления, положим, телевизором нажима­ ется клавиша, установленный в нем светодиод (ИК-диапазо­ на) начинает мигать. При этом он воспроизводит последова­ тельность вспышек с некоторой частотой (от 20 до 400 кГц) и пауз, которые в совокупности и есть код управления. Каж­ .дая клавиша имеет свой набор вспышек и пауз . Клавиши раз­ ных пультов излучают разные коды управления, частота
Схема и программа модуля приема ИК-команд 119 (несущая частота) вспышек также может различаться. В каче­ стве примера приведу структуру кодов управления фирмы Sony: Technical Info Code length (длина кода): 12 bits (15 bits для некоторых фуНКЦИЙ видеокамеры) Carrier (несущая) : 40kНz +------+ Header (Заголовок): + +--+ .. _4т__т +------+ 1 кодируется: + +--+.. _2т__т +--+ О кодируется: 1 •• 1 + +--+ _т_т т = 550us приблизительно Пауза между данными: 25ms data: hhhhxxxxxxyyyyy MSB LSB хххххх command (команда) уууууу address (номер аппарата) Таким образом, сначала идет заголовок длиной в 2,75 мс (инфракрасный свет мигает с частотой 40 кГц), затем пауза в 0,55 мс и код, в качестве которого для простоты рассмотрим последовательность 1001. Он будет соответствовать вспышке в 1,1 мс, паузе в 0,55 мс, вспышке в 0,55 мс, паузе в 0,55 мс, вспышке в 0,55 мс, паузе в 0,55 мс, вспышке в 1,1 мс, паузе в 0,55 мс, паузе в 25 мс. Уф! Как будут выглядеть коды других производителей? Скорее всего, иначе. Есть несколько рекомендаций по применению
120 Глава • 1 Базовая версия ИК-кодов, а производители вольны придерживаться их или нет. Кодирование логической единицы может производиться переходом (фронтом) от паузы к вспышке, логического нуля обратным переходом. Заголовок может отсугствовать и т.д. Многие универсальные пульты управления, запоминаю­ щие ИК-коды, фиксируют длительность посылок и пауз, ждуг длинной паузы между посылками, означающей завершение команды, а затем сохраняют значения в формате собственно­ го времени, которое зависит от тактовой частоты синхроге­ нератора. Если при воспроизведении кода они могуг менять несущую частоту, то записывают служебную информацию, ее определяющую. Как и в предыдущем проекте, вначале приведу схему (рис. 1.45) и программу. В табл. 1.4 перечислены все необходимые элементы. Таблица 1.4. СпецификаЦИ11 модуля приема инфракрасных кодов No Обоэна- Изделие Количество Цена Примечания чение (р.) 1 DD1 МАХ1483 1 96 2 DD2 PIC16F628A 1 100 Установить на панельку 3 DDЗ LM2936-Z5 1 68 4 DD4 TSOP17 (16) 1 10 5 VD1 АЛЗ07 1 з 7R1 1кОм0,25 1 1 8R2 12 кОм 0,25 Вт 1 1 9АЗ 100 Ом 0,25 Вт 1 1 10 R4-R7 10 кОм 0,25 Вт 4 4 11 С1, С2 0,1 мкФ 2 6 12 сз 100,0мкФ16В 1 5 13 С4 4,7 мкФ 5В 1 з 14 Х1 Клеммник 4 к 1 3 15 S1 Перекл. 2 пол., 4 н 1 5 16 Socket DIP18 1 21 Панелька Для обращения к модулю с запросом принята новая ИК­ команда - Cxx$0S (аналогично команде запроса статуса релей· ного модуля).
DD1 8 C1_L DD2 14 1 1I1 6 МАХ1483 PIC16F628A 4 8 DD4 2 з 6 :J1:r::C41111S1 RB4 5 =::1111 5 ·- RB7 з TSOP1737 2 Рис. 1.45 . Принципиальная схема модуля приема инфракрасных кодов + 128 :r:: сз _[Х1 ~~::i: :::i ::i: ф ~ s: ~ i1:S ..... N .....
122 Глава • 1 Базовая версия Ответ модуля - Cxxkkk, если команда пришла, и Cxx#ff, если новая ИК-команда не приходила. Здесь хх, как и ранее, - двухбайтовый адрес модуля, kkk - три байта символов номера команды от 001 до 255, ff под­ тверждает отсутствие изменений за время опроса. Проrрамма модуn• nриема ИК-команд на •эыкеС Фаiiп заrоповка #define MODULNAМESIM ·с· #define CМDSIM "$" void putch(unsigned char); unsigned char getch(void); int init_comms (); int sirn_num _adr(); int cmd(); Фаiiп nроrраммы #include <piclбf62xa.h> #include <stdio.h> #include "ir_rec_fnl.h" unsigned char input; / / Считываем содержимое приемного регистра. unsigned char MOD_SIМl; // Первый символ адреса моруля. unsigned char MOD_SIM2; //Второй символ адреса моруля. unsigned char IRSIMl; unsigned char IRSIM2; unsigned char IRSIMЗ; unsigned char cornmand_reciev [6]; //_Массив для полученной команды. int РНОТОСОМЕ =О; //Флаг активности фотоприемника. int MOD_ADDR; // Заданный адрес модуля, как число. unsigned char IRCOММAND = О; int MOD_ADDR; // Заданный адрес модуля, как число. int siml_num = О; int sim2_num = О; int sim_end_num = О; int МOD_NUМ; 11 Полученный адрес модуля, как число . int i;
Схема и программа модуля приема ИК-команд 1 23 int k; int 1; int m; unsigned char getch() { while ( (!RCIF) & (RВЗ регистр не пуст. continue; retum RCREG; 1)) //Устанавливается, когда void putch (unsigned char Ьуtе) { 11 Вывод одного байта . while( !TXIF) continue; TXREG =Ьуtе; int init_camпs () { PORTA =ОхОО; CMCON = Ох7; ТRISA = ОхОО; ТRISB = OxFE; PCON = Ох8; //Устанавливается, когда регистр пуст. //Инициализация мо.цуля. //Настройка портов А и В. 11 Тактовая частота 4 МГц. RCSTA = ОЫООlОООО; TXSTA = ObOOOOOllO; 11 Настройка приемника. 11 Настройка передатчика. SPBRG = Охб8; INTCON = ОхО; RВО = ОхО; PIEl = ОхО; TlCON = ОхО; ноль. ТМR~Н =ОхОО; ТМRlL =ОхОО; IRCOММAND = ОхО; //Настройка режима приема-передачи. //Запретить прерывания. 11 Выключим передатчик драйвера RS485. / / Настройка таймера 1, запрет прерывания. 11 Выбор внутреннего генератора, бит 1 в 11 Определим номер мо.цуля. MOD_ADDR = PORTB; //Номер МОдУЛЯ в старших битах. МOD_ADDR=MOD_ADDR>>4; } //Сдвинем на четыре бита. 11 Преобразуем символьный адрес в число. int sim_nшn_adr ()
124 Глава • 1 Базовая версия sim_end_num = ОхО; MOD_SIMl = command_reciev [1]; 11 Первый символ номера. MOD_SIМ2 = command_reciev [2]; 11 Второй символ номера. MOD_SIMl = MOD_SIMl - ОхЗО; MOD_SIM2 = MOD_SIM2 - ОхЗО; sim_end_num = MOD_SIMl*OxOA + MOD_SIМ2; return sim_end_num; int ir_cmd () intЬ=О; CREN = О; while (RВЗ == 0) continue; 11 Ждем окончания заголовка. for (Ь=О; Ь<В; Ь++) //Обработаем наши :импульсы. { while (RВЗ != 0) continue; //Дождемся :импульса. time () ; / / Включаем таймер 1. while ( !ТМRlIF); 11 Дождемся такта . TlCON = ОхО; / / Выключаем таймер. ТМRlIF = Ох О; / / Сбросим флаг. if (RВЗ == 0) //Если низкий уровень, то •1•. { IRCOММAND = IRCOММAND +1; / / Запишем это. time (); / / Включаем таймер 1. while ( !ТМRlIF); // Дождемся такта. TlCON = ОхО; / / ВЫключаем таймер . ТМRlIF = ОхО; / / Сбросим флаг . } else // Высокий уровень, значит "0". IRCOММAND = IRCOММAND; // Запишем это. } if (Ь<7) IRCOММAND = IRCOММAND<<l; на бит. //Сместимся влево } РНОТОСОМЕ = ОхО; RAO = ОхО; RAl=Oxl; for (m=O; m<4; ++m) {
Схема и nроrрамма модуля приема ИК-команд 1 25 for (1=0; 1<10000; ++1); CREN = 1; RAl =О; int crnd() ( CREN = 1; input = getch(); switch (input) { case "С": //Если обращение к фото модулю. for (i=l; i<б; ++i) // Запишем команду в массив. { input = getch(); comrnand_reciev (i] = input; } МOD_NUМ = sim_num_adr () ; / / Чтение из сети. if (MOD_NUМ != МOD_ADDR) break; //Если не наш адрес . else if (command_reciev [З] = "$ ") //Если команда. { if (command_reciev [5] = "S") ir_stat(); default: break; } . void time () / / Таймер 1 для чтения ИК. { ТМRlН = OxFD; //Установка числа циклов до переполнения. ТМRlL = Ох43; // FFFF минус 700 (2ВСh). TlCON =Oxl; 11 Включение таймера. int ir_stat () { int ircom; int ircoml; int ircom2; int ircomЗ;
126 Глава • 1 Базовая версия command_reciev[O] = "С"; coпunand_reciev[l] = МOD_SIMl+OxЗO; cornmand_reciev[2] = MOD_SIM2+0x30; ircorn = IRCOММAND; 11 Преобразуем коман,цу в символы . ircornl = ircom/Ox64; IRSIMl ircoml + ОхЗО; ircorn2 (ircom - ircoml*Ox64)/0xA; IRSIM2 ircom2 + ОхЗО; ircomЗ IRSIМЗ (ircom - ircoml*Ox64 - ircom2*0xA); ircomЗ + ОхЗО; if (IRCOММAND == 0) { command.__reciev[ЗJ "# "; command. __r e ciev[4] •f•; command_reciev[5] "f"; CREN =ОхО; // Запрещаем прием. RBO = Oxl; //Переключим драйвер RS485 на передачу. TXEN = Oxl; / / Разрешаем передачу. for (i=O; i<б; ++i) putch(command_reciev[i]); for (i=O;i<lOOO;i++); //Задержка для вывода. for (i=O; i<б; ++i) command_reciev [i] = • "; RBO = ОхО; //Выключаем драйвер RS485 на передачу. TXEN = ОхО; / / Запрещаем передачу. CREN =Oxl; //Разрешаем прием. else / / За время между двумя запросами пришла ИК команда. { command.__reciev[З] command_reciev[4] command.__r eciev[5] IRSIМl; IRSIM2; IRSIМЗ; CREN =ОхО; RBO = Oxl; 11 Запрещаем прием . //Переключим драйвер RS485 на передачу. TXEN = Oxl; / / Разрешаем передачу for (i=O; i<б; ++i) putch(command_reciev[i]); for (i=O;i<lOOO;i++); //Задержка для вывода. for (i=O; i<б; ++i) command_reciev [i] = • "; RBO = ОхО; TXEN = ОхО; 11 Выключаем драйвер RS485 на передачу. 11 Запрещаем передачу.
Схема и программа модуля приема ИК-команд 127 CREN =Oxl; //Разрешаем прием. } IRCOММAND = ОхО; / / Мы передали коман.цу, она больше не нужна } void main (void) { 11 Начнем работать. init_cornms (); / / Инициализация модуля. coпunand_reciev [i) =" •; for (i=O; i<б; ++i) command_reciev [О] РНагосОМЕ = ОхО; RAO = ОхОО; //Прочитаем и преобразуем номер модуля. MOD_ADDR =PORTB; // Номер модуля в старших битах. MOD_ADDR=MOD_ADDR>>4; 11 Сдвинем на четыре бита. start: RA2 = Oxl; ~/ Чтобы видно, что модуль включен. /* Нет ИК-сигнала, проверим сеть */ CREN =Oxl; if (RCIF) ard(); if (!RВЗJ // Появился ИК сигнал. { CREN =ОхО; for (k=O; k<ЗO;++k); //Поставим задержку. if (!RВЗ) { 11 ИК сигнал не пропал? РНагосОМЕ = Oxl ; RAO = OxOl; 11 Обработаем ИК коман.цу . ir_cmd (); РНОТОСОМЕ = ОхО; RAO = ОхОО; goto start; else РНОТОСОМЕ = ОхО; RAO = ОхОО; CREN =Oxl; } goto start ;
1 28 Глава • 1 Базовая версия HEX-фaiin дп• заrрУ3к• в nporpaммarop :10000000830100308A000428203084004C300D2009 :100010008301102A04068001840A0406031DOA28AD :02002000003ft\A :1002D8008301861D71298ClE6C291A080800FD30BF :1002E80083018F0043308E009001900A080083013B :1002F800CBOOB31203130C1E7D294B0899000800ВC :10030800F401F5010310F30CF20C031C922970089B :10031800F40771080318710AF5070310FOODF10IX:l :10032800720873040319003486298301В901ВАО1IХ: :100338003C08A4003D08A500D030A407A5070A3052 :10034800F200F3012408FOOOF10184212508740764 :10035800B90075080318750AВAOOF1003908FOOOE9 :1003680008008301850107309F0083168501FE3050 :10037800860008308E00903083129800063083166D :100388009800683099008B018312061083168C013F :10039800831290018F018E01A0010608A700A80111 :1003A8000430F000280DA80CA70CFOOBD629080083 :1003В800830118166C21A6000B2AAD01ADOAAE0107 :1003C8002E08803AF00080307002063003192D02A2 :1003D8000318FA296C21A6002DOBЗB3E84008313IX: :1003E80026088000ADOA0319AEOAE429992170088D :0803F800A9007108AA00280603 ': 10040000031D042A27 082 90603100800243 ОВЕООО 6 :100410005330COOOB62A2608433A031D0800E129IX: :10042000B521AD01AE011D2A2D083B3E840083138A :100430002030BOOOADOA0319AEOA2EOBB03AF00081 :1004400080307002063003192D02031C142A433039 :10045000ВВ00АВ01АС0 105100608А700А8010430Еl :10046000F000280DABOCA70CFOOB312A0515181662 :100470008ClAIX:218619582A1812AF01B0013008F5 :10048000803AF000803070021E3003192F020318EA :100490004D2AAFOA0319BOOA3F2A8619362AAВ0142 :1004АОООАВОААСО105145D22АВ01АС010510362А84 :1004В000АВ01АС0105101 816362А8 301С101С20137 :1004C0001812861D612AC101C201 8619652A73218D : 1004DOOOOC1C682A900 10C108619752AAOOA732139 :1004EOOOOC1C70 2A90010Cl0762A2008 4208803AD1 :1004FOOOF000803070020730031941020318822ABD : 100500000310AOOIX:10A0319C20A4208803AFOOOB4 :1005100080307002083003194102031С652ААВ01С8 :10052000AC010510 8514B301B4013408803AF00021
Схема и программа модуля приема ИК-команд 129 :10053000803070020430031933020318В32АВ1016А :10054000B2013208803AFOOOA7307002103003196F :1005500031020318АF2АВ10А0319В20АА12АВ30А59 :100560000319В40А952А1816851008004330830130 :10057000ВВ00240830ЗЕВС00250830ЗЕВD002008ЕА :10058000C500C6016430F200F3014608Fl004508D9 :10059000FOOOB1237408C7007508C8004708303E52 :1005A000Al006430F200F3014808Fl004708FOOOBO :1005B00084214608Fl004508F0007408F002031CBD :1005COOOF1037508Fl020AЗOF2000030F301B123A3 :1005D0007408C3007508C4004308303EA2000A3006 :1005EOOOF200F3014408Fl004308F000842174088C :1005FOOOC9007508CA006430F200F3014808Fl0030 :100600004708F00084214608Fl004508F00074080E : 10061000F002031CF1037508Fl024908F002031C03 :10062000Fl034A08Fl027008Cl007108C2004108D4 :1006300030ЗЕАЗООА008031D632В2330ВЕ0066ЗОАС :10064000BFOOC00018120614831698168312AD015D :10065000AE012E08803AF000803070020630031997 :100660002D0203183D2B2D083B3E84008313000808 :100670007B21ADOA0319AEOA292ВAD01AE012E086C :10068000803AF00083307002E83003192D0203181D :100690004D2ВADOA0319AEOA3F2ВAD01AE012E085A :1006A000803AF00080307002063003192D020318E2 :1006BOOOAA2B2D083B3E8400831320308000ADOA16 :1006C0000319AEOA4F2B2108BE002208BF002308El :1006DOOOC00018120614831698168312AD01AE01DD :1006E0002E08803AF00080307002063003192D0287 :1006F0000318842В2DО8ЗВЗЕ8400831300087В21С4 :10070000AD0A0319AEOA702ВAD01AE012E08803A76 :10071000F00083307002E83003192D020318942B87 :10072000ADOA0319AEOA862ВAD01AE012E08803A40 :10073000F00080307002063003192D020318AA2B36 :100740002DОВЗВЗЕ8400831320308000АDОА03193Е :10075000АЕОА962В06108316981283121816АО0163 :100760000800F601FllFВВ2BF009FOOA0319Fl0391 :10077000Fl097617F61773088039F606F31FC72BB1 :10078000F209F20A0319FЗOЗF309C72BF601F40186 :10079000F50172087304031DD02BF001Fl01003440 :1007A0001FЗOF6040310F60AF20DF30D031CD32BD1 :1007BOOOF30CF20C73087102031DE02B7208700237 :l007C000031CE82B7208F0027308031C730AF10281 :1007DOOOF40DF50DF60BF61AD82BF61FF42BF409Dl
130 Глава • 1 Базовая версия :1007EOOOF40A0319F503F5097408F2007508F3001B :1007F000761F0034F009FOOA0319Fl03F1090034FF :OOOOOOOlFF А для тех, кто не потерял интерес к процессу разработки собственных модулей и не спешит, я продолжу рассказ. Итак. Какие требования мы предъявим к нашему модулю приемника инфракрасных кодов? Учтем, что основная задача модуля - принимать коды, которые мы назовем системными. В качестве системных кодов, удобно было бы взять числа от 1 до 255 в формате выше разобранной структуры ИК-кода. На данном этапе примем этот вариант. Повторим еще раз, как будет выглядеть системный ИК-код. Вспышка с несущей частотой 37 кГц длительностью 2,2 мс (заголовок) . Байт ко­ манды от 1 до 255 с соответствующими вспышками и пауза­ ми. Пауза 25 мс между командами. Требования к модулю: • модуль должен принимать системные -ИК-команды с не­ сущей частотой 37 кГц; • модуль должен ответить на запрос центрального управ­ ля19щего устройства (компьютера) по интерфейсу RS485, обозначив номер принятой ИК-команды. Несколько слов о комплектующих элементах. Разумнее всего, с моей точки зрения, использовать фотоприемник TSOPI737 - рис. 1.46 - (если вы задействуете пульт с несу­ щей частотой 37 кГц , в противном случае следует выбрать другой фотоприемник из этой серии) . На рис. 1.47 схема его включения . Рис. 1.46. Внешний вид и выводы фотоприемника
Схема и nроrрамма модуnя приема ИК-команд 1 З 1 Рис. 1.47 . Типовая схема включения фотоприемникаTSOP Конденсатор 4, 7 мкФ желательно располагать непосред­ ственно около фотоприемника, если между модулем и при­ емником несколько метров провода. Подобное может про­ изойти, если вы не удовлетворитесь проверкой на макетной плате, а захотите воплотить модуль в жизнь и при этом реши­ те убрать сам модуль подальше, а на виду оставить только фотоприемник. Фотоприемник невелик по габаритам, его можно приклеить с помощью двустороннего скотча на панель телевизора. Именно в этом случае я советую непосредствен­ но к ножкам фотоприемника припаять конденсатор 4,7 мкФ. На выходе фотоприемника формируются сигналы (рис. 1.48): в отсутствие команд его выход в высоком состоянии; при на­ личии ИК-пульсаций (с частотой 3.7 кГц), он переходит в низ­ кое состояние. Output Signal, (see Fig.1 О) Vo 948134 Рис. 1.48 . Типовой вид сигнала на выходе фотоприемника Здесь время Ton соответствует посылке ИК-импульсов, Toff- паузе. Можно приступать к написанию программы. Как и прежде, для установки заданного адреса используем четыре старших бита порта В (RВ7-RВ4). Для работы с сетью применим встроенный в микроконтроллер блок USART, а фотоприемник подключим к выводу RАб. Добавим еще свето­ диод для индикации наличия сигнала, который подключим
132 Глава • 1 Базовая версия к выводу RAO. Поскольку остальные выводы портов нас не ин­ тересуют, отметим только, что в отличие от предыдущей кон­ фигурации порта А - вывод RАб - следует установить на ввод (в предыдущем варианте порт работал на вывод) . Основные блоки_ программы: • инициализация модуля; • ожидание активности приемника USART; • ожидание активности от фотоприемника; • обработка сетевой команды от компьютера; • обработка ИК-команды от фотоприемника. В предыдущей программе мы могли спокойно ждать актив­ ности в сети и ни о чем не заботиться, в этой программе нам приходится оТЮiикаться на два события - активность в сети и активность фотоприемника. Будем считать, что главное - это ожидание активности фотоприемника, и попробуем предста­ вить, что будет происходить при работе с реальной системой. Каждое слово команды, состоящее из 6 байт, занимает (байт - 44 мкс) 0,264 мс . Положим, мы добавим 0,5 мс между командами. Основное занятие компьютера - постоянный опрос моду­ лей, поскольку программа должна выявлять события (измене­ ние состояния модулей) и выполнять действия, соответству­ ющие этим событиям. В данном плане модуль. который опрашивает и сеть, и фотоприемник, должен отслеживать изменения в обоих источниках. Пока модуль «слушает» сеть, он не «слышит» фотоприемник, и наоборот. Вероятно, разумно было бы использовать механизм преры­ вания, хотя бы для работы по прерыванию с фотоприемни­ ком. Основанием стал бы тот факт, что в сети циркулируют запросы состояния, на которые модуль постоянно «отвлекает­ ся». При этом легко пропустить изменение состояния фото­ приемника. Но для начала попробуем оценить ситуацию. Мы определили длительность заголовка ИК-команды в 2,75 мс. Основное назначение заголовка-дать «Понять» фо­ топриемнику, что далее последует команда. Таким образом, изменение состояния фотоприемника с целью «привлечь внимание» контроллера модуля будет длить­ ся около трех миллисекунд. За это время успеет пройти
Схема и программа модуля приема ИК-команд 133 около 10 (длительность слова команды в сети около 0,3 мс) слов команды. А это дает основания предполагать, что модуль успеет все «оценить» и перейдет к приему ИК-команды . В от­ сутствие прерываний он примет команду полностью, если это системная команда, прежде чем вернется к прослушива­ нию сети. Однако скорость поступления ИК-команд едва ли будет превышать 0,3 с (интервал между двумя нажатиями на одну и ту же клавишу). То есть, за время между поступлениями ко­ манд у компьютера будет возможность послать около 1000 за­ просов. В итоге, если мы не планируем программу, которая будет нуждаться в 2000 запросов, а пользователь не будет иг­ рать на клавишах управлею~я. как на рояле, особых проблем возникнуть не должно .. . Мы не собираемся строить очень разветвленную сеть с большим количеством устройств. Но даже если бы мы этого захотели, то могли бы увеличить скорqсть работы в сети с 9600 бит/ с (в наших рассуждениях) до 115 ООО бит/с. Это из­ менение увеличило бы число возможных запросов до 12 ООО. Реальное время между командами я бы тоже оценил в 3-30 с, что позволило бы увеличить количество возможных сетевых запросов до 120 ООО. Если это не поможет, что ж, переделаем все полностыо! Итак, предварительная оценка, не исключаю, что ошибоч­ ная, позволяет нам считать возможной работу модуля без ис­ пользования прерывания. На том и порешим. Писать программу на ассемблере или на языке С? Я , пожа­ луй, пока не перестанет работать демонстрационная версия компилятора С, использую эту возможность. &пок """""ап11эац1111 модуn• Не мудрствуя лукаво, поправим и используем в этом блоке код предыдущего модуля. int init_comms (1· { PORTA = ОхО; CMCON =Ох7; ТRISA = ОхСО; ТRISB = ОхFб; 11 Инициализация модуля. 11 Настройка портов А и В. 11 Здесь только RАб на ввод .
134 Глава • 1 Базова• вереи• RCSTA = Ох90; ТХSТА = Ох4; SPBRG = Охlб; INТCON = О; PORTB = О; 11 настройка приемника. 11 настройка передатчика. //настройка режима . приема-передачи. 11 запретить прерывания. //Выключим передатчик драйвера RS485. } Sпок oSpaSorк• кома1111•• фоrоnр•емн•ка Пока RАб в высоком состоянии (" 1»), ничего не надо делать. Проверим состояние USART. Если обращение идет не к на­ шему модулю, делать ничего не надо, вернемся к определе­ нию состояния RАб . Я, как мне кажется, весьма рассудительно подошел к этому блоку программы. Но сомнения остаются . Я не уверен, будет ли она вообще работать, переключаясь с прослушивания от одного источника к другому. Я, пожалуй, выделю блок и проверю его до написания ос­ тальной части программы. Не забудьте установить нужное состояние конфигурации (3F1Ah) по адресу 2007h! Мне понадобится файл заголовка: #define MODULNAМESIМ ·с· #define CМDSIM "$ " void putch(unsigned char); unsigned char ge tch(void); int init_cormns (); int sim_nurn _adr(); int cmd(); и файл программы: #i nclude <piclбf62xa.h> #include <stdio .h> #include "ir_rec.h" unsigned char input; регистра. unsigned char MOD_SIMl; unsigned char MOD_SIM2 ; 11 Считываем содержимое приемного / / Первый символ адреса мо,цуля. 11 Второй символ адреса мо,цуля.
Схема н проrрамма модуля прнема ИК-команд 135 unsigned char СОММАND; //Символ команды. int MOD_ADDR; // Заданный адрес модуля , как число. int siml_num = О; int sim2_num = О; int sim_end_num = int МOD_NUМ; int РНОТО; int РНОТОСОМЕ = О; int FLAG = О; О; //Полученный адрес модуля, как число. //Временная переменная. unsigned char getch() ( while( !RCIF); пуст. continue; retum RCREG; //Устанавливается, когда регистр не //Вывод одного байта. void putch(unsigned char Ьуtе) ( PORTB = 1; TXEN = 1; while( !ТXIF) //Переключим драйвер RS485 на передачу. 11 Разрешаем передачу. / / Устанавливается, когда регистр пуст. continue; TXREG = Ьуtе; int init_comms () ( PORTA = ОхСО; CMCON = Ох?; TRISA = ОхСО; TRISB = ОхFб; RCSTA = Ох90; TXSTA = Ох4; SPBRG = Охlб; INТCON=O ; PORTB = О; } / / Инициализация модуля. 11 Настройка портов А и В. //Настройка приемника. 11 Настройка передатчика. //Настройка режима приема-передачи . //Запретить прерывания. // Выключим передатчик драйвера RS485. //Получение и выполнение команды. int cmd() (
136 Глава • 1 Базовая версня input = getch(); //Преобразуем символьный адрес в число. int sim_num_adr() sim_end_num = О: siml_num = getch(); MOD_SIMl = siml_num; sim2_num = getch(); MOD_SIM2 = sim2_num; siml_num = siml_num - //Чтение первого символа номера . 11 Сохраним первый символ. //Чтение второго символа номера. / / Сохраним второй символ. ОхЗО; sim2_num = sim2_num - ОхЗО; sirn_end_num = sirnl_num*OxOA + sim2_num; return siПLendJlum; 11 Начнем работать. void main (void) { init_comrns(); //Инициализация мо.цуля. //Прочитаем и преобразуем номер мо.цуля. MOD_ADDR = PORTB; //Номер МОдУЛЯ в старших битах. MOD_ADDR=MOD_JillDR>>4; //Сдвинем на четыре бита. start: РНОТО = PORTA; //Начинаем работать. if (РНОТО&Ох40) РНОТОСОМЕ =О; //Нет ИК-сигнала. if (!(РНОТО&Ох40)) РНОТОСОМЕ = 1; //Появился ИК-сигнал. while (РНОТОСОМЕ == 1) // Обработаем ИК командУ. { FLAG=1 break; } //Нет ИК-сигнала, проверим сеть. input = getch(); while (input == MODULNAМESIM) { FLAG=О; break; goto start;
Схема и проrрамма модуля приема ИК-команд 137 В файл input.txt запишем: "R03$0N" "C03$0S" Перед началом проверки запустим RВ4 Set High (Устано­ вить в высокое состояние), RВ5 Set High и RАб Set High на Stimulus Controller (я изменил адрес с 01 на 03, а фотоприем­ ник на вводе RАб перевел в пассивное состояние). Переменная FLAG ·покажет, попадаем ли мы в нужное место программы. Впоследствии мы вместо нее будем вызы­ вать подпрограммы обработки команды cmd () и ИК-команды ir_cmd (). Кнопками RАб Set High и RАб Set Low мы будем имитировать изменение состояния фотоприемника. Вроде бы работает. Хотя, признаюсь, получилось не сразу- я забыл задать слово конфигурации по адресу 2007h. Перейдем к обработке ИК-команды (обработку команд сети, я думаю, возьмем из предыдущей программы, подпра­ вим, попробуем). После получения заголовка и паузы в 0,55 мс мы можем ожидать прихода всего двух сочетаний импульс-пауза. Ноль - это импульс-пауза одинаковой длительности 0,55 мс. Едини­ ца - импульс-пауза, где импульс - 1,1 мс, а пауза - 0,55 мс. Таким образом, нам нужны два интервала в 1, 1 мс и 0,55 мс. Для получения интервалов можно воспользоваться таймерами или отсчитать их в пустом цикле. Я воспользуюсь второй воз­ можностью. Все команды, кроме переходов, выполняются за один ма­ шинный цикл (200 нс при частоте 20 МГц). Положим, что при частоте 4 МГц машинный цикл равен 1 мкс. Тогда нам нужно досчитать до 1100 для промежутка в 1,1 мс и до 550 для корот­ кого промежутка. Сравнивая эти промежутки времени с приходящими им­ пульсами, мы можем определить, единицу или ноль получаем в ИК-команде. Более того, мы можем установить тоЛько один счетчик до 550 (для верности возьмем 560) для вычисления байта команды. На практике при первой проверке я успевал нажать кноп­ ку RАб, чтобы имитировать приход ИК-команды. Теперь не
138 Гnава • 1 Базовая версия успеваю. Слишком все быстро. Попробуем поискать, не мо­ жет ли МРI.АВ помочь с симуляцией, как это было в случае с USART. И действительно, как любил повторять один из моих зна­ комых, «Грамотная программа!». В разделе Debugger • SCL Generator (Отладчик• SCL генератор) находим New Workbook (Новая рабочая тетрадь). Щелкаем и открываем окошко, в котором можно настроить имитатор работы фо­ топриемника. В очередной раз наступив на грабли (вместо того чтобы почитать описание), я начинаю понимать, что в первой ко­ лонке нужно задать текущее время, выделяя события. Для этого следует, щелкнув кнопку со стрелкой правее надписи Time Units (Единицы времени), выбрать мкс (us) . Событием в данном случае будет изменение состояния вывода RАб пор­ та А, которое мы зададим, щелкнув большую клавишу Click here to Add Signals (Щелкните здесь, чтобы добавить сигна­ лы). Из раскрывающегося меню выберем RАб и получим еще одну колонку с этим именем . Теперь в колонку Time {dec) впишем десятичные значения текущего времени (мкс), а в колонку RАб - состояния входа, соединенного с фотоприем­ ником. Не следует забывать, что в отсутствие активности фотоприемник на выходе имеет высокий логический уро­ вень («1»). Первый ИК-сигнал, с которым я хочу работать, выглядит так: 10000000. Если вернуться к разговору об ИК-командах и выбранному решению по системным командам, то сигнал, поступающий с фотоприемника на вход RАб, должен выглядеть, как показа­ но на рис. 1.49 и 1.50. Значения, которые следует проставить, представлены в табл.1.5. Нет сигнала Заголовок 2750 мкс Единица 1100 мкс Ноль 550 мкс Ноль 550 мкс 550мкс Проверка 550 мкс 550 мкс ит.д. 8 бит Рис. 1.49. Схема сканирования бит ИК- команды
Схема и проrрамма модуля приема ИК-комс;1нд 139 Рис. 1.50. Заполнение SCLWorkЬook Таблица 1 .5. Задание временных интервалов в сценарии ИК-команды Time RA6 Мои пометки (в книrе) 10000 о Через 1000 мкс приходит заголовок RA6 = О 12750 1 Через 2750 мкс заголовок заканчивается RA6 = 1 13300 о Через 550 мкс приходит 7-й бит (единица 1100 мкс) 14400 1 Перебивка 550 мкс 14950 о Ноль 550 мкс 6-й бит 15500 1 Перебивка 550 мкс 16050 о Ноль 550 мкс 5-й бит 16600 1 Перебивка 550мкс 17150 о Ноль 550 мкс 4-й бит 17700 1 Перебивка 550 мкс 18250 о Ноль 550 мкс 3-й бит 18800 1 Перебивка 550 мкс 19350 о Ноль 550 мкс 2-й бит 19900 1 Перебивка 550мкс 20450 о Ноль 550 мкс 1-й бит 21000 1 Перебивка 550 мкс 21550 о Ноль 550 мкс 0-й бит 22100 1 Перебивка 550 мкс 47100 1 Пауза между командами 25 ООО мкс
140 Гnава • 1 Базовая версия ИК-команда имеет вид 10000000 или 80h. Теперь нужно сохранить Workbook и, щелкнув кнопку Generate SCL From Workbook (Генерировать SCL из рабочей тетради), сохранить .sсl-файл. Для использования этой имита­ ции ИК-команды в Simulus Controller необходимо щелкнуть кнопку Attach (Прикрепить), указав сохраненный прежде .sсl-файл. После сохранения Workspace все необходимое будет появляться при загрузке проекта . Спасибо создателям программы МРLАВ, которые позабо­ тились о возможности работы с портами ввода-вывода в раз­ ных их применениях! Теперь я собираюсь проделать следующее: при активиза­ ции RАб я перейду к функции обработки ИК-команды : • пропускаем заголовок; • пропускаем перебивку в 550 мкс; • при активизации RАб приходящим битом запустим «Ожи­ далку» на 560 мкс (немного длиннее импульса в 550 мкс), после которой проверим состояние ввода RАб; если это ноль, бит «1», если единица, - бит «О» (на схеме сканиро­ вания это обозначено словом «Проверка»); • если единица, еще раз включим «ожидалку», если ноль, не будем этого делать; • запишем бит в переменную IRCOMМAND, сдвинем вле­ во на одну позицию; • все это проделаем с 8 битами ИК-команды. Поскольку я человек ленивый, моя «Ожидалка» самая про­ стая: for (i =О; i<560; ++i); 11 Ждем-с Было ли это наказанием за лень, или я не справился с на­ стройками сценария, но, промучившись несколько <~асов, вы­ яснил, что во время выполнения цикла for сценарий подхва­ тывает циклы команды и успевает выполниться весь, прежде чем осуществляется выход из цикла ожидания. Я пробовал в качестве единиц измерения 11me Units и циклы (сус) и мкс (us) - не помогло. Конечно, хорошо бы выяснить, в чем проблема, но единож­ ды наказанный за лень, я решил из двух зол выбрать меньшее,
Схема и программа модуля приема ИК-команд 141 организовав «ожидалку» на таймере, как это и положено. Пока я, чертыхаясь, пытался оживить программу с циклом for, я заметил, что цикл while не мешает работе сценария. В конечном счете, эта часть программы (в состоянии про­ верки) получилась следующей: #include <piclбf62xa.h> #include <Stdio . h> #include "ir_rec.h" unsigned char input; регистра. int РНОТОСОМЕ = О; int МOD_ADDR; int IRCOММAND = О ; unsigned char getch() { / / Считываем содержимое приемного 11 Флаг активности фотоприемника. //Заданный адрес мо.цуля, как число . while(!RCIF) continue; return RCREG; //Устанавливается, когда регистр не пуст. // Вывод одного байта. void putch(unsigned-char Ьуtе) { PORTB = 1; //Переключим драйвер RS485 на передачу. TXEN = 1; //Разрешаем передачу. while (!TXIF) / / Устанавливается, когда регистр пуст . conti nue; TXREG =byt e; int init_comms () { PORTA = ОхСО; CMCON = Ох7; TRISA = ОхСО; TRISB = ОхFб; RCSTA = Ох90; TXSTA = Ох4; SPBRG = Охlб ; INГCON=O; / / PORTB = О; 11 Инициализация мо.цуля. /./ Настройка порто в А и В. //Настройка приемника . //Настройка передатчика. //Настройка режима приема-передачи. Запретить прерывания . / / Выключим передатчик драйвера RS485 .
142 Глава 8 1 Базовая версия PIEl = О; 11 Настройка таймера 1, запрет прерывания. TlCON = О; 11 Выбор внутреннего генератора, бит 1 в ноль. } int ir_cma () intЬ О; while ((PORTA&Ox40)== 0) continue;// Ждем окончания заголовка. for (Ь=О; Ь<В;++Ь) // Обработаем наши импульсы . { while ((PORTA&Ox40) !=О) continue; //Дождемся импульса. "1". бит. tirne (); / / Включаем таймер 1. while ( !ТМRlIF); 11 дождемся такта. TlCON = ОхО; 11 Выключаем таймер. ТМRlIF = ОхО; 11 Сбросим флаг. if ( (PORTA&Ox40) == 0) 11 Если НИЗКИЙ уровень, то IRCOММAND = IRCOММAND +1; / / Запишем это. tiщe (); 11 Включаем таймер 1. while ( !ТМRlIF); / / Дождемся такта. TlCON = ОхО; //Выключаем таймер. ТМRlIF = ОхО; //Сбросим флаг. } else //Высокий уровень, значит ·о·. { IRCOММAND = IRCOММAND +О; } IRCOММAND = IRCOММAND<<l; //Запишем это. //Сместимся влево на //Уехали мы в смещениях на бит далеко, поэтому IRCOММAND = IRCOММAND>> l; //сместимся вправо на бит. int crnd() { РНОТОСОМЕ = О; input = getch () ; 11 switch (СОММАND =getch())
Схема и программа модуля приема ИК-команд 143 // case "N": rel_on (REL_NUМ); 11 break; 11 case "F": rel_off (REL_NUМ); 11 break; 11 case • S •: rel_stat (REL_NUМ) ; 11 break; // } } void time(} { ТМRlН = OxFD; //Установка числа циклов до переполнения. ТМRlL = ОхА7; // FFFF минус 600 (258h). TlCON = Oxl; //Включение таймера. void main (void) / / Начнем работать. { init_comms (); / / Инициализация моцуля. //Прочитаем и преобразуем номер моцуля. MOD_ADDR = PORTB; // Номер МОдУЛЯ в старших битах. MOD_ADDR=MOD_ADDR»4; 11 Сдвинем на четыре бита. start: if (PORTA&Ox40) РНОТОСОМЕ =О; //Нет ИК сигнала. if (!(PORTA&Ox40)) РНОТОСОМЕ = 1; //Появился ИК­ сигнал. while (РНОТОСОМЕ == 1) { ir_cmd (); break; } 11 Обработаем ИК команцу. //Нет ИК-сигнала, проверим сеть. input = getch(); while (input == MODULNAМESIM) { cmd (); break; goto start;
144 Глава • 1 Базовая версия Все это получилось не сразу, но, вроде бы, заработало. Те­ перь осталось проверить программу с другими вариантами ИК-кода. Например, с командой 00100000, или 20h. 10000 О Через 1000 мкс приходит заголовок RA6=0 12750 1 Через 2750 мкс заголовок заканчивается RA6=1 13300 о Через 550мкс приходит 7й бит 13850 1 Перебивка 550 мкс 14400 о Ноль 550 мкс 6й бит 14950 1 Перебивка 550 мкс 16050 о Единица 1100 мкс 5й бит 17150 1 Перебивка 550 мкс 17700 о Ноль 550 мкс 4й бит 18250 1 Перебивка 550 мкс 18800 о Ноль 550мкс 3 бит 19350 1 Перебивка 550 мкс 19900 о Ноль 550 мкс 2 бит 20450 1 Перебивка 550 мкс 21000 о Ноль 550 мкс 1 бит 21550 1 Перебивка 550 мкс 22100 о Ноль 550 мкс Ой бит 22650 1 Перебивка 550 мкс 47650 1 Пауза меж.цу командами 25000 мкс С комаНдой 10000011, или 83h: 10000 о Через 1000 мкс приходит заголовок RA6=0 12750 1 Через 2750 мкс заголовок заканчивается RA6=1 13300 о Через 550 мкс приходит 7-й бит (единица 1100 мкс) 14400 1 Перебивка 550 мкс 14950 о Ноль 550 мкс 6-й бит 15500 1 Перебивка 550 мкс 16050 о Ноль 550 мкс 5-й бит 16600 1 Перебивка 550мкс 17150 о Ноль 550 мкс 4-й бит 17700 1 Перебивка 550 мкс 18250 о Ноль 550 мкс 3-й бит 18800 1 Перебивка 550 мкс 19350 о Ноль 550 мкс 2-й бит 19900 1 Перебивка 550мкс 20450 о Единица 1100 мкс 1-й бит 21550 1 Перебивка 550 мкс 22100 о Единица 1100 мкс 0-й бит 23200 1 Перебивка 550 мкс 48200 1 Пауза между командами 25000 мкс
Схема и проrрамма модуля приема ИК-команд 145 И можно двигаться дальше. Предстоит добавить обработ­ ку запросов по системной сети, преобразование позиционно­ го кода ИК-команды в символьный вид. Функцию обработки запросов по системной сети, подправив, я возьму из версии программы для предыдущего модуля. Можно слегка изменить и сценарий имитации работы фотоприемника, добавив задание адреса модуля (пусть он пока остается «03») и подключение к порту А фотоприемни­ каRАб=1. Для этого в Workbook SCL Generator кнопкой Click here to Add Signals добавим еще три столбца: RВ4, RВ5 и PORTA, а в конце (как в табл. 1.5 .) - информацию, представленную в табл.1.6. Таблица 1.6 . Добавление к таблице време-ых интервалов Тlme RA6 RВ4 R85 РОRТА Мом пометки (в книrе) 10000 о Через 1ООО мкс приходит заголовок, Rдб=О и т.д. 47100 1 Пауза между командами 25000мкс 5 1 1 40 Начальная инициализация адреса фо~оприемника Теперь при запуске программы будет задан адрес модуля, и фотоприемник установит вывод RАб в «l». В итоге получилась (не слишком аккуратная) следующая программа: #include <piclбf62xa.h> #include <stdio.h> #include "ir_rec .h" unsigned char input; регистра. / / Считываем содержимое приемного 11 Первый символ адреса модуля. 11 Второй символ адреса модуля. unsigned char MOD_SIMl; unsigned char MOD_SIM2; unsigned char IRSIMl; unsigned char IRSIМ2; unsigned char IRSIMЗ; int РНОТОСОМЕ = О; 11 Флаг активности фотоприемника .
146 Глава• 1 Базовая версия int MOD_ADDR; int IRCOММAND = О; int sirnl_num = О; int sirn2_num = О; 11 Заданный адрес МОдУЛЯ, как число. int sirn_end_num = О; int MOD_NUМ; //Полученный адрес модУЛЯ, как число. unsigned char getch() { while(!RCIF) continue; return RCREG; //Устанавливается, коrда реrистр не пуст. //Вывод одноrо байта. void putch(unsigned char Ьуtе) { PORTB = 1; / / Переключим драйвер RS485 на передачу. TXEN = 1; //Разрешаем передачу. while( !TXIF) // Устанавливается, коrда реrистр пуст. continue; TXREG = Ьуtе; int ini t_cornrns ( ) { PORTA = ОхСО; CMCON = Ох7; TRISA = ОхСО; TRISB = ОхFб; RCSTA = Ох90; TXSTA = Ох4; SPBRG = Охlб; INТCON=O; PORTB = О; PIEl = О; TlCON = О; //Инициализация модУЛя. //Настройка портов А и В. //Настройка приемника. 11 Настройка передатчика. 11 Настройка режима приема-передачи. 11 Запретить прерывания. 11 Выключим передатчик драйвера RS485. //Настройка таймера 1, запрет прерывания. 11 Выбор внутреннеrо rенератора, бИт 1 в ноль. / / Определим номер модУля. MOD_ADDR = PORTB; / / Номер МОдУЛЯ в старших битах. MOD_ADDR=MOD_ADDR»4; / / Сдвинем на четыре бита. } 11 Преобразуем символьный адрес в число.
Схема и программа модуля приема ИК-команд 147 int sim_num_adr () { sim_end_num = О; siml_num = getch(); MOD_SIMl = siml_num; s.j.m2_num = getch( ) ; MOD_SIM2 = sim2_num; siml_num = siml_num - sim2_num = sim2_num - //Чтение первого символа номера. //Сохраним первый символ. //Чтение второго символа номера. / / Сохраним второй символ. ОхЗО; ОхЗО; sim_end_num = siml_num*OxOA + sim2_num; return sim_end_num; int ir_cmd () intЬ=О; while ((PORTA&Ox40)== 0) continue;// Ждем окончания заголовка. for (Ь=О; Ь<В;++Ь) { //Обработаем наши импульсы. while ((PORTA&Ox40) !=О) continue; //Дождемся импульса. "1". time (); while ( !ТМRlIF); TlCON = ОхО; ТМRlIF = ОхО; 11 Включаем таймер 1. //Дождемся такта. 11 Выключаем таймер. / / Сбросим флаг. if ( (PORTA&Ox40) == О) / / Если низкий уровень, то IRCOММAND = IRCOММAND +1; // Запишем это. time (); / / Включаем таймер 1. while ( !ТМRlIF); // Дождемся такта. TlCON = ОхО; //Выключаем таймер. ТМRlIF = ОхО; //Сбросим флаг. } else // Высокий уровень, значит "0". { IRCOММAND = IRCOММAND +О; } IRCOММAND = IRC0ММAND<<l; 11 Запишем это. //Сместимся влево на бит. / / Уехали мы в смещениях на бит далеко, поэтому IRCOММAND = IRCOММAND»l; //сместимся вправо на бит.
148 Глава • 1 Базовая версия РНОТОСОМЕ = О; int cmd() MOD NUМ = sim_num _adr () ; //Чтение из сети (файла) . if (MOD_NUМ == MOD_ADDR) / / Если наш адрес МОдУЛЯ. { input = getch(); if (input == "$ ") // Если символ команды. { while ((input = getch())!= "S"); /1 Ждем. ir_stat{); } void time() { ТМRlН = OxFD; //Установка числа циклов до перепоШiения. ТМRlL = 0хА7; // FFFF минус 600 (258h). TlCON = Oxl; / / Включение таймера. int ir_stat() int ircom; int ircoml; int ircom2; int ircomЗ; ircom = IRCOММAND; 11 Преобразуем коман,цу в символы . ircoml = ircom/Ox64; IRSIMl = ircoml + ОхЗО; ircom2 = (ircom - ircoml*Ox64)/0xA; IRSIM2 ircom2 + ОхЗО; ircomЗ = (ircom - ircoml*Ox64 - ircom2*0xA); IRSIMЗ = ircomЗ + ОхЗО; putch("C"); putch(МOD_SIMl); putch (МOD_SIМ2) ; if (IRCOММAND == 0) 11 Команда не менялась.
Схема н программа модуля nрнема ИК-команд 149 putch("#"); putch( • f •); putch(•f •); putch(OxOA) ; 11 Тольхо для ВШ1ода в файл! 1!111 } else //За время между двумя запросами пришла ИК команда. { putch(IRSIMl); putch !IRSIМ2) ; putch ( IRSIМЗ) ; putch ( ОхОА) ; / / Тольхо для вывода в файл1! 11 ! ! } IRCOММAND = О; / / Мы передали ИК команду, она нам больше не нужна. } void main(void) { 11 Начнем работать. init_comms ( ) ; / / Инициал.1.зация модуля. / / Прочитаем и преобразуем номер модуля. MOD_ADDR = IORTB; // Номер модуля в старших битах. МOD_ADDR=MOD_ADDR»4; / / Сдвинем на четыре бита . //Начинаем работать start: if (IORTA&Ox40) РНОТОСОМЕ = О; //Нет ИК-сигнала. if (!(IORTA&Ox40)) РНОТОСОМЕ = 1; //Появился ИК­ сигнал. while (РНОТОСОМЕ == 1) { 11 Обработаем ИК-команду. ir_cmd (); break; } 11 Нет ИК-сигнала, проверим сеть. input = getch(); while(input == MODULNAМESIM) // Если в сети обращение к модулю. { cmd (); break; goto start; //Обработаем сетевую команду.
150 Глава • 1 Базовая версия В настоящий момент меня уже одолевают сомнения . Пока активность в сети не мешает приему ИК-команд. Не будет ли она мешать, когда появится функция обработки запросов? Можно попытаться рассчитать это, но расчеты могут оказать­ ся достаточно сложными. И не будет ли мешать прием ИК­ команд системным запросам? Не стану считать, попробуем, посмотрим. В крайнем случае, если не забуду, в основной программе системы при отсылке запроса о состоянии модуля ИК-прием­ ника, сделаю паузу и при отсутствии ответа повторю запрос. Есть и еще одно сомнение - не будет ли в реальных усло­ виях неправильно считываться ИК-команда? Здесь тоже мож­ но что-нибудь придумать. Например, повторять системную команду трижды, а в модуль добавить три считывания , при­ нимая в качестве команды ту, которая совпадает дважды. На данном этапе я предпочту отложить решение проблем до момента их появления, хотя, как мне кажется, самое время обо всем позаботиться. Работа выше приведенной программы происходит при input.txt такого вида: "R03$0N" "R01$0N" "C03$0S" Опция Rewind Input на странице Uartl 10 установлена. В результате имитация сетевых команд постоянно «крутит­ ся», принимая три команды, последняя из которых запраши­ вает состояние модуля фотоприемника. Результат работы программы выводится, как и раньше, в файл output.txt: COЗ#ff// Команда не менялась С03131// Пришла команда 131 (десятичная) или 10000011 двоичная COЗ#ff //Команда не менялась после последнего запроса COЗ#ff// Команда не менялась COЗ#ff// Команда не менялась
Схема и программа модуn11 приема ИК-команд 151 По дороге я еще раз наступил на грабли. Внеся исправления в программу, я обнаружил, что она не желает работать. Во вся­ ком случае, работать так, как мне хочется. Пытаясь понять, в чем дело, я много раз просматривал программу, пока не обна­ ружил, что один из операторов имеет тот же цвет, что и ком­ ментарий. Как это получилось? Я использую много одностроч­ ных комментариев (тоже следствие лени) и если в конце строчного комментария не нажат ввод при удалении промежут­ ков между операторами программы, следующий воспринима­ ется программой как продолжение комментария. Чтобы частично развеять сомнения, я хочу переделать программу для тестирования: • проверить, правильно ли будет работать программа, если после первой ИК-команды вторая придет через 50 мс; • проверить, много ли запросов о состоянии модуля про­ пускается, если это происходит. Для этого в папке, где лежат все проекты, я создам еще одну папку, которую обозначу, добавив _test к имени. Скопи­ рую туда содержимое папки модуля приемника ИК-команд. Переименую все файлы, добавив _test (исключая файлы input и output). Затем открою этот проект в программе МРLАВ, настрою, добавлю в сценарий второй ИК-код, счетчики и по­ пробую ответить на два вопроса, которые задаю себе сейчас. nередепк• В раздел переменных добавим (я использую глобальные пе­ ременные, чтобы их легче было отслеживать, поскольку ло­ кальные переменные до обращения к функциям не видны): int COUNTER = О; А в основной программе - счетчик после вызова команды обработки сетевых команд: /* Нет ИК-сигнала, проверим сеть*/ input =getch{); while{input == MODULNAМESIM) / / Если в сети обращение к мо.цулю.
152 Глава • 1 Базовая версия crnd (); ++cooNТER; break; goto start; 11 Обработаем сетевую командУ. Результат эксперимента - за время прохождения двух ИК­ команд (83hи 20h) счетчик досчитал до 5. Файл input.txt, который «крутится» без перерывов выгля­ дит так: "R 03$0N" "R 0 1$0N" " C 03$0S" Обращение к модулю приемника ИК команд "R 03$0N" "R 01$0N" " C0 3$0S" Обращение к модулю приемника ИК команд Файл output.txt получился следующим: COЗ#ff Команда не обновлялась С03131 Команда 131 (83h) СОЗ#ffКоманда не обновлялась COЗ#ff Команда не обновлялась С03032 Команда 32 (20hJ Таким образом: • ИК-команды не потерялись за непрерывно следующи· ми сетевыми командами; • ИК-команды прочитались правильно; • между приходами ИК-команд запрос статуса правильно отображал отсутствие обновления. Посмотрим, как это все выглядит во времени. Первая ИК-команда приходит через 10 мс и заканчивает­ ся через 24 мс, вторая приходит через 60 мс и заканчивается через 73 мс после начала работы. Сетевые команды начина­ ют поступать сразу после начала работы . Каждая сетевая ко­ манда занимает около 6,3 мс (имеет 60 бит, проходящих со скоростью-9600 бит/с). До начала ИК-команды при такой скорости должна прой­ ти одна сетевая кома!_lда. За время считывания первой
Схема и программа модуnя приема ИК-команд 153 ИК-команды ((1О мс - 6 мс) + 24 мс) = 28 мс пройдет 4 команды. После завершения первой и до конца второй пройдет 73 мс - 24 мс= 49 мс, что соответствует 7-8 командам. Таким образом, за все время пройдет 12-13 команд. То есть, файл input прочи­ тается дважды или немного более. Что дает 4-5 обращений к модулю приемника ИК-команд. Файл output фиксирует 5 обра­ щений, счетчик фиксирует 5 обращений. Для большей уверенности посмотрим, как распределяют­ ся сетевые обращения: • за время от начала работы до завершения считывания ИК-команды проходит 5 системных запросов, среди которых один к ИК-приемнику; • в выходном файле этому соответствует один ответ об отсутствии обновления команд; • следующая команда во входном файле это запрос к моду­ лю; • в выходном файле на втором месте стоит ответ о при­ ходе команды 131 (к этому моменту считывание первой команды завершено); • до завершения считывания второй комаI:Щы проходит семь системных команд, среди которых два обращения к модулю приемника; • в выходном файле два ответа - команда не обновлялась (предыдущая уже передана); • следующая сетевая команда - запрос о состоянии моду­ ля приемника, который следует сразу за завершением считывания ИК-команды , ответ - команда 32 в выход­ ном файле. Если я ничего не напутал, даже при короткой основной программе (центрального управляющего устройства), когда запросы о состоянии модуля приемника идут достаточно час­ то, ответ успевает доходить до адресата. Если учесть, что в тестовом варианте две команды проходят с интервалом в 36 мс, что в 10-30 раз быстрее реально отправляемых команд - (интервал между двумя нажатиями на одну и ту же клавишу составляет от 0,3 до 1 с), то запас, я думаю, есть. Конечно, мои подсчеты не страдают излишней продуман­ ностью и точностью, но я на время решил успокоиться.
154 Глава • 1 Базовая версия Отnадка модуnя Прототип я делаю на той же макетной плате, на которой со­ бирал релейный модуль. По этой причине я включаю фото­ приемник на вход RВ3. Для индикации приема ИК-команд дополнительно использую вывод RAO, к которому уже под­ ключен светодиод. Когда устанавливается флаг прихода ИК­ команды, светодиод включается. Флаг снимается - светодиод выключается. if (! (RВЗ&Ох01)) { РНОТОСОМЕ = 1; RAO = OxOl; else РНОТОСОМЕ = О; RAO = ОхОО; Вот и очередные «грабли»! Приоритет приема ИК-команд хорошо бы закрепить одно­ значно. Например, так: while((!RCIF)&(RВЗ == 1)) /*устанавливается, когда регистр не пуст*/ continue; return RCREG; Я выделил добавленный фрагмент. У прототипа фотопри­ емник подключен к выводу RВ3. Смысл добавленного фраг­ мента в том, что на сетевые запросы ответ будет, если модуль не занят приемом ИК-команд, то есть RВ3 = 1. Неплохо было бы защитить модуль от помех по RB3. При включении может «проскочить» короткий нулевой импульс (на чем я и споткнулся), и модуль перейдет в режим приема ИК-команды, которой нет. Поправил я это так: start: if (RВЗ&Ох01) //Нет ИК сигнала .
break; } РНОТОСОМЕ = О; RAO = ОхОО; if (!(RВЗ&Ох01)) { Отладка модуля 1 55 11 Появился ИК сигнал. for (k=O; k<ЗО; ++k); //Поставим задержку. if (!(RВЗ&Ох01)) //ИК сигнал не пропал? { else РНОТОСОМЕ = 1; RAO = OxOl; РНОТОСОМЕ = О; RAO = ОхОО; break; Я добавляю задержку, а затем еще раз проверяю наличие активности фотоприемника. Короткий случайный импульс проскочит за время задержки, а длинный импульс команды приведет механизм считывания в действие. Помогло. Если в первый раз после включения питания (сразу или через не­ сколько секунд) модуль «подвисал» на приеме ИК-команды, то после исправления перестал. Итак, модуль получает команду. Возможно, распознает ее. Он даже передает ее по запросу через RS485. А что получит­ ся, если команда не единичная, то есть в том случае, когда идет поток одинаковых команд? Что будет, если команды не системные, а чужие? Не знаю. Первое, что приходит в голову- запустить еще один тай­ мер сразу после завершения считывания ик~команды. И пока он не завершит отсчет времени больший, чем занимают 2-3 команды, не принимать ИК-коды. Попутно я пытаюсь воспро­ извести код, аналогичный тому, что использовал в отладчи­ ке МРLАВ, из программы WinLIRC, аппаратный модуль ко­ торой имеет излучающий светодиод. Проходит два дня. Результаты не впечатляют. Коды про­ читываются не слишком уверено. Я увеличиваю интервал сканирования с 600 до 700 мкс, но совсем не удовлетворен
156 Глава • 1 Базовая версия стабильностью работы модуля. В отличие от релейного, мо­ дуль приема системных ИК-команд мне совсем не нравится. Он, вроде бы, работает, но... В конечном счете, я меняю излучатель кодов. Использую оригинал - старый пульт от видеомагнитофона Sony. Меняю второй таймер на обычный цикл в команде считывания ко­ дов (выделено в тексте программы), попутно решаю внести исправления в сдвиг на один бит. У меня получился лишний сдвиг, который я после получения ИК-команды убирал обрат­ ным сдвигом. После замены переменной IRCOMMAND с типа int на unsigned char я стал терять старший бит. . Замена всех этих «Шатаний из стороны в сторону» оказа­ лась простой (изменение выделено). Если я не ошибаюсь, это­ го достаточно. int ir_cmd () intЬ О; while (RВЗ == 0) continue; //Ждем окончания заголовка. for (Ь=О; Ь<8; Ь++) //Обработаем наши импульсы. { while (RВЗ != 0) continue; //Дождемся импульса. time () ; 11 Включаем таймер 1 . while ( !ТМRlIF); // дождемся сброса таймера. TlCON = ОхО; 11 Выключаем таймер. ТМRlIF = Ох О; 11 Сбросим флаг. if (RВЗ == 0) //Если низкий уровень, то " 1" . { IRCOММAND = IRCOММAND +1; 11 Запишем это. time (); //Включаем таймер 1. while ( !ТМRlIF); / / Дождемся сброса таймера. TlCON = ОхО; 11 Выключаем таймер. ТМRlIF = ОхО; 11 Сбросим флаг. } else // Высокий уровень , значит "0". IRCOММAND = IRCOММAND; 11 Запишем это. if (Ь<7) IRCOММAND = IRCOММAND<<l; //СИестиися влево на бит. РНОТОСОМЕ = ОхО;
RAO = ОхО; RAl=Oxl; Отладка модуля 157 for (m=O; m<З; ++m) // Перестанем ;принимать ИК-ходы. for (1=0; 1<10000; ++1); RAl = ОхО; Здесь на выводе порта А RAl я использую еще один свето­ диод, чтобы видеть окончание команды . В результате модуль хорошо распознает команды от пуль­ та видеомагнитофона. Чувствительность высокая, распозна­ вание стабильное (рис.1.51). Рис. 1.51 . Прием ИК-кодов модулем Не удовлетворяют меня только два момента: • иногда во время паузы между приемами ИК-команд зап­ рос по сети «подвешивает» модуль в нераспознанном месте (помогло сокращение времени этой паузы); • коды с пульта плохо согласуются с моими ожиданиями. .
158 Глава • 1 Базовая версия Вот сравнение кодов, прочитанных с помощью WinLIRC в режиме распознавания, и кодов, которые транслирует мо­ дуль в ответ на запрос по сети RS485: Номер канала 1. Модуль возвращает номер команды 001 - 00000001 (С14001 - в ответ на запрос статуса). 7F2h - 11111110010 (инверсия 00000001101), без послед- них трех бит 0000001. Номер канала 2. Прочитано модулем 129 - 10000001 3F2h - 01111110010 (инверсия 10000001101), без послед- них трех бит 10000001. Номер канала 3. Прочитано модулем 65-1000001 5F2h - 10111110010 (инверсия 01000001101), без послед- них трех бит 1000001 Номер канала 6. Прочитано модулем 161 - 10100001 2F2h - 01011110010 (инверсия 10100001101), без послед- них трех бит 10100001. Номер .канала 9. Прочитано модулем 017 - 10001 772h - 11101110010 (инверсия 00010001101), без послед- них трех бит ООО 1ООО1. power. Прочитано модулем169- 10101001 2B2h-1010110010 (инверсия 0101001101), без последних трех бит 0101001. Команда включения канала 1 в записи WinLIRC- 7F2h, но я определяю единицу и ноль, как это описано в технической информации о кодах Sony, которой располагаю, а в WinLIRC сделано наоборот. Можно инвертировать код. Кроме того, я использую 8-битовый код, а оригинальный код - 11-битовый. Тоже не страшно, отбросим три последних бита. Смущающим меня обстоятельством служит то, что команды каналов 1 и 2 не совпадают, как я ожидал после превращений с инверсией и отбрасыванием. Аналогичная история с командой power. Пока я не понимаю, как это происходит.
Отладка модуля 159 Шутка калькулятора, который отбрасывает первые нули! Но понял я это позже. Последнее, что я делаю, измученный борьбой с «собствен­ ной гениальностью», - проверяю работу модуля в заготовке под среду программирования. Модуль работает. Я использую два кода: номер включения канала 1 - для тестирования ко­ манды, а канала 2 - для включения лампы. Оба кода стабиль­ но работают. Думаю, пока следует остановиться . Основная задача - получить модуль считывания системных команд, которые стабильно распознавались бы системой, достигнута. При этом, как это и планировалось, используется старенький пульт от видеомагнитофона. А если что-то осталось непо­ нятно, что ж... Будем надеяться, что это позже прояснит­ ся (рис. 1.52). Рис. 1.52. Работа модуля с основной программой
160 Глава 8 ' 1 Базовая версия Самым непонятным для меня оказалось то, что попытка ис­ пользовать третий светодиод для индикации включенного мо­ дуля - я несколько раз вытаскивал микросхему из панельки без отключения питающего напряжения - успехом не увенча­ лась. Я попробовал разные варианты включения. Ничего не получилось! Мистика!? В данный момент программа модуля приема системных кодов получилась такой. Файл заголовка: #define MODULNAМESIM ·с· unsigned char getch(void); • int init_camms () ; int ir_cmd () ; int crnd (); void time () ; void time_cmd(); int ir_stat () ; Файл основной программы: #include <piclбf62xa.h> #include <stdio.h> #include "ir_rec _Ol.h" unsigned char input; / / Считываем содержимое приемного регистра. unsigned char MOD_SIMl; / / Первый символ адреса мо.цуля. unsigned char MOD_SIМ2; / / Второй СИМВОЛ адреса МОдУЛЯ . unsigned char IRSIMl; unsigned char IRSIМ2; unsigned char IRSIMЗ; unsigned char command_reciev [6]; //массив для полученной команды . int РНОТОСОМЕ =О; //Флаг активности фотоприемника. int МOD_ADDR; //Заданный адрес мо.цуля, как число. unsigned char IRCOММAND = О; int siml_num = О; int sim2_num = О; int sim_enQ..num = О; int OOD_NUМ; // Полученный адрес мо.цуля, как число.
int i; int k; int 1; int ~; unsigned char getch() { while{ ( !RCIF!&!RВЗ continue; return RCREG; Отладка модуля 161 1)) 11 Когда регистр не пуст . //Вывод одного байта. void putch(unsigned char Ьуtе) { while{!TXIF) continue; TXREG = byte; 11 Когда регистр пуст . int init_comms {) { //Инициализация модУЛЯ . PORTA = ОхОО; CMCON = Ох7; TRISA = ОхОО; TRISB = OxFE; //Настройка портов А и В. PCON = OxFF; RCSTA = ОЬ10010000; ТХSТА = ОЬ00000110; SPBRG = Ох68; N,8,1. //Тактовая частота 4 МГц. / /Настройка приемника. //Настройка передатчика. //Настройка режима приема-передачи 2400, INТCON = ОхО; RBO = ОхО; PIEl = ОхО; TlCON = ОхО; ноль. //Запретить прерывания. //Выключим передатчик драйвера RS485. 11 Настройка таймера 1, запрет прерывания. //Выбор внутреннего генератора, бит 1 в ТМRlН = ОхОО; ТМRlL = ОхОО; IRCOММAND = ОхО; MOD_J\DDR = PORTB; МOD_ADDR=МOD_J\DDR>>4; } //Обнулим таймер. /* Определим номер модУля */ //Номер модУля в старших битах. //Сдвинем на четыре бита. //Преобразуем символьный адрес в число. int sim_nurn _adr()
162 Глава • 1 Базовая версия sim_end_num = ОхО; MOD_SIMl = command_reciev [1]; MOD_SIМ2 = command_reciev [2]; MOD_SIMl = MOD_SIMl - ОхЗО; //Первый символ номера . //Второй символ номера . MOD_SIM2 = MOD_SIM2 - ОхЗО; sim_end_num = MOD_SIMl*OxOA + MOD_SIM2; return sim_end_num; int ir_cmd () intЬ=О; while (RВЗ == 0) continue; // Ждем окончания заголовка . for (Ь=О; Ь< 8 ; Ь++) //Обработа ем наши импульсы. { while (RВЗ != 0) continue; //Дождемся импульса. time (); / / Включаем таймер 1. · while ( !ТМRlIF) ; / / Дождемся сброса таймера. TlCON = ОхО ; / / ВЫключаем таймер. ТМRlIF = ОхО ; / / Сбросим флаг. if (RВЗ == 0) // Если низкий уровень , то •1 • . { IRCOММAND = IRCOММAND +1; / / Запишем это. time () ; / / Включаем таймер 1. while ( !ТМRlIF); // дождемся сброса. TlCON = ОхО; //Выключаем таймер . ТМRlIF = ОхО; //Сбросим флаг. }else //Высокий уровень, значит •о•. IRCOММAND = IRCOММAND; / / Запишем это. if (h<7) IRCOММAND = IRCOММAND<<l; //Сместимся влево на бит. } РНОТОСОМЕ = ОхО; RAO = ОхО; RAl=Oxl; for (m=O; m<З; ++m) //Перестанем принимать ИК. for (1=0; 1<10000; ++1); RAl = ОхО;
Отладка модуля 163 int cmd() { if (command_reciev [5] •s• J ir_stat (); void time () / / Таймер 1 для чтения ИК. { ТМRlН = OxFD; //Установка числа циклов до переполнения. ТМRlL = Ох43; // FFFF минус 700 (2BCh). TlCON = Oxl; //Включение таймера. int ir_stat () { int ircom; int ircoml; int ircom2; int ircomЗ; command_rec iev[O] =•с•; command_reci ev [l] = MOD_SIMl+OxЗO; command_reciev[2] = MOD_SIМ2+0x30; ircom = IRCOММAND; //Преобразуем команду в символы . ircoml = ircom/Ox64; IRSIMl ircoml + ОхЗО; ircom2 (ir com - ircoml*Ox64J/0xA; IRSIM2 i rcom2 + ОхЗО; ircomЗ IRSIМЗ (ircom - ircoml*Ox64 - ircom2*0xA); ircomЗ + ОхЗО; if (IRCOММAND == 0) { command_reciev[З] command_reciev[4] command_reciev[5] "# "; //Команда не менялась . "f" i "f"·; CREN =ОхО; RBO = Oxl; 11 Запрещаем прием. //Переключим драйвер RS485 на передачу. TXEN = Oxl; / / Разрешаем передачу. for (i=O; i<б; ++i) putch(command_reciev[i));
164 Глава 8 1 Базовая версии for (i=O;i<lOOO;i++); 11 Задержка для вывода. for (i=O; i<б; ++i) command_reciev [i] =" "; RВО = ОхО; //Выключаем драйвер RS485 на передачу. TXEN = ОхО; CREN =Oxl; 11 Запрещаем передачу. 11 Разрешаем прием. else //За время междУ двумя запросами пришла ИК команда. { coпunand_reciev[З] command_reciev[4J command_reciev[5] IRSIMl; IRSIМ2; IRSIМЗ; CREN =ОхО; RВО = Oxl; 11 Запрещаем прием. //Переключим дРайвер RS485 на передачу. TXEN = Oxl; / / Разрешаем передачу. for (i=O; i<б; ++i) putch(canmand_reciev(i]); for (i=O;i<lOOO;i++); //Задержка для вывода. for (i=O; i<б; ++i) command_reciev [i] =" "; RBO = ОхО; //Выключаем дРайвер RS485 на передачу. ТХЕN = ОхО; //Запрещаем передачу. CREN =Oxl; //Разрешаем прием. } IRCOММAND = Ох О; / / Мы передали командУ , она больше не нужна. } void main (voidJ { 11 Начнем работать. init_comms (); //Инициализация МОдУЛЯ. for (i=O; i<б; ++i) command_reciev [i] =" "; command_reciev [О) = "С"; //Прочитаем и преобразуем номер модУля. MOD_ADDR = PORTB; // Номер МОдУЛЯ в старших битах. MOD_ADDR=MOD_ADDR>>4; //Сдвинем на четыре бита. RA2 = Oxl; / / Чтобы видно, что МОдУЛЬ включен. 11 Тах и ие получилось! ! //Начинаем работать. start: if (RВЗ) // Нет ИК-сигнала. { РНОТОСОМЕ = ОхО; RAO = ОхОО;
Отладка модуля 165 if ( !RВЗ) { //Появился ИК-сиrнал for (k=O; k<ЗO;++k); 11 Поставим задержку. if (!RВЗ) { //ИК-сигнал не пропал? else РНОТОСОМЕ = Oxl; RAO = OxOl; РНОТОСОМЕ = ОхО; RAO = ОхОО; while (РНОТОСОМЕ == 1) { 11 Обработаем ИК-коман.цу. ir_crnd (); break; } //Нет ИК-сигнала, проверим сеть. CREN =Oxl; input = getch(); switch (input) { case •с•: //Если обращение к фото модУлю. for (i=l; i<б; ++i) //Запишем комаНдУ в массив. { input = getch(); cornrnand_reciev [i] i nput; МOD_NUМ = sirn_nшn_adr () ; / / Чтение из сети. if (MOD_NUМ != MOD_ADDR) break; //Если не наш адрес . else if (cornrnand_reciev [3] = "$ ") crnd(); //Если команда. default: goto start; goto start;
166 Глава • 1 Базовая версия Схема и nроrрамма модуnR изпучени• ИК-кодов Модуль должен получать команду по сети и излучать ИК-код. В принципе, ИК-коды в «собственном формате» системы могут храниться в EEPROM (можно использовать внешнюю энергонезависимую память) . Если мы хотим превратить мо­ дуль И3Л}'Чения инфракрасных кодов в универсальный пульт ИК-управления, запоминающий коды других пультов, допол­ нительная внешняя память может оказаться обязательной составляющей. Для этой цели можно добавить к модулю фо­ топриемник и подпрограмму считывания-запоминания. Но вернемся к конкретной задаче (рис. 1.53). Ниже приведена таблица составляющих (табл. 1.7) . Таблица 1.7 . СnецификаЦИtl модуля излучения ИК-кодов NI 1 2 з 4 5 6 7 8 9 Обозначение Издепие Копичество Цена(р.) DD1 МАХ1483 1 96 DD2 PIC16F628A 1 100 DDЗ LM2936-Z5 1 68 VD1 АЛЗО7 1 з VD2 АЛ144А 1 20 С1, С2 0,1 мкФ 2 2 сз 100,0 мкФ 16В 1 5 R1, R2 1кОм0,25 Вт 2 1 RЗ-Rб 10 кОм 0,25 Вт 4 1 Ориентировочная стоимость элементов - 297 руб. Команды: Ixx$nP и байты данных, где n - количество повторов. Байты данных в файле input.irc на диске компьютера, за- писанные с помощью НЕХ-редактора: 020232Bl26SD262626SD262626SD2626262626SD 26SD262626SD2626FF
Схема и nроrрамма модуля излучения ИК-кодов 167 DD1В С1 DD2 14 Х17 1I7 б МАХ1483 4 В PIC16F628A 17 15 з6 5 F RB4 S1 RB5 iRB6 2 5 Рис. 1.53 . Принципиальная схема модуля излучения ИК-кодов Проrрамма модуnя изnучения ИК-кодов на языке С Фаiiп ~rоповка .#define MODULNAМESIM ·r· unsigned char getch(void); int init_comms (); int cmd (); void ir_tms (); Основной фаiiп #include <piclбf62xa.h> #include <stdio.h> #include "ir_trans_fnl.h" unsigned char input; / / Считываем содержимое приемного регистра. unsigned char MOD_SIМl; // Первый символ адреса модУля. unsigned char MOD_SIM2; // Второй СИМВОЛ адреса МОдУЛЯ. unsigned char command_reciev [6 ] ; // Массив для полученной команды.
168 Глава • 1 Базовая версия int MOD_ADDR; //Заданный адрес модУля, как число. int MOD_ADDR; / / Заданный адрес МОдУЛЯ, как число. int sim_end_num = О; int MOD_NUМ; // Полученный адрес модУля, как число. inti=О; unsigned char Ь = О; intс=О; intd О; intk=О; int1=О; intm=О; unsigned char ir_cmd [60]; команды. 11 Массив для прочитанной ИК- unsigned char getch() { while( !RCIF) continue; retum RCREG; //Устанавливается, когда регистр не пуст. int init_cornms () { PORTA = ОхО; СМСОN = Ох7; TRISA = ОхО; 11 Инициализация мо.цуля. //Настройка портов А и в. 11 Настройка приемника. //Настройка передатчика. TRISB = OxFE; RCSTA = ОЬ10010000; TXSTA = ObOOOOOllO; SPBRG = Ох68; RВО=О; 11 Настройка режима приема-передачи. //Выключаем драйвер RS485 на передачу. CREN =1; //Определим номер модУля. MOD_ADDR = PORTB; // Номер мо.цуля в старших битах. MOD_ADDR=MOD_ADDR>>4; //Сдвинем на четыре бита. for (i=O; i<бl; ++i) ir_cmd[i] = ОхОО; i =О; RA2=1; } //Преобразуем символьный адрес в число. int sirn_num_adr ()
Схема и программа модуля излучения ИК-кодоа 169 sim_end_num = О; MOD_SIMl = conunand_reciev [1]; //Первый символ номера. MOD_SIМ2 = command_reciev [2]; //Второй символ номера. MOD_SIMl =MOD_SIMl - ОхЗО; MOD_SIМ2 =MOD_SIM2 - ОхЗО; sim_end_num =MOD_SIMl*OxOA + MOD_SIМ2; return siщ__end_num; int cmd() i=O; / / Принимаем данные . while ( (input = getch()) != OxFF) { ir_cmd[i] = input; ++i; ir_cmd[i] void ir_trns () { 1=О; input; for (1 О; 1<4; ++1) { с3; while (ir_cmd[c] != OxFF) команды. { 11 Импульс. Ь = ir_cmd[c]; ++с; while {Ь != 0) RAl 1; RAl 1; RAl 1; RAl 1; RAl :: 1; RAl 1·. RAl 1; //Наш байт окончания
170 Глава • 1 Базовая версия RAl =1; RAl 1; RAl 1; RAl 1; RAl 1; RAl О; RAl О; --Ь; } 11 Пауза. ь = ir_cmd[c]; ++с; while (Ь != 0) { RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; RAl О; --Ь; for (m=O; m<1563; ++m); 11 Пауза в 25 мс. } for (i=O; i<бl; ++i) ir_cmd[i] = ОхОО; i =О; void main(void) { 11 Начнем работать. init_cOI1'[!lS (); 11 Инициализация модУnя. for (k=O; k<б; ++k) COI1'[!land_reciev [k] =" "; conпnand_reciev [0] = "I";
Схема н программа модуnя нзnучення ИК-кодов 171 //Прочитаем и преобразуем номер модУля. MOD_ADDR = PORTB; // Номер МОдУЛЯ в старших битах . MOD_ADDR=MOD~ADDR>>4; 11 Сдвинем на четыре бита. 11 Ждем прихода команды и данных. start: RA2 =1; input = getch(); switch (input) case "!": //Если обращение к МОдУЛЮ ИК команд. for (k=l; k<б; ++k) // Запишем комаНдУ в массив. { input = getch(); cornmand_reciev [k) = input; MOD_NUМ = sim_num _adr(); // Определим, к кому адресуются. if (MOD_NUМ != MOD_ADDR) break; //Если не наш адрес. else if (cornmand_reciev (5) == "Р") { and() ; / / Если команда . ir_trns () ; / / Отправим ИК комаНдУ на излучатель. } default: goto start; goto start; НЕХ-Файп дn• 3аrррки в nporpa11111111a'f'Op :10000000830100308A0004282030840078300D20DD :1000100083012D2B04068001840A0406031DOA288F :0 2 0020000034АА :1005520083018ClEA92AlA080800FCOlFD01031060 :100 5 6200FВOCFAOC031CВC2A7808FC077908031858 :10057200790AFD070310F80DF90D7A087B040319B7 :100582000034B02A8301AC01AD01D0 2A2C083CЗED4 :100592008400831323088000ACOA0319ADOAA92240 :1005А200АЗОО2ЗОFС72А2С08ЗСЗЕ84008313230890 :1005В200800008008301В401В5013708А0003808АЗ :1005C200A100D030A007Al070AЗOFAOOFB012008El :1005D200F800F901AE2221087C07B4007D08031 857
172 Глава • 1 Базовая версия :1005E2007DOAВ500F900340BFBOOOBOOB3018501BE :1005F20007309FOOB3168501FE3086009030B312FB :10060200980006308316980068309900831206100D :100612001816060BA400A5010430FB00250DA50C43 :10062200A40CFBOBOF2ВAC01AD012DOBBOЗAFB0099 :10063200803078023D3003192C020318292B2COB34 :100642003СЗЕВ40083138001АСОА0319АDОА162ВС9 :10065200AC01AD0105150BOOF722AE01AF013A2BЗE :100662002ЕОВ363Е8400831320308000АЕОА031920 :10067200AFOA2F08803AF80080307802063003195A :100682002Е02031С312В4930Вб000608А400А50136 :100692000430F800250DA50CA40CF80B4B2B7C2B79 :1006A200AE01AEOAAF012F08803AF800803078021E :1006В200063003192ЕО203186А2ВА922А3002ЕОВ62 :1006C200363EB40083132308BOOOAEOA0319AFOA62 :1006D200542BDB227808A6007908A7002506031D03 :1006E200742B24082606031D7C2B3B08503A031D5D :1006F2007C2ВC32283230515A922A300493A03199F :10070200512B7C2BB301B001B101B001B101DE2B71 :100712000330А800А901С52В28083СЗЕ840083139Е :10072200000ВА200А80А0319А90АА2080319А92В02 :1007320085148514851485148514851485148514EF :10074200851485148514851485108510А203962ВВЗ :100752002ВОВЗСЗЕВ40083130008А200АВОА03195В :10076200А90АА2080319С52В851085108510В510СА :1007720085108510851085108510851085108510CF :1007820085108510А203В22В2808ЗСЗЕ84008313F7 :10079200000FBD2BB201B3013308803AFB00863086 :1007А20078021ВЗООЗ193202031ВDВ2ВВ20А031939 :1007B200B30ACD2BB00A0319B10A3108803AF80006 :1007С20080307802043003193002031С892ВАС01FВ :1007D200AD012D08803AF800803078023D300319CF :1007E2002C02031BFD2B2C083CЗE8400831380014D :OE07F200ACOA0319ADOAEA2ВAC01AD010800FB :OOOOOOOlFF Возвращаясь к представлению в некотором «Собственном формате», попробуем «прикинуть», как все будет выглядеть. EEPROM хранит 128 байт. Если мы будем использовать модуль излучателя ИК-кодов для одного устройства, сколько управляющих команд нужно для него в системе? Возьмем, например, DVD-проигрыватель. Какие команды нужны пользователю, чтобы смотреть фильмы? Проиграть, Стоп,
Схема и программа модуnя изnучения ИК-кодов 173 Предыдущий фрагмент, Следующий фрагмент, Громче, Тише, Выключить звук, команды курсора Влево, Вправо, Вверх, Вниз, Ввод, Меню. Для ровного счета возьмем 15 команд. Таким образом, на одну команду мы можем потратить 8 байт. Много это или мало? Ответ на вопрос следовало бы искать в следующем раз­ деле - «Модуль считывания инфракрасных кодов», проведя считывание всех интересующих нас ИК-команд. В данный момент я решаю, что нет смысла хранить коды в модуле воспроизведения ИК-команд, будем хранить их на компьютере. Предварительно примем формат команды вида, показанного в табл. 1.8. Таблица 1.8 . Предполагаемый формат ИК-кода Устройство Команда Повторов Коэффициент Частота ? байт ? байт байт байт 2 байта Импут.с Паузаит.д. EOF . 2 байт 2 байта байт О При этом в отличие от предыдущих модулей, модуль излу­ чения должен получать по сети не только команду, но и дан­ ные, следующие за ней. Если мы определим префикс модуля с помощью латинской буквы «I», команда может выглядеть сле­ дующим образом: Ixx$nP и байты данных, где n - количество повторов. Я думаю, что повторов от О до 9 должно хватить. Байты данных начнутся с байта коэффициента и закончат­ ся нулевым байтом. Мы не знаем, сколько именно будет пе­ редано байт. Для определенности возьмем 50 байт. Значит, все данные будут переданы приблизительно через 50 мс. После приема данных модуль может начать воспроизведение ИК-кода. Таким образом, задержка между нажатием на клави­ шу управления и отправкой управляющего ИК-кода будет не более 0,1-0,2 с. Думаю , не слишком много. Осталось два момента, которые мене сейчас не ясны. Пер­ вый - хватит ли места в регистрах контроллера для хране­ ния команды. В первых двух банках памяти 176 байт отведе­ но для регистров общего назначения. Полагаю, этого хватит, но хранение в двух банках...
174 Гnава • 1 Базовая версия Второй момент, смущающий меня, относится к некоторой вероятности того, что передаваемые данные, а это байты, совпадуг с видом команды. Не думаю, что это очень вероят­ но, но эту неприятность мы можем отслеживать на этапе за­ писи ИК-кода. Если, паче чаяния, это произойдет, воспользу­ емся коэффициентом пересчета, преобразовав данные к другому виду. Теперь мы готовы начать разработку нового модуля. За основу возьмем предыдущий модуль, у которого исполь­ зуем вывод RA6 на выход. К этому выводу порта мы будем подключать светодиод ИК-диапазона (излучатель, или ИК­ эмиттер). Как обычно, я создаю папку в рабочей папке МРl.АВ, кото­ рую называю ir_trans, и копирую в нее все файлы предыдуще­ го модуля. Теперь я открываю в программе MPLAB предыду­ щий проект, но уже из этой папки. Сохраняю его под новым именем - ir_trans, а также файл заголовков и программы, меняю их в менеджере проекта, включая файл todo.txt, на­ страиваю установки Debugger. Осталось поменять файлы сце­ нария, удалить из папки все старые файлы, и можно начинать работу. Вся эта процедура необязательна. Можно открыть новый проект, но при этом не следует забывать, что все его настрой­ ки следует сделать заново. Задать рабочую тактовую частоту контроллера и скорость выполнения анимации. Иначе мож· но наступить на грабли, которые подстерегали нас в самом начале работы. В отличие от предыдущих данный модуль при настройке должен прочитывать из файла input.txt последовательность данных. Вернемся к рекомендациям изготовителя микроконт­ роллера PIC16F628A и после строки команды в файле input.txt впишем данные в виде шестнадцатеричных чисел, записан­ ных в столбик и завершаемых командой OAh. Но сначала под­ готовим их. Возьмем код из раздела " модуль считывания ин­ фракрасных кодов». pulse 2455 Заголовок space 532 pulse 1291 Единица врасе 506
Схема и программа модуля излучения ИК-кодоа 175 pulse 664 Ноль space 533 pulse 1266 Едияип;а space 533 pulse 665 Ноль space 591 pulse 1211 Едияип;а space 533 pulse 685 Ноль space 515 pulse 693 Ноль space 526 pulse 1271 Едияип;а space 506 pulse 1265 Едияип;а space 533 pulse 666 Ноль space 557 pulse 1241 Едияип;а space 533 pulse 664 input.txt " R0 3$0N" "!03$5Р" Команда обращения к модулю трансляции ИК команды 01 Количество повторов 01 Коэффициент 25 Частота несущей 37 кГц 97 младший байт импульса заrоловка (mестнадцатеричноrо числа) 09 14 02 Е3 04 4А 02 4А 02 4А 02 Е3 Старший байт импульса заrоловка младший байт паузы Старший байт паузы младший байт импульса единицы (1251 мкс - среднее) Старший байт импульса единицЬI младший байт паузы единицы (586 мкс - среднее) Старший байт паузы единицы младший байт импульса нуля (586 мкс - среднее ) Старший байт импульса нуля младший байт паузы нуля (586 мкс - среднее) Старший байт паузы нуля Младший байт импульса единицы (1251 мкс - среднее) 04 Старший байт ~льса единицы 4А младший байт паузы единицы (586 мкс - средне е )
176 Глава • 1 Базовая версия 02 Старший байт паузы единицы 4А Младший байт импут,са нуля (586 мкс - среднее) 02 Старший байт импульса нуля 4А Младший байт паузы нуля (586 мкс - среднее) 02 Старший байт паузы нуля ЕЗ Младший байт импульса единицы (1251 мкс - среднее) 04 Старший байт импульса единицы 4А Младший байт паузы единиuы (586 мкс - среднее) 02 Старший байт паузы единицы 4А Младший байт импульса нуля (586 мкс - среднее) 02 Старший байт импульса нуля 4А Младший байт паузы нуля (586 мкс - среднее) 02 Старший байт паузы нуля 4А Младший байт импульса нуля (586,мкс - среднее) 02 Старший байт импульса нуля 4А Младший байт паузы нуля (586 мкс - среднее) 02 Старший байт паузы нуля ЕЗ Младший байт импульса единицы (1251 мкс - среднее) 04 Старший байт импульса единицы 4А Младший байт паузы единицы (586 мкс - среднее) 02 Старший байт паузы единицы ЕЗ Младший байт импульса единицы (1251 мкс - среднее) 04 Старший байт импульса единицы 4А Младший байт паузы единицы (586 мкс - среднее) 02 Старший байт паузы единицы 4А м_ладший байт импульса нуля (586 мкс - среднее) 02 Старший байт импульса нуля 4А Младший байт паузы нуля (586 мкс - среднее) 02 Старший байт паузы нуля Е3 Младший байт импульса единиuы (1251 мкс - среднее) 04 Старший байт импульса единицы 4А Младший байт паузы единицы (586 мкс - среднее) 02 Старший байт паузы единицы 4А Младший байт импульса нуля (586 мкс - среднее) 02 Старший байт импульса нуля 00 Завершающий нулевой байт Конечно, файл не должен содержать моих пометок. Я ис­ пользовал одинаковые усредненные числа. Прав ли я? Это можно будет проверить только при воспроизведении. На дан­ ном этапе это не играет роли. Позже, возможно, мы напишем программу, которая будет упаковывать считанные данные. Посмотрим.
Схема и программа модуnя иэnучения ИК-кодов 177 Теперь нам нужно позаботиться о том, где мы будем хра­ нить полученные данные. Для этой цели используем массив беззнаковых символов: unsigned char ir_cmd [53]; Я задал массив длинною в 53 байта. Вообще мы не знаем, какой длины получится массив, но можно вернуться к этому позже. Основной переделке подвергается функция прочитыва­ ния команды. За последним символом команды ' Р' следуют данные. Количество повторов мы получаем перед командой. Но мы оставили под это байт данных. Поэтому пока будем игнорировать количество повторов в команде. Ожидаем 'Р ' , начинаем заполнение массива. Основная часть программы: 11 Начинаем работать. 11 Ждем прихода команды и данных. start: while(input != MODULNAМESIM) input = getch(); / / Ждем обращения к мо.цулю. cmd (); 11 Обработаем сетевую коман.цу. goto start; / / Обработка сетевой команды. int cmd() { MOD_NUМ = sim_num _adr () ; if (MOD_NUМ == MOD_ADDR) { 11 Чтение из сети (файла) . / / Если наш адрес мо.цуля . while (input ! = "Р" ) input = getch() ; 11 Ждем. if (input •р•) //Если символ завершения команды . { 11 Принимаем дaIOible. while (i<54) { input = getch(); ir_cmd[i] input; ++i;
178 Глава • 1 Базовая версия Перед запуском программы я не забываю установить в высокое состояние биты, имитирующие переключатель адре­ са модуля (RВ4, RВ5 в окне Stimulus Controller). Очередные грабли, на которые я наступаю, - программа не ра­ ботает. После первого символа в регистре приемника USART появляется 02• .Это не номер модуля, дальше ничего не получа- . ется . Не пытаюсь разобраться, просто добавляю в файл input.txt еще пару команд перед командой обращения к модулю. "R02$1N" "R01$1N" "I03$5P" Теперь программа работает, массив заполняется. Добавив его в наблюдение, можно посмотреть, как он заполняется, и есть ли печатные символы в наших данных. После заполнения массива мы готовы передать ИК-команду. У нас три временных интервала: pulse 2455 Заголовок space 532 pulse 1291 Единица Несущая частота - 37 кГц период -27 мс. Через время -13 мс будем менять состояние вывода RАб порта А, если у нас в масси­ ве записан импульс. Можно, как в программе предыдущего модуля, использо­ вать встроенные таймеры контроллера. Но для начала попро­ буем использовать простые циклы. void ir_trns ( J { i =О; с=3; / / В первых трех байтах служебная информация. while (ir_cmd(i] != 0) // Наш байт окончания команды . 11 Импульс. Ь = ir_cmd[c+l]; // Сначала прочитаем старший байт. Ь = Ь<<В; //Сместимся на один байт. Ь = Ь + ir_cmd[c]; //Сложим байты, получая длительность импульса. с=с+2; 11 Сместимся на два байта.
Схема и программа модули излучении ИК-кодов 179 while· (Ь != 0) { for (d=O;d<l4;++d) RАб l; //Теперь с частотой в 37 кГц for (d=O;d<l4;++d) RАб О;// будем создавать несущую 11 частоту. --Ь; 11 Пауза. Ь = ir_cmd[c+l]; ь =Ь<<8; Ь = Ь + ir_cmd[c]; //В этой переменной мы храним длительность паузы. с=с+2; while (Ь != 0) { for {d=O;d<28;++d) RАб О; 11 Передаем паузу. --Ь; } В глобальные переменные я добавил несколько индексных переменных. Их можно добавить локально, но глобальные переменные удобнее наблюдать. int i =О; int ь =О; intс О; int d =О; Пытаясь передать массив, я обнаружил, что по умолчанию он не обнуляется, поэтому в раздел инициализации модуля я добавляю обнуление массива. Проблема, которая возникает без этого обнуления, состоит в том, что мы записываем байт, а работаем с двухбайтовыми числами. Нулевой байт записы­ вается в конец массива, но второй байт не нулевой, тогда как условие while (Ь !=О) // гдеЬ-целое. for (i=O; i < бl; ++i) ir_cmd[i] 7 О; 11 Обнуление массива. теперь, вроде "бы все работает, но мне хочется посмотреть, что транслируется излучателем, соединенным с выводом
180 Глава • 1 Базовая версия RАб. Программа позволяет воспользоваться программным . логическим анализатором. Для этого я выделяю всю часть void ir_trns () , правой кнопкой мыши вызываю раскрываю­ щееся меню, в котором выбираю раздел Add Filter • in Trace (Добавить фильтр• в Трассировку). Теперь, во View (Вид) основного меню добавляю к рабочему окну Simulator Trace (Симулятор трассировки) и жду, когда заполненный массив начнет транслироваться. Я ожидаю, что мне удастся увидеть весь передаваемый через RАб код. Запускаю Simulator Logic Analyzer (Симулятор логического анализатора), в котором с помощью кнопки Channels (Каналы) вхожу в меню выбора отслеживаемых выводов. Затем выбираю RАб и добавляю вывод в наблюде­ ние -Аdd (Добавить). Вопреки желаемому, потратив достаточно много времени, получаю очередное напоминание о «граблях». Удается зафик­ сировать только фрагменты. Пытаюсь добавить управление еще одним выводом порта А - RAO, устанавливая единицу перед формированием импульса и сбрасывая в ноль при пау­ зе. Единственное, что получилось, - это ряд фрагментов, по­ казанных {!а рис. 1.54 -1 .56 . ~111~ 5(ХХХ)О0 10IXIOJ.0 15'XXXXIO Рис. 1.54. Первый фрагмент эксперимента с логическим анализатором Первый из фрагментов относится к моменту завершения передачи заголовка. Во втором следом за заголовком переда­ ется единица. На последнем фрагменте видно, что передача несущей сменяется паузой. Не густо. Оставлю программу модуля, удалив управление выводом RAO, и проверю работу модуля, когда соберу его. У меня нет уверенности , что частота несущей - 37 кГц (или близка к ней),
Схема и программа модуля излучения ИК-кодов 181 Рис. 1.55. Второй фрагмент эксперимента слоrическим анализатором Рис. 1.56 . Третий фрагмент эксперимента слоrическим анализатором а длительность импульсов и пауз не требует дополнительной калибровки. Пока я не могу сделать больше, оставлю все, как есть. #include <piclбf62xa.h> #include <stdio.h> #include •ir_trans.h• unsigned char input; регистра. unsigned char MOD_SIMl; unsigned char MOD_SIM2; int MOD_ADDR; int MOD_ADDR; int siml_num = О; int sim2_num = О; int sim_end_num = О; / / Считываем содержимое приемного / / Первый символ адреса модуля. / / Второй символ адреса модуля. 11 Заданный адрес модуля, как число. //Заданный адРес модуля, как число. int MOD_NUМ; // Полученный адРес модуля, как число. int i =О; intЬ О; intс О;
182 Глава • 1 Базовая версии intd=О_; unsigned char ir_cmd [60]; unsigned char getch{) { while( !RCIF) cont.inue; return RCREG; //Устанавливается, когда регистр не пуст. //Вывод одного байта. void putch(unsigned char Ьуtе) { PORTB = 1; TXEN = 1; while( !ТXIF) continue; TXREG = Ьуtе; int init_comms () { PORTA =ОхО; CMCON = Ох?; TRISA =Ох80; TRISB = ОхFб; RCSTA =Ох90; TXSTA =Ох4; SPBRG = Охlб; INТCON=O; PORTB = О; //Переключим драйвер RS485 на передачу. 11 Разрешаем передачу. //Устанавливается , когда регистр пуст . 11 Инициализация модуля. 11 Настройка портов А и В. 11 настройка приемника. 11 Настройка передатчика. / / Настройка режима приема-передачи. 11 Запретить прерывания. //Выключим передатчик драйвера RS485. / / Определим номер модуля. MOD_ADDR = PORTB; // Номер модуля в старших битах. MOD_ADDR=MOD_ADDR>>4; / / Сдвинем на четыре бита. for (i=O; i<бl; ++i) ir_cmd[i] = О; } 11 Преобразуем символьный адрес в число. int sim_num _adr () sim_end_num = О; siml_num = getch(); номера. MOD_SIMl = siml_num; sim2_num = ge tch () ; //Чтение первого символа / / Сохраним первый символ. //Чтение второго символа номера.
Схема и программа модуля излучения ИК-кодов 183 MOD_SIM2 = sim2_num; / / Сохраним . второй символ. sirnl_num = sirnl_num - ОхЗО; s im2_num =s irn2_num - ОхЗ О ; sirn_end_nurn = sirnl_nurn*OxOA + sirn2_nurn: retum sirn_end_num; int crnd() { МOD_NUМ = sirn_num_adr () : / / Чтение из сети (файла) . if (MOD_NUМ == MOD_ADDR) / / Если наш адрес модуля. { while (input != if (input "Р") input = getch (); / / Ждем. "Р") // Если символ заве~шения команды . { i=O: //Принимаем данные. while (i<54) { i~put =getch(); ir_crnd(i] = input; ++i; void ir_trns () { i =О; с =З; while (ir_cmd[i] != 0) { 11 Импульс. Ь = ir_crnd[c+l]; Ь=Ь«8; Ь = Ь + ir_crnd[c); с=с+2; RAO=1; while (Ь != 0) //Наш байт окончания команды . for (d=O;d<14;++d) RАб 1; for (d=O;d<l4;++d) RАб О; --Ь;
• 184 Глава• 1 Базовая версия 11 Пауза. Ь = ir_cmd[c+l]; Ь=Ь«8; Ь = Ь + ir_cmd[c]; с=с+2; RAO=О; while (Ь != 0) { for (d=O;d<28;++d) RАб О; --Ь; void main (void) { init_comms (); 11 Начнем работать . 11 Инициализация мо.цуля. //Прочитаем и преобразуем номер мо.цуля. MOD_ADDR = PORTB; //Номер МОдУЛЯ в старших битах. МOD_ADDR=MOD_ADDR»4; 11 Сдвинем на четыре бита. / / Начинаем работать . //Ждем прихода команды и данных. start: while(input != МODULNAМESIM} input = getch(); 11 Ждем обращения к модУлю. cmd (); / / Обработаем сетевую командУ. ir_trns(); goto start; / / отправим ИК командУ на излучатель . Все получается разумно и красиво, л?гично и грамотно. Ай, да я! Смущает одно. Когда я проверяю времена, соответствую­ щие картинкам анализатора , получаю совсем не то, что хоте­ лось бы. В моем приборном арсенале нет записывающего ос­ циллографа. Представив, как я пытаюсь поймать и измерить последовательность импульсов ИК-команды обычным осцил­ лографом (если вам не приходилось, попробуйте), я решаю вернуться к МРLАВ. Верю я тем, кто создал эту замечательную программу! И начинаю понимать, что совсем не «Ай, да я! ». Где-то я ошибаюсь.
Схема и программа модуля излучения ИК-кодов 185 Напишем простую программку: #include <piclбf62xa.h> #include <stdio.h> int d =О; int с =О; int init_comms () { PORTA = ОхО; CMCON = Ох7; TRISA = Ох80; TRISB = ОхFб; RCSTA = Ох90; TXSTA = Ох4; SPBRG = Охlб; INТCON=O; PORTB = О; } void main(void) { / / Инициализация модуля. //Настройка портов А и В. //Настройка приемника. 11 Настройка передатчика. 11 Настройка режима приема-передачи. 11 Запретить прерывания. //Выключим передатчик драйвера RS485. init_comms (); //Начинаем работать. / / Здесь поставим ТO"DtY останова. start: for {d=O;d<2;++d) RАб = 1; for {с=О;с<2;++с) RАб = О; goto start; Настроим, установив тактовую частоту контрошiера 4 МГц, все, что настраиваем обычно. Выделим с помощью Add Fil- ter • in Trace строки, выделенные в тексте, и в пошаговом режиме сделаем четыре шага по программе. Посмотрим, что нам рисует логический анализатор (рис. 1.57). Время, определяемое в циклах команд контроллера для состояния «О>>, - около 75 циклов, или 75 мкс. Но я устанавли­ ваю, как я полагал, вывод RАб в ноль на один цикл. В состоя­ нии "1 », что по моим предположениям тоже должно соответ­ ствовать 1 мкс, я «зависаю» на 78 мкс. Проверяю маркером (рис. 1.58).
186 Глава • 1 Базовая версия ЕЮ.О 100.0 120.О 140.0 IEll.O 1ЕЮ.О 200.0 Рис. 1.57 . Отображение логическим анализатором пошаговых команд Рис. 1.58 . Измерение интервала времени маркером Так и есть. Не нравится мне это, но пока я не понимаю, в чем дело. Включив в Simulator Trace режим просмотра в инженер­ ных единицах, я получаю следующую картинку за один про­ ход моих циклов for (вид программы в трассировщике МРI.АВ) - рис. 1.59. Это не полная картина трассировки, строки следуют до номера 45, что соответствует моменту времени в 115 мкс от начала процесса. mjl------ ·- §-·--H 1111111 1•1'11'11'1•11'11111111"1" ' ' 1•" ' 1'11'1'1111 7n.O 75.0 ЕЮ.О 85.0 90.О 950 100.0 105 .0 110.0 115.О Рис. 1.59 . Определение интервала времени одного прохода цикла for И я медленно начинаю понимать... Это в своем правильном логическом мире, описанном язы­ ком С, я за одну команду успеваю перейти от «О » к « 1» и об­ ратно. В реальном мире контроллера это занимает ровно столько времени, сколько требует команд. На 82-й микросе­ кунде текущего времени я устанавливаю RАб в единицу, что трассировщик отображает в 12-й строке командой BSF Ох5 , Охб (рис. 1.60).
10 011:8 1801 11 0'1'U 0000 1' O'th t'IOt 1101'1:10Ш 11 О1'1О ONI 11 Ottl suo ZD 0'781 OOrtl Схема и программа модуля и311учения ИК-кодов 187 =.::'··~~~оо:о: атrк 0.1. 0 .10001 tr ·--- -- ..,..,. o.az. • ONZ 00 0011 '8 ,...ooo . -t IПSC:O..J.O 0001 18 ---- - 80.000 .-8 ltOf 0000 00 ---- - 11.000 .-1 lltD•t,OW:8 000100 · · -· ·- 11.ООО.·8 uкr 0.ZI. , ONJ 00 0011 01 11.000.-1 IПКО..1,0•10001 11 · - - · • 11'1» 0000 00 --- -- 001'00.~ --- -------- .,. -- -- - --- - l' t,00 0.-1 rIOn O..ZJ, 1 0021 00 00\111 00 Н.000.-8 za.a.• Ох8О • -- • оо 11.000. -• ...,., о. '7 0 --- -- 001'0 80 llOl/L.I О.80 1--180 ZZ 0'71:• OlXI 11JIW O. 'JO , 1 00"70 1О 001'0 00 ZJ 0715 ЮС! llOU'LI OlfZ 1••1Ol IТl'SCD•l,0.10001 lf ------ JS tпn Cl:ZJI 10.wroxzz, 1 0021 01 oozz,., . 21 07U 1801 IПК0.1, О 0001 11 ---- -- 0000 00 --- -- .., D•I.°"' 0001 t0 ---- - н.ооо.-• ZI 0111 O.uJ ПICr0.11,f 0021 01 002102 81.ЬОО.·С 10 O'l'V . 111(11 msc D•>- 0 .1 0001 11 - -- -· i.oo .ooo. -• 11 0'11 0000 ltOf 0000 00 ~- ." ---- - --- - 101. 000. -• --- - -- --- -- 101. 000.- • 0021 00 0011 00 10.. DOOe- I 101.000 .-• Рис. 1.60. Видnрограммы втрассироаЩl'lке MPLAB Спасибо программистам, создавшим программу MPL.AB - сидеть бы мне за осциллографом, чертыхаясь, долго и бе­ зуспешно! Спасибо тем, кто учил меня писать программы в машинных кодах, когда я начал заниматься микропроцессорной техни­ кой; тем, кто терпеливо пояснял мне, как правильно отсчиты­ вать «branch» в командах! Посыпав голову пеплом, как и полагается, попробуем из­ менить ситуацию к лучшему. В первую очередь, постараемся добиться, чтобы циклы были одинаковы. Я же хочу получить меандр частотой 37 кГц. Экран в данный момент выглядит, как показано на рис. 1.61 (я добавил внешний цикл for). Изменив часть программы и манипулируя числами, я не­ сколько меняю результат (рис. 1.62): start: а =О; while ( а< 100)
188 Глава • 1 Базовая версия for (d=O;d<З;++d) RАб for (с=О;с<2;++с) RАб ++а; goto start; D'!I х~""' t' . > c1s.,1.r . ..._••,",...~t••.,.1-11"~~":м-t:t.teg11 - .- ,••,."" . U•1J - ,_.",..,.-:,•••' au"o. l; О; "-..rd8 (43%) 7Ь)оt-1]1%) ~~~~si~~-W G ' ·"··- "~·- • Рис. 1.61 . Экран отладки в MPLAB Рис. 1.62 . Исправленный интервал времени несущей частоты Меандр я получаю, но частота несущей остается близка к 8 кГц, тогда как мне нужна частота раз в пять выше. Пока я вижу несколько решений - повысить в пять раз тактовую ча­ стоту контроллера, настроить внешний генератор на частоту 37 кГц WIИ использовать внугренние резервы контроллера.
Схема и программа модуля излучения ИК-кодов 189 Попытка использовать таймер несколько улучшила ситуа­ цию, но не в полной мере. Последний вариант, не затрагива­ ющий коренных переделок всей программы или модуля, вы­ глядит следующим образом: start: а = О; for (а=О; a<lOO;++a) ( RАб 1; RАб 1; RАб 1; RАб 1; RАб 1; RАб=1; RАб 1; RАб 1; RАб 1; RАб 1; RАб О; RАб О; goto start ; Получившийся при этом сигнал показан на рис. 1.63. fi'a1*1i·1.jljlq• , 1 111 llшl~ш+1111 11 1о1 120.0 1:11.0 1~.О 150.0 1QJ.O 170.0 11Ю.О 1!Ю.О "~------------ - -- Рис. 1.63 . Исправленное значение величины несущей частоты Период сигнала в 27 мкс соответствует частоте несущей 37 кГц. Это не самое изящное решение. В первую очередь, теперь следует отказаться от изменения несущей частоты ИК-команды «на лету» . Модуль будет работать с фиксирован­ ной несущей частотой. Посмотрим, можно ли поправить про­ грамму модуля. Не забудьте проверить модуль приема ИК-кодов. Нет ли и там подобной ошибки!
190 Глава • 1 Базовая версия С несущей частотой положение несколько улучшилось, но времена посылок раз в 10 превышают реальные. Первое, что мне приходит в голову, - уменьшить в 1О раз времена в файле input.txt. В этом есть и привлекательная сторона - теперь мас­ сив, в котором я храню времена, становится не двухбайтовым, а однобайтовым. Но посылки все еще слишком длинные. Укорачиваем их еще вдвое, разделив значение времени на два уже в программе. И последнее «заметание мусора под ковер» - деление в файле input.txt всех значений на 1,38. Мне не нравится то, что я делаю. Но в итоге я получаю результат, показанный на рис. 1.64. Рис. 1.64 . Вид ИК-сигнала на экране логического анализатора Это даже больше, чем я ожидал. Вернее, я ожидал этого в начале работы, но, не справившись с логическим анализато­ ром, отказался от попыток получить подобную картинку. Здеп·несущая, если ее увеличить, выделив затемненный уча­ сток сигнала RA6 с помощью мыши и клавиши выбора на ин­ струментальной панели (пятая слева), выглядит, как показа­ но на рис. 1.65, заголовок имеет время, как на рис. 1.66 , а единица и пауза, рис. 1.67 и 1.68, соответственно. ~·-~r· f!im!· •,-r ----------- Рис. 1.65 . Вид несущей частоты
Схема и программа модуля излучения ИК-кодов 191 Рис. 1.66 . Вид заголовка Рис. 1.67 . Видединицы 11i!-::'•~~· --21 F:Г-Гr ' ... ·-- . --- Рис. 1.68 . Видnауэы Времена близки к оригиналу. Последние грабли, на кото­ рые я умудряюсь наступить - в функции обработки массива: void ir_trns () { i =О; с=З; while (ir_c:md[i] != 0) 11 Наш байт окончания команды.
192 Глава 8 1 Базовая версия забываю, заменить i на с. Вот так: void ir_tms () { i =О; с =З; while (ir_cmd[c] != О) // Наш байт окончания команды. Без этого, закончив передачу ИК-команды, программа ме­ няет байт, из которого я начинаю позже вычитать, и, вычитая из нуля, я получаю опять ненулевой байт, который при про­ верке циклом while вместо завершения работы функции на­ чинает «пороть чушь». Для отправки я распаковываю массив не с самого начала, а с третьего байта, поскольку в первых трех байтах (от О до 2) у меня служебная информация (с = 3), а в этом месте поменять я забыл. Итоговая программа выглядит так: #include <piclбf62xa . h> #include <stdio.h> #include "ir_trans.h" unsigned char input; регистра. unsigned char MOD_SIMl; unsigned char МOD_SIМ2; int MOD_ADDR; // int MOD_ADDR; // int siml_num = О; int sim2_num = О; int sim_end_num = О; //Считываем содержимое приемного //Первый символ адреса мо.цуля. //Второй символ адреса модуля. Заданный адрес мо.цуля, как число . Заданный адрес мо.цуля, как число. int MOD_NUМ; // Полученный адрес мо.цуля, как число. int i =О; int с =О; unsigned char ir_cmd [60); unsigned char Ь = О; unsigned char getch() { while( !RCIF) continue; retum RCREG; 11 Устанавливается, когда регистр не пуст.
Схема 1А программа модуля JАзлученJАя ИК-кодов 193 / / Вывод одного байта. void putch (unsigned char Ьуtе) { PORTB = 1; //Переключим дРайвер RS485 на передачу. TXEN = 1; / / Разрешаем передачу. while ( ! TXIF) / / Устанавливается, когда регистр пуст. continue; TXREG = byte; int init_coпuns () { 11 Инициализация модуля. PORTA = ОхО; CMCON = Ох7; TRISA = Ох80; TRISB = ОхFб; RCSTA = Ох90; TXSTA = Ох4; SPBRG = Охlб; INТCON=O; PORTB = О; //Настройка портов А и В. //Настройка приемника. //Настройка передатчика. //Настройка режима приема-передачи. //Запретить прерывания . //Выключим передатчик дРайвера RS485. 11 Определим номер модуля . MOD_ADDR = PORTB; // Номер модуля в старших битах. MOD_ADDR=MOD_ADDR»4; / / Сдвинем на четыре бита. for (i=O; i<бl; ++i) ir_crnd[i] = О; } //Преобразуем символьный адРес в число. int sim_num_adr () sim_end_num = О; siml_num =getch(); MOD_SIMl = siml_num ; sim2 _num = ge t ch(J; MOD_S IМ2 = s im2_num; s iml_num = s i ml_num - s im2_num = sim2_num - //Чтение первого символа номера. //Сохраним первый символ. 11 Чтение второго символа номера . / / Сохраним второй символ . ОхЗО; ОхЗО; sim_end_num = siml_num*OxOA + sim2_num; return sim_end_num; int cmd !J
194 Глава • 1 Базовая версия МOD_NUМ = sirn_num_adr(); 11 Чтение из сети (файла). if (MOD_NUМ == MOD_ADDR) // Если наш адрес модуля. { while (input != "Р") input = getch(); //Ждем. if (input "Р") //Если символ завершения команды . { i=O; input = getch () ; / / Принимаем данные. while (input != ОхО) { ir_cmd[i] = input/Ox2; input = getch(); ++i; void ir_trns () { i =О; с=З; while (ir_crnd[c] != 0) / / Наш байт окончания команды . { 11 Импульс. Ь = ir_cmd[c]; ++с; while (Ь != 0) { RA6 1; RA6=1; RАб 1; RA6 1; RA6 1; RA6 1; RA6 1; RA6 1; RA6 1; RA6 1; RАб=1;
Схема и программа модуля излучения ИК-кодов 195 RАб 1; RАб 1; RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; --Ь; 11 Пауза . ь = ir_cmd[c] ; ++с ; while (Ь != 0) RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб=О; RАб=О; RАб О; RАб О; RАб О; RАб=О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб О; RАб=О; RАб=О; --Ь ;
196 Глава • 1 Базовая версия void main(void) { //Начнем работать. init_coпuns (); / / Инициализация мо.цуля. //Прочитаем и преобразуем номер мо.цуля. MOD_ADDR =PORTB; //Номер мо.цуля в старших битах . MOD_ADDR=MOD_ADDR>>4; / / Сдвинем на четыре бита. //Ждем прихода команды и данных. start: while ( input ! = МODULNAМESIM) input = getch (); //Ждем обращения. cmd (); ir_trns(); goto start; / / Обработаем сетевую коман.цу . // Оrnравим ИК коман.цу на излучатель . Если ее запустить, набраться терпения и дождаться ре­ зультата, он будет выглядеть, как показано на рис. 1.69 (отсле­ живание RAO я убрал, оно бьvю полезно только для определе­ ния времен). Рис. 1.69. Итоговый вид ИК-кода Именно такой сигнал мы могли бы увидеть на записываю­ щем осциллографе, если бы воспроизвели ИК-команду с пуль­ та устройства перед фотоприемником (без встроенной обра­ ботки сигнала). Картинка не была бы столь четкой, вероятно, но была бы очень похожа. Видно, что сигнал начинается с за­ головка (pulse), затем следует короткая пауза (space), после нее - единичная посылка несущей со своей паузой и т.д. По этой картинке можно прочитать сигнал - 10101001101.
Схема и nроrрамма модуля излучения ИК-кодов 197 Вернувшись к началу этого раздела, мы найдем данную команду. Проверить работу модуля с этой командой можно несколь­ кими способами (собрав модуль): прочитать команду с пульта и с модуля считывающим устройством и сравнить результаты или отправить команду на устройство, которое этой коман­ дой управляется. Работает устройство - работает и команда. Однако прежде чем проверять работу собранного модуля, есть смысл проверить его работу в МРLАВ с другими коман­ дами. У меня есть несколько считанных команд, проверкой работы которых я и хочу заняться, записав их для этого в новый input.txt файл. Попробую понять, что из этого получа­ ется . Вот как выглядит команда PLAY одного из устройств фир­ мы Sharp (в представлении, приведенном к виду, который получился бы с помощью считывания в WinLIRC). Исходный вид: 4000 dlOl 4000 dlOl 4000 с700 4000 с700 4000 с700 4000 с 700 4000 dlOl 4000 с700 4000 с700 4000 с700 4000 dlOl 4 000 с700 4000 с700 4000 d l Ol 4000 с700 4000 бf2Ь После первого преобразования: 0040 ИМПупьс Oldl Пауза 0040 ИМПупьс Oldl Пауза 0040 ИМПульс и т.д. 00с7 0040 00с7 0040 00с7 0040 00с7 0040 Oldl 0040 00с7 0040 00с7
198 Глава• 1 Базовая версия 0040 00с7 . 0040 Oldl 0040 00с7 0040 00с7 0040 Oldl 0040 00с7 0040 2Ьбf Времена - 64 (0040), 465 (Oldl), 199 (00с7), 11119 (2Ьбf). Первый импульс - 256 мкс. Что предполагает коэффициент 4. Тогда времена - 256 мкс, 1860 мкс, 796 мкс, 44 476 мкс. И, нако­ нец, в том виде, с которым мы начали работать (справа в шес­ тнадцатеричном представлении): pulse 256 . 12 Я разделил на 13,8 и перевел в НЕХ-формат space 1860 87 pulse 256 12 space 1860 87 pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА pulse 256 12 space 1860 87 pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА
Схема и программа модуля излучения ИК-кодов 1 99 pulse 256 12 space 1860 87 pulse 256 12 space 796 ЗА pulse 256 12 space 796 ЗА pulse 256 12 space 1860 87 pulse 256 12 space 796 ЗА pulse 256 12 space 44476 С96 Осталось заменить данные в файле input.txt. Посмотрим, что получится. Общий вид полученных импульсов изображен на рис. 1.70, а времена: первой паузы рис. 1.71, второй паузы и импульса рис. 1.72 и рис. 1.73. И период несущей частоты, рис. 1.74, похож на «настоящий» . Рис. 1.70. ВидконтрольногоИК-кода Рис. 1.71 . ВидnервойnауэыконтрольногоИК-кода
200 Глава • 1 Базова11 версн11 !Шl)_О !S600?..Q • . 61Щ).О Рис. 1.72. Вид второй паузы контрольного ИК-кода Rд6 11 11~1 111 АдО '9 50 0.0 50000.О 50500.0 510010 51500.0 52000.0 Рис. 1.73 . Вид импульса контрольного ИК-кода ~~1111 50500.О !Ю900.О Рис. 1.74. Вид несущей контрольного ИК-кода Для сравнения посмотрите, как выглядят информацион­ ные импульсы в программе, из базы данных которой взяты ИК-кодыShагр (рис. 1.75). Сравнивая его с видом импульсов, представленных как RAO на рисунке вида контрольного код", можно убедиться в их схожести. А времена (256 мкс против 259, 1860 мкс про­ тив 1828, 796 мкс против 825) не столь разительно отличают­ ся. Несущая, правда, уехала к 38,5 кГц, но это может быть и не совсем точно измеренное значение (маркер несколько съехал с фронта импульса).
Схема и программа модуля излучения ИК-кодов 201 Рис. 1.75. Вид импульсов кода Sharp И что nопучиnось? Приступая к разработ!(е, мы вполне разумно определились в том, что хотим от данного модуля. В процессе разработки, столкнувшись с трудностями, мы не менее разумно отказа­ лись от части первоначальных запросов. Написав первую вер­ сию кода программы, выглядевшую вполне «рассудительно и логично», мы отказались от нее. Предполагая хранить значе­ ния текущей длительности интервала в двух байтах, мы для ускорения работы программы приняли однобайтовый вари­ ант хранения. С точки зрения обучения это яркий пример того, как не надо делать. С практической точки зрения это пример того, как приходится иногда поступать, чтобы справиться с пробле­ мой, обойдя ее хотя бы на время. В нашем случае, пытаясь овладеть приемами работы с про­ граммой МРLАВ и одновременно создав некоторую люби­ тельскую систему, мы в праве принять несколько решений: • оставить все, как есть - мы не можем менять частоту несущей ИК-команды «на лету», но пока не убедились, что это нужно, можем не тревожиться; как выглядит программа, изящно или нет, после загрузки ее в кон­ троллер едва ли будет кому-либо интересно; все что требуется, так это чтобы модуль исправно работал; • можно собрать модуль, опробовать и, если работает, за­ быть о существовании проблем; • и, наконец, третье решение -пересмотреть все, что сде­ лано, и создать модернизированные версии тех же мо­ дулей; .к концу работы появится больше опыта, чаще бу­ дет приходить в голову мысль о том, что если бы знать раньше, можно было бы сделать и лучше! Лично я склоняюсь к тому, что, когда появятся эти мысли, тогда и займемся модернизацией. А пока рисуем схему и от­ правляемся в «Чип и Дип», собираем модуль.
202 Глава • 1 Базовая версия Напомню формат, который мы «перелопатили», идей­ ствия, которые мы осуществляем. вопреки первоначальным замыслам. Формат записи в файл ИК-команды представлен в табл. 1.9 . Таблица 1.9 . Новый вариант формата ИК-кода Устройство Повторов Коэффициент Имnуnьс Паузаит.д. EOF байт байт байт байт байт байт О Импульс и пауза - это времена в мкс, деленные на 13,8 после прочитывания в программе WinLIRC в виде шестнад­ цатеричных чисел. Затем, в программе, они будут еще раз разделены на 2. В программе в настоящий момент не используется служеб­ ная информация, относящаяся к устройству, количеству по­ второв и коэффициенту. Позже, если решим модернизиро­ вать модуль, мы дополнительно сделаем несколько выходов, которые будут выбираться по записи «Устройство», добавим обработку количества повторов и, возможно, используем ко­ эффициент 13 или 14 для деления времени, полученного при подготовке кода, самой программой . Если решим, что следу­ ет внести изменения в модуль. Модуnь с11итывания ИК-кодов WinLIRC Будем работать в программе WinLIRC, доступной для свобод­ ного использования, с соответствующим модулем в качестве считывающего устройства для предварительной подготовки ИК-кодов. Излучатель WinLIRC, возможно, используем для генерации системных ИК-кодов. Схема фотосчитывателя и излучателя для работы с про­ граммой WinLIRC показана на рис. 1.76. Програ~ма доступна на сайте http://winlirc.sourceforge.net. Элементы, необходимые для сборки фотосчитывателя приведены в табл. 1.10.
Модуль считывания ИК-кодов WinLIRC 203 ~L-"JLГ-.__ WinLIRC приемник-передатчик *VD2 IC1 TSOP 1738 Рис. 1.76. СхемаприемникаWinURС Таблица 1.1О. СпецификаЦИt1 фотосчитывателя No Обозначение Изделие Кол-во Цена(р.) 1 IC1 TSOP 1738 1 40 2 IC2 78L05 1 30 з VD1, VDЗ 1N4148 2 5 4 VD2 АЛ144А 1 20 5 R1 4,7 кОм 0,25 Вт 1 1 6 R2 2 кОм 0,25 Вт 1 1 7 С1 4,7мкФ16В 1 20 8 Х1 DB9 гнездо 1 10 Вид платы может быть таким, как показано на рис. 1.77. Рис. 1.77. Плата фотоприемника WinURC
204 Глава • 1 Базовая версия Программа WinLIRC работает в двух режимах при прочи­ тывании ИК-кодов. В первом режиме она определяет соот­ ветствие кода стандарту и создает текстовый файл, в кото­ ром записаны параметры кода. Во втором режиме она непосредственно выводит во встроенное окно времена посы­ лок и пауз ИК команды (рис. 1.78). Рис. 1.78. ВидпроrраммыWiпURС Появление в правом углу панели значка g] означает, что программа работает. Правой клавишей мыши с помощью это­ го значка можно вывести окно программы на экран. Кнопкой Browse задать файл конфигурации. А, щелкнув кнопку Raw Codes, прочитать ИК-команду. Думаю, что для считывания команд мы используем второй метод, поскольку существует много кодов, не читаемых пер­ вым. Файл, записанный с помощью программы WinLIRC, выг­ лядит следующим образом: Коды с пульта VCR Sony Прямое считывание, клавиша power
Модуль считывания ИК-кодов WinLIRC 205 Outputting raw mode2 data. space 12856572 pulse 2455 space 532 pulse 1291 space 506 pulse 664 space 533 pulse 1266 space 533 pulse 665 space 591 pulse 1211 space 533 pulse 685 space 515 pulse 693 space 526 pulse 1271 space 506 pulse 1265 space 533 pulse 666 space 557 pulse 1241 space 533 . pulse 664 space 24527 pulse 2463 space 579 pulse 1219 space 534 pulse 664 space 534 pulse 1266 space 534 pulse 666 space 531 pulse 1266 space 534 pulse 663 space 536 pulse 662 space 567
206 Глава • 1 Базовая версия Реально эта запись получается еще длиннее, если пульт при нажатии клавиши постоянно воспроизводит одну коман­ ду до тех пор, пока клавиша не будет отпущена (рис. 1.79). Рис. 1.79. считывание ИК-кода nporpaммoйWinURC Собственно, команда, интересующая нас, содержится в следующей записи: Output ting raw mode2 data. pulse 2455 ·space 532 pulse 1291 space 506 pulse 664 space 533 puls e 1266 space 533 pulse 665 space 591 pulse 1211 space 533
pulse 685 space 515 pulse 693 space 526 pulse 1271 space 506 pulse 1265 space 533 pulse 666 space 557 pulse 1241 space 533 pulse 664 space 24527 Модуль считывания ИК-кодов WinLIRC 207 Здесь pulse -вспышка излучателя с частотой, положим, 36 кГц, а space - пауза между вспышками. Раскрасим эту запись в соответствии с тем, что говорилось о кодах Sony выше: pulse 2455 Заголовок space 532 pulse 1291 Единица space 506 pulse 664 Ноль space 533 pulse 1266 Единица space 533 pulse 665 Ноль space 591 pulse 1211 Единица space 533 pulse 685 Ноль space 515 pulse 693 Ноль space 526 pulse 1271 Единица space 506 pulse 1265 Единица space 533 pulse 666 Ноль space 557 pulse 1241 Единица space 533