Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
Скачать 3.49 Mb.
|
). Выше текста программы, которая будет исполняться, расположена так называемая " шапка " программы Она нужна для того, чтобы можно было создать "прошивку " (HEX- файл. Если этой "шапки " не будет, то при ассемблировании , MPLAB "уйдет в решительный отказ ". В "шапке " программы указывается тип ПИКа (в данном случае, PIC16F84A ) и значения битов конфигурации (что переключают эти биты посмотрите в распечатке битов конфигурации. Примечание "шапка " программы - моя фантазия, которая облегчает процесс объяснения, так как шапка, она и есть шапка (то, что на самом верху. Устанавливаем биты конфигурации бит защиты CP выключен , сторожевой таймер WDT выключен , кварцевый генератор (используем кварц на мГц) работает в режиме стандартного генератора ( XT ). Разборки " с битами конфигурации будут позднее И тип ПИКа , и установленные биты конфигурации (а также "прописка " в программе регистров специального и общего назначения, разрешение на начало выполнения программы и ориентир конца программы - см ниже) "вводятся в эксплуатацию " так называемыми директивами (не путать с командами программы. О них будет рассказано ниже, а также ив других разделах "Самоучителя" (хорошего понемножку ". Сейчас "перенапряг " совсем ненужен. Далее, в "шапке " программы "прописываются " названия и адреса регистров специального назначения (см область оперативной памяти. Так как нужно только определить направление работы вывода порта В и далее работать только с этим выводом, то необходимо "прописать " названия и адреса регистров TRISB ( выбор направления работы выводов порта В ), PORTB (работа с защелками порта В ) и (необходимо переключение банков, так как регистр TRISB находится в 1- м банке ). Остальные регистры специального назначения "прописывать " ненужно, так как в программе они не задействованы (обращений к ним нет. Таким образом, в "шапке " программы, "прописываются " только те регистры специального назначения, которые задействуются в работе программы Далее , в "шапке " программы, "прописываются " адреса регистров общего назначения С ними нужно определиться В предыдущем разделе, речь шла о задержках Это как раз то, что нужно, так как в данном случае, необходима задержка на 100 мкс Для обеспечения такой малой задержки, достаточно одного регистра общего назначения Этот регистр будет участвовать ив процессе формирования нулевого уровня, ив процессе формирования единичного уровня (я называю это совмещением функций. 39 Назовем его, например, и с помощью директивы, назначим ему адрес в области оперативной памяти Например , 0Ch Всё Регистр "прописан ". В конце "шапки ", располагается директива, определяющая, с какого именно адреса памяти программ ( PC ) начать исполнение программы (обычно, org 0 С нулевого адреса) и команда перехода на начало исполнения программы (обычно, goto Start ). Так как команда расположена сразу же после директивы 0 (у команды нулевой адрес в памяти программ, то с этой команды и начнется исполнение программы Для более сложных программ, "шапка ", конечно же, более " объемна ", иона содержит в себе большее количество "прописанных " регистров и директив (в том числе и других типов. В "технологии " оформления "шапки " программы, ничего особо сложного нет Нужно только знать, что именно "прописывать ", то есть, нужно определиться с теми регистрами, которые будут задействованы походу исполнения программы Если содержимое "шапки " программы сейчас "мутно " (что вполне естественно, то ничего страшного далее это прояснится Просто сейчас нецелесообразно "уходить " в детальное обсуждение вопросов, связанных с "шапкой ", так как это может привести к "отклонению в сторону от генерального направления " затеянного мной объяснения Итак , приступаем к составлению программы После "срабатывания " команды Start она находится в конце "шапки " программы, происходит переход на первую команду рабочей части программы (адрес в счетчике команд 0001h). Она помечена словом, которое можно считать либо названием подпрограммы, либо меткой - кому как нравится Обычно , его считают стандартным названием подпрограммы (слово "старт " всем понятно. Далее, работаем в соответствии с "выстроенным скелетом " программы После инициализации ПИКа (по умолчанию, автоматически устанавливается 0- й банк Так как регистр "дислоцируется " в 1- м банке , то переходим в 1- й банк (а иначе, с регистром TrisB невозможно будет работать. Для этого нужно установить 5- й бит регистра Status в единицу Делаем это ( bsf Status,5 ). Так как направления работы выводов порта В RB1…RB7 нас не интересуют (они не задействованы, то проще всего установить все биты регистра в ноль (все выводы порта В работают "на выход "), то есть, записать в этот регистр константу 0. Примечание : по умолчанию, все выводы портов настроены на работу "на вход ". Так как напрямую записать константу в регистр (любой) нельзя, то "транспортировка " этого нуля, в регистр TrisB, производится через аккумулятор (через регистр, что Вы и видите в тексте программы ( movlw и TrisB ). В этом случае, задействуются байт- ориентированные команды Другой способ задействуем бит- ориентированную команду BCF В этом случаев ноль устанавливаются не все биты регистра, а только бит с номером ноль bcf TrisB,0 (сброс нулевого бита регистра TrisB в 0). На практике, чаще применяется первый вариант, так как в тех случаях, когда нужно перенастроить направления работы более 2- х выводов портов (такие случаи часты, можно обойтись минимальным количеством команд Всё Дело сделано Теперь вывод RB0 работает "на выход То есть, к нему подключился выход "своей " защелки Так как дальнейшие "манипуляции " будут производиться в нулевом банке, то возвращаемся в нулевой банк (устанавливаем 5- й бит регистра в 0: bcf Status,5 ). Все перечисленные выше операции, можно считать подготовительными То есть, подпрограмма Start начинается именно с таких операций А как же иначе Ведь к "боевым действиям " нужно подготовиться Для того чтобы осуществить декремент (или инкремент) содержимого регистра Sec ( вспомните про задержки, необходимо сначала определиться сего содержимым (какую "начальную точку отсчета " задавать. Предположим, что с этим содержимым мы определились в регистр Sec записывается число (почему именно оно см далее. Посмотрите в текст программы 40 Число .32 (точка - атрибут десятичной системы исчисления) является константой (то, что задается программистом. Напрямую " записать это число в регистр Sec (и вообще, в любой регистр) нельзя Эта операция осуществляется через "посредника " в виде регистра и Sec ). Число .32 в регистр Sec записано , ив дальнейшем, содержимое этого регистра (то есть, число) можно последовательно декрементировать (уменьшать на 1). Итак, все готово для управления защелкой RB0 порта В Формируем нулевой уровень на выводе RB0 Применяем бит - ориентированную команду BCF и указываем в ней нулевой бит регистра, который нужно сбросить в 0 ( bcf PortB,0 ). Все Дело сделано, и на выводе RB0, ноль зафиксируется до тех пор, пока мы его незаменим на 1 (вспомните о том , что защелка является банальным триггером, то есть, элементом оперативной памяти. Теперь нужно сделать так, чтобы с момента установки, на выводе RB0, нуля и до момента смены этого нуля на единицу, прошло ровно 100 мкс. Предположим, что с учетом того, что в регистр Sec , ранее была записана "нужная " константа, этот интервал времени сформирован Установка , на выводе RB0, единицы происходит также, как и установка нуля, только применяется команда ( bsf PortB,0 ). Точно таким же образом, как описано выше, для формирования, на выводе, единичного уровня, происходит запись, в регистр Sec , следующей константы Давайте разберемся, почему числовое значение константы, обеспечивающей формирование нулевого уровня, должно быть не абы какое, а .32 ? Применяется кварц на мГц, следовательно, один машинный цикл равен 1 мкс Таким образом, с момента установки, на выводе RB0, нуля и до смены его на единицу должно пройти 100 машинных циклов Подпрограмма задержки - циклическая Если результат декремента содержимого регистра Sec не равен нулю, то один "виток " этой подпрограммы будет отработан за 3 машинных цикла команда DECFSZ выполняется за один м ц ., а команда GOTO - за два Таким образом, уменьшение содержимого регистра на единицу происходит за 3 м ц (3 мкс .). Если результат декремента содержимого регистра Sec равен нулю, то команда GOTO не исполняется (вместо нее, виртуальный " NOP ), и выход из подпрограммы Pause_1 происходит за 2 м ц Следовательно , константе .32 соответствует хм ц. (мкс. К 95- ти , плюсуем 2 м ц двух команд, 2 м ц команд установки константы в регистр Sec для формирования времени единичного уровня на выводе ( movlw и Sec ) им ц команды установки, на выводе RB0, единицы ( bsf PortB,0 ). Получаем ровно 100 мкс. Теперь о двух NOP ах , которые стоят перед ПП Pause_1 Если сделать константу равной .33- м, то получится неустранимый "перебор " (рабочие команды из программы не выкинешь. Если константа равна .32- м, то получается устранимый "недобор " в 2 мкс, который устраняется добавлением двух NOP ов (дополнительная задержка на 2 мкс. После того, как результат декремента содержимого регистра Sec станет равным нулю, рабочая точка программы выйдет из этой " закольцовки " по сценарию программа исполняется далее. После этого, с целью обеспечения условий для дальнейшего формирования единичного уровняв течение ста мкс, в регистр Sec, необходимо записать "новую " константу Мотивация : "на влёте " в процедуру формирования единичного уровняв регистре "лежит " ноль Такая запись и имеет место быть ( movlw и Sec ). Различие числовых значений констант (.32 и .30) при формировании нулевого и единичного уровней, объясняется тем, что при формировании, на выводе, единичного уровня, исполняется команда (2 м ц .) и команды ПП Start в конце текста программы, осуществляется безусловный переход в ПП Start ). Кто имеет такое желание - посчитайте 41 Если такие расчеты пугают, то могу Вас успокоить в, с которой мы будем работать далее, имеется счетчик машинных циклов (секундомер "), и при отладке циклических подпрограмм, сего помощью, подобного рода трудозатраты существенно снижаются Разбираемся с директивами ассемблера . Директивы , в отличие от команд, не включаются в выходной код Выходной код - результат ассемблирования текста программы, а проще говоря, содержимое- файла (прошивки "), то есть, файла, предназначенного для открытия в программе , обслуживающей программатор Тогда зачем вообще нужны директивы Дело в том , что директивы, за "пределы " MPLAB (интегрированной среды разработки для ПИКов ), не выходят и исполняются только внутри MPLAB Те директивы, которые предназначены для применения в рабочей части программы (с учетом рабочей части директивы, имеют свои так называемые "разложения на команды ". То есть, одна такая директива как бы заменяет конкретную группу команд, которая автоматически (вставится ей в соответствие Если в тексте рабочей части программы имеется такая директива (элемент удобства " при составлении текста программы, то исполняется неона, а ее разложение на команды Точно также программа исполнится, если в тексте рабочей части программы заменить директиву на ее разложение на команды Если директива находится вне "границ " рабочей части программы (в "шапке " или директива, то естественно, что никакого ее разложения на команды не будет Вне рабочей части программы, до команды перехода на начало исполнения рабочей части программы ( goto Start ), MPLAB "понимает " директивы и "не понимает " команд Посмотрите в "шапку " программы до команды перехода на начало исполнения рабочей части программы, Вы не найдете ни одной команды Это "внутреннее дело " MPLAB (тайна сия велика есть. Смысл же состоит в том , что директивы, отрабатываемые вне рабочей части программы, либо обеспечивают подготовку ее исполнения, либо "обозначают ее границы ". Результаты всей этой "свистопляски закладываются в прошивку ", при ее создании Что касается директив рабочей части программы, то они, по существу, - элемент "оформительского " удобства, так как в случаях их применения, в тексте программы ненужно "расписывать " соответствующие им группы команд (разложения. MPLAB , без вмешательства программиста, "воткнет " это разложение в то место памяти программ, в которое его и нужно "воткнуть " и создаст соответствующий HEX файл (" прошивку "). Директивы можно уподобить администратору - распорядителю какого- то мероприятия Задача этого администратора перед началом "мероприятия " (рабочей части программы, для того чтобы оно прошло успешно, "расставить всё по своим местам ", а также ив "меру своих возможностей, поучаствовать в этом мероприятии ". Несмотря на большое количество всевозможных директив, на практике применяется ограниченное их количество Некоторые директивы : Директивы макроассемблера MPASM 1. 2. CBLOCK Определение блока констант. Используется для размещения нескольких констант в памяти программ и памяти данных Сначала указывается стартовый адрес для первой константы, последующие адреса декрементируются . Список заканчивается директивой ENDC. cblock 0x20 nameA,nameB адрес nameC,nameD адрес endc 3. END Окончание программы (конец всех команд) ………………………………. ………………………………. end Присваивает неизменное значение 42 4. 5. EQU константе. Присваивает значение константе, которое можно переопределить. set nameA equ 0x05 присвоить константе nameA 0x05 5. INCLUDE Подключение дополнительного исходного файла p16f84a.inc подключение файла с описаниями ; регистров спец. назначения. _ _CONFIG Установка битов конфигурации См . таблицу символов конфигурации. 8. CONSTANT Определение неизменной символьной константы Определение символьной константы, значение которой впоследствии можно переопределить. constant cnt=255 variable temp=0xF0 constant cnt1=cnt2+cnt3 9. ORG Установить начальный адрес программы. При отсутствии ORG программа начинается с нулевого адреса. метка org 0x20 вектор с адресом 20 метка org метка вектор с адресом 30 10. RADIX Система исчисления по умолчанию – 16, dec – 10, oct – 8) radix dec Обратите внимание на директивы, __CONFIG, ORG, Они используются практически во всех программах (примечание перед директивой CONFIG не одно, а 2 подчеркивания, идущих подряд) Есть они ив программе Multi.asm Найдите их в тексте этой программы, и Вы поймете что они "администрируют " распределяют, назначают и ограничивают ). Также обратите внимание на то, что с помощью директивы EQU, регистры TrisB и PortB прописаны " по одинаковым адресам (06h). С нулевым банком все понятно регистр PortB имеет в области оперативной памяти адреса вот регистр (первый банк) "прописан " не по адресу 86h, а все потому же адресу. В чем дело В адресах регистров специального назначения, ноль (устанавливается по умолчанию) меняется на восьмерку только тогда, когда программно осуществлен переход в 1- й банк Без учета этого, нумерация адресов регистров специального назначения обеих банков одинакова А раз это так, то регистр TrisB можно прописать не по адресу 86h, а по адресу 06h. После исполнения команды выбора 1- го банка, 06h автоматически "превращается " в 86h, что и нужно Такой способ "прописки " удобен тем, что в окне результата ассемблирования , будут отсутствовать сообщения информативного характера типа "сие лежит не в нулевом банке ", что намой взгляд, удобно Если прописать регистр TrisB по адресу 86h, то такие сообщения будут выдаваться Они не являются ошибками, но нервируют и отвлекают внимание Особенно на первых порах Рекомендую Вам , при "прописке " адресов регистров специального назначения 1- го банка, обозначенных, в области оперативной памяти, черным цветом, назначать им адреса по принципу типа " минус 80" , то есть, так, как сделано в программе Multi.asm (в части касающейся "прописки " регистра |