Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
Скачать 3.49 Mb.
|
; Примечание процесс преобразования заканчивается приуменьшении числа проходов преобразования, которые заложены в регистр Count (.32), до нуля. ;================================================================================ ; Циклический сдвиг влево. ;================================================================================ Loop16 rlf TimerL,F ; Циклический сдвиг влево 4- байтного двоичного rlf TimerM,F ; числа, записанного в группе регистров rlf TimerH,F ; на одну позицию rlf TimerHH,F ; через бит С регистра STATUS. rlf LED0,F ; Циклический сдвиг влево 4- байтного двоичного rlf LED1,F ; числа, записанного в группе регистров rlf LED2,F ; LED0/LED1/LED2/LED3, на одну позицию через rlf LED3,F ; бит С регистра STATUS . decfsz Count,F ; Декремент (-1) содержимого регистра Count с ; сохранением результата в нем же. goto adjDEC ; Если результат не, то переход в ПП adjDEC ; Если результат =0, то программа исполняется ; далее. ;================================================================================ ; Поразрядное распределение содержимого регистров LED0...3 (обоих 259 ; полубайтов) по младшим полубайтам регистров LED0...7. ;================================================================================ swapf LED3,W ; Запись старшего полубайта LED3 andlw 0Fh ; в младший полубайт LED7. movwf LED7 ; -------------------------------- movfw LED3 ; Запись младшего полубайта LED3 andlw 0Fh ; в младший полубайт LED6. movwf LED6 ; -------------------------------- swapf LED2,W ; Запись старшего полубайта LED2 andlw 0Fh ; в младший полубайт LED5. movwf LED5 ; -------------------------------- movfw LED2 ; Запись младшего полубайта LED2 andlw 0Fh ; в младший полубайт LED4. movwf LED4 ; -------------------------------- swapf LED1,W ; Запись старшего полубайта LED1 andlw 0Fh ; в младший полубайт LED3. movwf LED3 ; -------------------------------- movfw LED1 ; Запись младшего полубайта LED1 andlw 0Fh ; в младший полубайт LED2. movwf LED2 ; -------------------------------- swapf LED0,W ; Запись старшего полубайта LED0 andlw 0Fh ; в младший полубайт LED1. movwf LED1 ; -------------------------------- movfw LED0 ; Запись младшего полубайта LED0 andlw 0Fh ; в младший полубайт LED0. movwf LED0 ; -------------------------------- ;-------------------------------------------------------------------- ; Конец распределения. В младших полубайтах регистров LED0...7 установлены двоично - десятичные числа в порядке возрастания разрядности. ; Старшие полубайты = 0. ;-------------------------------------------------------------------- return ; Переход по стеку в группу подпрограмм ; разрядной динамической индикации. ;================================================================================ ; Запись в регистр FSR адресов регистров LED0...3 для дальнейшей косвенной адресации к ним в ПП adjBCD. ; Переход к обработке следующего LED - после возврата по стеку. ;================================================================================ adjDEC movlw LED0 ; Запись в регистр FSR, через регистр W, movwf FSR ; адреса регистра LED0 с дальнейшим переходом call adjBCD ; в ПП adjBCD (адрес следующей команды ; закладывается в стек ). ;---> Возврат по стеку из ПП adjBCD. movlw LED1 ; ----------------------------- movwf FSR ; Тоже самое для регистра LED1. call adjBCD ; ----------------------------- ;---> Возврат по стеку из ПП adjBCD. movlw LED2 ; ----------------------------- movwf FSR ; Тоже самое для регистра LED2. call adjBCD ; ----------------------------- ;---> Возврат по стеку из ПП adjBCD. movlw LED3 ; ----------------------------- movwf FSR ; Тоже самое для регистра LED3. call adjBCD ; ----------------------------- ;---> Возврат по стеку из ПП adjBCD. goto Loop16 ; Проход всех LED (с LED0 по LED3). Переход в ; ПП Loop16, то есть наследующее кольцо ; числовых преобразований. ;================================================================================ 260 ; Основные операции преобразования двоичных чисел в двоично - десятичные : ; операции сложения LED0...3 и констант 03h,30h с условиями по 3- му и 7- му битам. ;================================================================================ adjBCD movlw 3 ; Сложить содержимое текущего LED (LED0...3) с addwf 0,W ; числом 03h, c записью результата операции movwf Mem ; через регистр W, в регистр Mem. btfsc Mem,3 ; Анализ состояния го бита регистра Mem. movwf 0 ; Если бит 3 =1, то содержимое регистра Mem ; копируется в текущий LED. movlw 30 ; Если бит =0, то содержимое текущего LED addwf 0,W ; складывается с константой 30h, с последующей movwf Mem ; записью результата операции , через регистр W, ; в регистр Mem. btfsc Mem,7 ; Анализ состояния го бита регистра Mem. movwf 0 ; Если бит =1, то содержимое регистра Mem ; копируется в текущий LED. retlw 0 ; Если бит =0, то регистр W очищается и ; происходит возврат по стеку в ПП adjDEC. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ГРУППА КОМАНД ПРЕОБРАЗОВАНИЯ ДВОИЧНО - ДЕСЯТИЧНОГО КОДА В КОД СЕГМЕНТНОГО ИНДИКАТОРА (относится к группе подпрограмм динамической индикации. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TABLE addwf PC,F ; Содержимое счетчика команд PC увеличивается ; на величину содержимого аккумулятора W. retlw b'00111111' ; ..FEDCBA = Происходит скачек по таблице retlw b'00000110' ; .....CB. = на строку со значением, retlw b'01011011' ; .G.ED.BA = записанным в аккумуляторе , retlw b'01001111' ; .G..DCBA = и далее - возврат по стеку retlw b'01100110' ; .GF..CB. = 4 retlw b'01101101' ; .GF.DC.A = 5 retlw b'01111101' ; .GFEDC.A = 6 retlw b'00000111' ; .....CBA = 7 retlw b'01111111' ; .GFEDCBA = 8 retlw b'01101111' ; .GF.DCBA = 9 ;******************************************************************************** end ; Конец программы. Все что Вы видите, было "разобрано " ранее Сразу бросается в глаза "разросшаяся шапка " программы, что вполне естественно Регистр Count так же, как и регистр Temp , задействуется многократно (в данном случае, 2 раза. Если Вы проассемблируете текст программы, то получите сообщение о 7- ми ошибках, что вполне закономерно, так как в тексте этой программы, значения трех констант выражены в символьном виде ( X , Y1 , Y2 ). Это 3 "ненормальности ", которые "воспринимает " как ошибки Остальные 4 ошибки связаны с "непонятностью " того, к чему обращается директива (....) и "непонятностью " первой команды ПП START (....). Если символьные константы, Y1 , будут заменены на числа, директива CONFIG будет обращаться к "нормальному " числу (например 03FF1H) и будет определена 1- я команда ПП START , то никаких сообщений об ошибках не будет Если Вы хотите перейти к другому количеству знакомест линейки, то руководствуйтесь изложенной ранее информацией, в которой "расписан " принцип такого перехода Числовые значения констант, Y1 , определяет программист, исходя из стоящих передним задач На что влияют эти числовые значения, указано ранее Если изложенные выше методики "трансформации " этой универсальной "заготовки " освоены и понятны , то после достижения желаемого, ее нужно "доукомплектовать " подпрограммой формирования- байтного (определяет программист, двоичного числа "Конструкция " этой ПП может быть различной В N - байтное , двоичное число можно "загнать " любой параметр внешнего (по отношению к микроконтроллеру ) сигнала Выбор богатейший 261 Таким образом, в том , что я назвал Группой подпрограмм формирования 4(N) - байтного двоичного числа, "сконцентрирован " очень объемный класс задач, на решение которых, в большинстве случаев, и направлены основные усилия программиста Объем этого класса задач велики могуч, но "набор приемов ", который позволяет эффективно их решать, конечен Освоение этих приемов - вполне посильная работа Вы познакомились сих частью (многие приемы универсальны, а это уже вполне приличный старт Если Вы , с первого захода, поняли хотя бы 50% из того, о чем шла речь, то это уже несомненный успех Программирование – "дело наживное " и совсем не "шапкозакидательское ". Если не получается, то повторите "заходы ", и при наличии " упёртости ", рано или поздно, "все встанет на свои места ". Противник грозный и очень достойный Он , по определению, будет сопротивляться И это нужно как следует понимать Несколько "голов ", у этого "многоголового дракона, мы посшибали ". Давайте " посшибаем " еще " Самоучитель по программированию PIC контроллеров для начинающих" http://ikarab.narod.ru E-mail: karabea@lipetsk.ru 262 17. Принцип счета Работа с таймером TMR0. Принцип установки групп команд счета в текст программы Как это не странно, но изложенная ниже информация, почему- то, образно выражаясь, является "страшно секретной ". В том смысле, что в свое время, мне таки не удалось найти более- менее "внятной " информации по высокоскоростному счету Это вынудило хорошенько " поднапрячься ". А куда деваться Заниматься программированием и игнорировать "базу ", это нонсенс Ниже предпринята попытка достаточно подробного (как мне кажется) описания механизма низкоскоростного и высокоскоростного счета, рассчитанная на начинающих программистов, усвоивших предыдущие разделы Низкоскоростной счет Первичная информация о таймере TMR0 и принципе счета, основанном на его применении, была изложена ранее Казалось бы, все просто при работе от внешнего источника импульсов, подсчитывается количество переполнений Оно умножается на 256, и к этому произведению приплюсовывается число, находящееся в TMR0 на момент окончания счета Примечание : речь о низкоскоростном счете идет в том случае, когда для подсчета импульсов применяется только (без предделителя ). Сигнал от внешнего источника сигнала, на вход TMR0, подается через синхронизатор Функцией синхронизатора является синхронизация сигнала, поступающего от внешнего источника сигнала, с внутренней , тактовой частотой м / контроллера В связи с этим , период сигнала, поступающего от внешнего источника сигнала, не должен быть менее 4- х периодов внутреннего такта Например , при применении кварца номиналом 4 Мгц ., период сигнала, поступающего от внешнего источника сигнала, не должен быть менее 1 мкс, и это есть "граница ", за которую "заходить " нельзя Таким образом, при использовании кварца номиналом 4 Мгц ., не может работать с частотами выше 1 Мгц Плюс , при приближении к этой "границе ", нужно будет организовывать достаточно частые проверки на переполнение, и для хранения результатов подсчетов переполнений, одного регистра будет маловато Не смотря на то, что по способу своей организации, низкоскоростной счет достаточно прост ( задействуется только, но он, по причинам указанным выше, не находит широкого применения Каков выход Выход в использовании предделителя Например , если использовать предделитель с максимальным коэффициентом деления (256), то переполнение TMR0 наступит через х импульсов Если измерять частоту 30 Мгц ., то 65536 импульсов "проскочат " примерно за 2,2 мс, что уже есть " зер гут " (прикиньте, сколько команд можно исполнить за 2200 мкс. По причине того, что в случае использования предделителя , счетным входом ПИКа является несчетный входа вход предделителя , условия нормального функционирования обеспечиваются даже при подсчете импульсов с большой частотой следования И количество проверок на переполнение TMR0 резко сокращается Мало того, при таком "раскладе ", можно даже поднять частотную, "программную границу " максимальную скорость счета, на которую рассчитана программа) выше частотной, аппаратной границы " ПИКа (максимальной скорости счета, на которую рассчитан ПИК ). Высокоскоростной счет Для того чтобы было понятно, с чем мы имеем дело, есть смысл кое- что напомнить и добавить Таймер TMR0 представляет собой делитель на 256. 263 Это означает, что "чистый " TMR0 (без использования предделителя ) будет переполняться каждый раз после поступления на его счетный вход (вывод) "пачки " из 256 импульсов (при переходе от .255 к .00). считает только в одну сторону (реверса нет, а именно , в сторону увеличения Если в качестве "предмета счета ", выбран внешний тактовый сигнал, присутствующий на выводе, то подсчитывается количество импульсов, формируемых внешним источником импульсов Примечание : "внешний тактовый сигнал " буду называть "внешним тактом ". Так короче В случае выбора внешнего такта, импульсы внутреннего такта ( CLKOUT ) не подсчитываются ( и наоборот. всегда включен Выключить его нельзя По этой причине, для того чтобы, при наличии импульсной последовательности на выводе выбран внешний такт, остановить или разрешить счет, нужно заблокировать или разблокировать счетный вход ПИКа (вывод. То есть, примитивно выражаясь, его нужно либо "закоротить " на корпус, либо снять этот "коротыш " (с этим, детально разберемся позднее, "а пока итак сойдет "). Для этого, выводы ( блокировка / разблокировка ) и (счетный вход ПИКа ) электрически соединяются между собой, и блокировка осуществляется программно То есть, если на выводе (можно использовать и другой вывод порта) устанавливается 0 блокировка, то это соответствует остановке счета, а если 1 ( разблокировка ), то это соответствует разрешению счета Критерием переполнения TMR0 является флаг прерывания по переполнению TMR0 ( бит № 2 регистра INTCON с названием. Поднятие этого флага (1) свидетельствует о факте переполнения, а его "опущение " (0. Извиняюсь за неблагозвучие) свидетельствует о том , что переполнения TMR0 нет В определении флага T0IF, упоминаются прерывания, но этот флаг работает независимо оттого, разрешены или запрещены прерывания по переполнению TMR0 То есть, если прерывания по переполнению TMR0 запрещены , то флаг T0IF тоже будет "полноценно " работать Флаг T0IF относится к флагам 2- й группы То есть, после того как он поднялся (1), и факт этого события подсчитан (" задокументирован "), в конце процедуры проверки TMR0 на переполнение, флаг T0IF нужно опустить (0), а иначе , результат следующей ( их ) проверки ( ок ) на переполнение, будет необъективен Напоминаю о том , что все флаги 2- й группы опускаются только программно Разбираемся дальше Для того чтобы разговор был предметным, речь пойдет о частотомере "Привяжусь " к 3- байтному результату подсчета импульсов Результаты этого подсчета будут записываться в 3- байтный регистр TimerH/TimerM/TimerL Иными словами, после завершения подсчета, в этом регистре, с соблюдением порядка старшинства, "осядет " 3- байтное , двоичное число результата измерения частоты Интервал времени измерения 0,1 сек (100000 мкс. Максимальная, измеряемая частота 30 Мгц ( паспортная , максимальная частота, которую "способен воспринять " счетный вход. Разрядность линейки сегментных индикаторов десятичных разрядов (знакомест. Погрешность измерения 10 гц . Рассмотрим случай подсчета импульсов импульсной последовательности с частотой 30 Мгц Обращаю Ваше внимание на то, что в этом случае, речь идет не о подсчете 30 000 000 импульсов, а о подсчете 000 импульсов, так как интервал времени измерения составляет не 1 сек, а |