Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
Скачать 3.49 Mb.
|
Index , который является счетчиком количества малых колец индикации Он "встроен " в цикл малого кольца индикации и инкрементируется в конце интервала времени активации, с последующим анализом его содержимого В числовом диапазоне от .00 до .07, рабочая точка программы последовательно "отматывает " 8 малых колец индикации В начале 9- го кольца (число .08), текущий, полный цикл большого кольца индикации заканчивается Сразу же после этого, начинается формирование "нового ", большого кольца индикации, вначале которого, число .08, "лежащее " в регистре Index , сбрасывается в 0. А теперь предположим, что динамическая индикация организована Но ведь это жене самоцель А отображать - то что Если рабочая точка программы все время, пока устройство включено, будет "мотать кольца " в подпрограмме динамической индикации, не выходя из нее, то такое устройство и даром ненужно Это как в "12- ти стульях ": "Все это великолепие разбивалось о вывеску Штанов нет ". Вывод : рабочая точка программы, "сделав все дела " в подпрограмме динамической индикации, должна из нее выйти, для того чтобы каким- то образом (вариантов может быть много, в других подпрограммах и группах команд, не относящихся к подпрограмме динамической индикации, сформировать число, которое нужно отобразить в линейке В интервале времени между моментом выхода рабочей точки программы из ПП динамической индикации и моментом ее очередного " влёта " в ПП динамической индикации, программа должна сформировать данные, которые нужно вывести на индикацию Из этого следует простой вывод необходимо ограничить "пребывание " рабочей точки программы в ПП динамической индикации Вопрос : "Каким образом "? Ответ напрашивается сам собой Количество больших циклов индикации нужно "поставить на счетчик ". Покрутилась " (речь идет о рабочей точке программы) в ПП динамической индикации определенное количество больших циклов индикации Будь добра, покинь ее и подготовь то, что нужно вывести на индикацию в следующем , полном цикле программы Вот тогда и снова "милости просим ". Советую Вам представить себе рабочую точку программы в виде живого существа, которое, для того чтобы оно не сотворило чего- то нехорошего, нужно постоянно учить уму- разуму и опекать Срабатывает на все стона себе проверил. Итак, для того чтобы ограничить время пребывания рабочей точки программы в ПП динамической индикации, в качестве счетчика количества больших колец индикации, нужно назначить регистр общего назначения, предварительно (до " влёта " в цикл большого кольца индикации) записать в него константу (заданное количество больших колец индикации) ив конце цикла большого кольца индикации, декрементировать его содержимое Если результатом декремента будет являться число отличное от 0, то рабочая точка программы "улетит " на начало следующего цикла большого кольца индикации 228 После того как в счетчике будет обнаружен 0 (заданное количество циклов отработано, отрабатывается сценарий "программа исполняется далее " (выход из ПП динамической индикации. Подобное уже описывалось ранее, так что ничего нового в этом нет Итак , терминология такая - малое кольцо динамической индикации, - большое кольцо динамической индикации, - полный цикл динамической индикации, - полный цикл программы Почему "полный цикл динамической индикации ", а не "полное кольцо динамической индикации "? Потому, что полный цикл динамической индикации не является кольцом В противном случае, рабочая точка программы не сможет выйти из ПП динамической индикации По факту, " закольцовка "есть, но только через полный цикл программы А теперь , начиная с малого кольца индикации, в общем виде, представьте себе, как именно происходит движение рабочей точки программы, и какие "фигуры высшего пилотажа " она "проделывает ". Если будут затруднения, то еще раз повнимательнее прочитайте то, о чем говорилось выше Прежде чем перейти к деталям , осталось выяснить, каким должно быть соотношение времени отработки полного цикла динамической индикации, к времени отработки полного цикла программы В идеале , это соотношение должно быть чуть меньше 1 (больше чем 1, оно быть не может. То есть, величина интервала времени между моментом выхода рабочей точки программы из ПП динамической индикации и моментом начала следующего, полного цикла динамической индикации, должна быть как можно меньшей Проще говоря, рабочая точка программы, в интервале времени отработки большей части полного цикла программы, должна находиться в ПП динамической индикации, а всё остальное должно отрабатываться очень быстро Дело в том , что, после отработки ПП динамической индикации, и до начала "нового ", полного цикла динамической индикации, процесс динамической индикации прерывается Не трудно догадаться, что при этом, в линейке будет "высвечиваться " содержимое одного знакоместа, а остальные будут "погашены " (пассивны. При выходе из ПП динамической индикации, можно "погасить " и это знакоместо, но смысл в этом небольшой, так как это практически не уменьшает эффект " мерцаний ". В любом случае, периодическая "пассивность " подпрограммы динамической индикации приводит к " мерцаниям / морганиям " показаний, с периодом равным интервалу времени отработки полного цикла программы Для того чтобы максимально ослабить негативные последствия " мерцаний ", необходимо максимально уменьшить время этого "моргания ", то есть, стремиться к тому , чтобы та часть программы, которая не относится к ПП динамической индикации, отрабатывалась как можно быстрее То есть, в этой "части ", в идеале , должны отсутствовать подпрограммы задержек, и количество команд должно быть минимальным Первое актуальнее, чем второе По причине того, что интервал времени, формируемый даже одной ПП задержки , может многократно превышать интервал времени отработки всех остальных команд, указанного выше, участка программы А если ПП задержек несколько и они "массивны " (по суммарному времени отработки Получим "сильнейшие моргания / мерцания ". Вывод в идеале : при разработке программы, в состав которой входит ПП динамической индикации, необходимо сделать так, чтобы в состав "участка пассивности " подпрограммы динамической индикации не входила ни одна ПП задержки , ион был "линейными коротким ". На практике, такое возможно сделать только в простых программах По мере возрастания их сложности, программист вынужден будет идти на компромисс И еще одна особенность, связанная с ПП динамической индикации Предположим , что разрабатывается измерительное устройство, с отображением результатов измерений в линейке , состоящей из 7- сегментных индикаторов Например , частотомер 229 Следовательно, нужно сформировать, довольно- таки значительный, интервал времени измерения Если ПП динамической индикации будет работать отдельно от группы программ формирования интервала времени измерения, то соотношение времени отработки полного цикла динамической индикации, к времени отработки полного цикла программы, очень сильно ухудшится, что приведет к сильнейшим " мерцаниям ". Вопрос "Как выйти из этого затруднительного положения" Ответ : цикл динамической индикации должен отрабатываться внутри цикла формирования интервала времени измерения, то есть, входить в его состав В этом случае, "и волки сыты и овцы целы " (совмещение функций. Как это делается В сущности , это делается очень просто В начале полного цикла динамической индикации, время отработки которого калибровано ( не "гуляет "), счетный вход микроконтроллера разблокируется (начало счета, а после окончания отработки полного цикла динамической индикации, блокируется (конец счета. С таким расчетом, чтобы интервал времени, между моментом разблокировки счетного входа и моментом его блокировки, был в точности равен значению измерительного интервала времени Интервал времени отработки полного цикла динамической индикации нужно сделать несколько меньшим, чем минимальный (если их несколько) интервал времени измерения Это обусловлено тем, что сразу же после окончания отработки полного цикла динамической индикации и до момента блокировки счетного входа микроконтроллера (окончания счета, нужно произвести точную "доводку " (калибровку) интервала времени измерения до требуемой величины В состав ПП динамической индикации должны входить команды ветвления, обеспечивающие, в "границах " полного цикла динамической индикации (ноне вне их, соответствующие " закольцовки ". А теперь , после того как сформированы общие представления о принципах работы подпрограмм динамической индикации, займемся деталями Работаем с текстом программы Fsr.asm На "шапке " программы останавливаться не буду (ничего нового нет. В ней "прописано " все то, что используется в рабочей части программы ПП START - стандартная (подготовительные операции С учетом специфики разрабатываемого устройства. Далее следует ПП преобразования двоичных чисел в двоично - десятичные Обоснование нужности этой ПП было дано ранее, а "разборки " с ней будут позднее Для определенности, нужно "привязаться к начальной точке отсчета ". То есть, дать ответ на вопрос "Какое знакоместо линейки, после влёта рабочей точки программы, в ПП динамической индикации, нужно активизировать первым" Обычно, начинают с самого младшего знакоместа (разряда, что и имеет место быть Содержимое счетчика малых колец индикации сбрасывается в 0 ( clrf Index ). Перед " влётом " в малое кольцо индикации, в счетчик количества больших колец индикации Count, нужно записать константу То есть, количество больших колец индикации, которые должна "отмотать " рабочая точка программы для того, чтобы выйти из полного цикла динамической индикации (по сценарию "программа исполняется далее "). Константа указана в общем виде ( X ). Ее числовое значение определяет программист Далее , по тексту программы, Вы видите общую "точку входа " в малое и большое кольца индикации, которой является первая команда ПП CYCLE ( movlw LED0 ). Посмотрите в "шапку " программы Вы увидите, что в ней "прописаны " 8 регистров общего назначения ... LED7 В них , с соблюдением порядка старшинства, хранятся двоично- десятичные числа, которые, в дальнейшем , нужно "протащить " через ПП кодировки и после этого, вывести на индикацию Эти числа записываются в них еще до " влёта " рабочей точки программы в ПП динамической индикации (а именно, после отработки ПП преобразования двоичных чисел в двоично - десятичные. 230 В интервале времени отработки полного цикла динамической индикации, их содержимое не меняется (в них ничего не записывается. Их содержимое только последовательно считывается В тексте программы, Вы видите только обращение к регистру LED0 Куда "испарились " остальные 7 регистров ( LED1 ... LED7 ), ведь в тексте программы, прямых обращений к ним нет Эти "чудеса " называются косвенной адресацией Прежде всего, к ней нужно подготовится Необходимость этой подготовки обусловлена тем, что после каждого перехода, с предыдущего малого кольца индикации, на последующее, нужно активировать следующее ( по старшинству) знакоместо То есть, принципом динамической индикации Команда movlw является "хитрой " командой По определению, с ее помощью, в регистр W, должна быть записана некая константа, но только где она На ее "месте " находится LED0 Вопрос : "Какая же это константа "? Ответа самая что ни наесть натуральная Посмотрите в "шапку " программы Регистру LED0, директивой equ , присвоен адрес 10h. Это и есть константа В этом случае, MPLAB "видит " не название регистра, а его адрес Таким образом, в регистр W, записывается адрес регистра LED0. То есть, командой задается "начальная точка отсчета ", к которой , через процедуру косвенной адресации, осуществляется "привязка " адресов всех остальных LED ов Содержимое регистра, от цикла к циклу малого кольца индикации, будет инкрементироваться , последовательно возрастая от .00 до .08. Следовательно, если в каждом цикле малого кольца индикации, производить суммирование фиксированной константы 10h (адрес регистра) и содержимого регистра Index,W ), то от цикла к циклу малого кольца индикации, результат суммирования ( сохраняется в регистре W ) будет последовательно увеличиваться от 10h до 17h. Почему не до 18h? Потому, что "появление ", в регистре Index , восьмерки , есть критерий сброса его содержимого в 0, который происходит в самом начале ее (восьмерки) "появления ". Таким образом, входе отработки ПП динамической индикации, в регистре W , будет происходить последовательный перебор (по кольцу) адресов регистров ... Зачем это нужно и "к какой стенке прислонить " содержимое этих регистров Чтобы ответить на этот вопрос, нужно поподробнее разобраться стем, что называется косвенной адресацией В части касающейся байт- ориентированных команд (команды работы с константами не в счёт ), до сих пор, использовалась только прямая (непосредственная) адресация, при которой команда обращается к названию регистра Косвенная адресация есть способ обращения к содержимому регистра, посредством выбора его адреса (название регистра не указывается ). К командам работы с константами это не относится Эта нужная, но "темная лошадка " многим попортила нервы, так что имеет большой практический смысл с ней разобраться Кроме того, косвенная адресация – "вещь " исключительно полезная, так как очень часто, ее применение позволяет заменить "громоздкие " процедуры на более "компактные " (выигрыш по количеству команд, причем, без изменения функциональности Косвенная адресация начинается с копирования (через регистр, из области оперативной памяти, в регистр специального назначения с названием FSR , адреса регистра, содержимое которого, в дальнейшем , будет использоваться Регистр FSR задействуется только при косвенной адресации Естественно , что до исполнения команды FSR , адрес этого регистра должен быть записан в регистр W см LED0 ). В данном случаев регистр, на самом первом "витке " малого кольца индикации, записывается число 10h, и далее , входе отработки ПП динамической индикации, в регистр W, будут последовательно и по кольцу, записываться числа в диапазоне от 10h до 17h 231 адреса регистров ... LED7 ). Сразу же после записи, в регистр W , любого из этих чисел, оно копируется, из регистра, в регистр FSR ( movwf FSR ). Это приводит к тому , что походу отработки ПП динамической индикации, в регистре FSR , происходит последовательный "перебор " адресов (по кольцу) тех регистров, содержимое которых, в дальнейшем , будет использоваться Для того чтобы скопировать (считать) содержимое регистра с адресом , указанным в регистре FSR , в регистр W для дальнейшего использования, нужно выполнить команду То есть, обращение к регистру Indf соответствует обращению к содержимому того регистра, адрес которого записан в регистре FSR . Для удобства, можно коварно перефразировать так команда Indf,W обращается не к "регистру " Indf (чистая подстава ", так как он физически не реализован Просто "кнопка, которая включает действие "), а к содержимому того регистра, адрес которого "лежит " (на момент обращения кв регистреbFSRbРегистр специального назначения, также, как и регистр специального назначения, задействуется только при косвенной адресации Оба они находятся в 0- м банке и отображаются в 1- м банке , так что работать сними можно, не забивая себе голову " выборами банков Итак , в результате работы первых 4- х команд ПП CYCLE , на каждом "витке " малого кольца индикации, в регистр W, будет по очереди, последовательно копироваться содержимое регистров ... Содержимое 8- ми регистров ... представляет собой 8 двоично- десятичных чисел, в диапазоне от .0 до .9 (с "привязкой " к порядку старшинства, значения которых, после перекодировки, нужно последовательно отобразить в соответствующих знакоместах Это мы уже проходили Вспомните ПП TABLE , в которой осуществляется перекодировка двоично- десятичного кода в код 7- сегментных индикаторов (программа " addwfpc.asm ). В регистре W, находится то, что нужно перекодировать Останавливаться на этом я не буду (см программу. Только что мы рассмотрели пример организации косвенной адресации с обращением к таблице данных То же самое можно сделать и без использования косвенной адресации, нов этом случае, количество команд возрастет, и весьма существенно Для "входа в таблицу ", используется команда условного перехода |