Здравствуйте. По долгу службы мне пришлось осваивать микроконтроллеры и ассемблер, я нашел замечательный сайт labkit.ru и взял оттуда несколько простых программ. Этот пример с бегущей строчкой. То есть светодиоды должны загораться по очереди, но на макетной плате загорается только первый светодиод и дальше ничего не происходит. Компиллировал в среде mplab 8.91, все скомпилировалось и прошилось нормально. Я неофит, поэтому пожалуйста, опишите подробно почему программа не работает как надо. вот текст программы взятый с сайта: LIST P=PIC16F84A __CONFIG H'3FF1' STATUS EQU H'0003' PORTB EQU H'0006' TRISB EQU H'0006' Reg_1 EQU H'000C' Reg_2 EQU H'000D' Reg_3 EQU H'000E' org 0 ; начало программы ; подготовительные моменты bsf STATUS,5 ; переход в Банк 1 clrf TRISB bcf STATUS,5 ; переход назад в Банк 0 clrf PORTB ; очистка порта bsf STATUS,0 ; установка нулевого бита в единицу
; установка сигналов на порту B m1 rlf PORTB,1 ; <<< сдвиг в регистре PORTB call Pause ; <<< goto m1 ; <<< переход на метку (зацикливание)
Во первых, код нужно публиковать в тегах кода, а не как простое сообщение. Во вторых, при написании программы на ассемблере нужно присоединять к исходнику хедер контроллера (inc-файл, где уже объявлены все специальные регистры), а так же оформлять конфиг не в виде магического числа, а в виде масок с именами бит (так же объявленных в хедере). Перепишу Ваш код хотя бы в теги.
Код:
LIST P=PIC16F84A __CONFIG H'3FF1' STATUS EQU H'0003' PORTB EQU H'0006' TRISB EQU H'0006' Reg_1 EQU H'000C' Reg_2 EQU H'000D' Reg_3 EQU H'000E' org 0 ; начало программы ; подготовительные моменты bsf STATUS,5 ; переход в Банк 1 clrf TRISB bcf STATUS,5 ; переход назад в Банк 0 clrf PORTB ; очистка порта bsf STATUS,0 ; установка нулевого бита в единицу
; установка сигналов на порту B m1 rlf PORTB,1 ; <<< сдвиг в регистре PORTB call Pause ; <<< goto m1 ; <<< переход на метку (зацикливание)
Затем, в среде стоит включить симулятор и пройти свой код по шагам. Это тут же даст ответ на Ваш вопрос. Но могу сказать, что двигать выходной порт - плохая идея. Нужно двигать переменную в ОЗу, которую выводить в порт.
Код:
init_var movlw 0x01 movwf Reg_4 m1 bcf STATUS, C rlf Reg_4, f ; <<< сдвиг в регистре регистре ОЗУ btfsc STATUS, C goto init_var movf Reg_4, w movwf PORTB call Pause ; <<< goto m1
Если кому интересно, я понял в чем проблема была. Калькулятор паузы Pause_ver1.2, который я использовал, выдавал неправильный код и при задержке более 700 машинных циклов пауза повторялась бесконечно.
LIST P=PIC16F84A __CONFIG H'3FF1' STATUS EQU H'0003' PORTB EQU H'0006' TRISB EQU H'0006' Reg_1 EQU H'000C' Reg_2 EQU H'000D' Reg_3 EQU H'000E' org 0 ; начало программы ; подготовительные моменты bsf STATUS,5 ; переход в Банк 1 clrf TRISB bcf STATUS,5 ; переход назад в Банк 0 clrf PORTB ; очистка порта bsf STATUS,0 ; установка нулевого бита в единицу
; установка сигналов на порту B m1 rlf PORTB,1 ; <<< сдвиг в регистре PORTB call Pause ; <<< goto m1 ; <<< переход на метку (зацикливание)
Вы наблюдаете это в симуляторе или косвенно на железе? То есть по шагам в симуляторе переменная становится равной нулю, а переход на return не происходит?
wr decfsz Reg_1, F goto wr decfsz Reg_2, F goto wr decfsz Reg_3, F goto wr
return
не по очереди, а по правилам математического счёта. Вот и посчитайте выдержку , хотя-бы, от регистра Reg_1, с учётом времени выполнения команд. У меня получилось много.. Так что программу паузы изменяйте. Для начала, выкиньте (закомментируйте) Reg_2 и оставьте крайние Reg_1 и Reg_3. Заносить какие-то данные в младший (Reg_1) регистр бесполезно. Считайте с нуля. А в старшем начните с двух, а потом, при необходимости, увеличивайте значение.
Код:
wr decfsz Reg_1, F goto wr ;decfsz Reg_2, F ;goto wr decfsz Reg_3, F goto wr
Не полинился симульнуть и всё сработало как и должно быть. По адресу 0СН=0 и есть переход.ТС наводиш тень на плетень. Задержка у него 0.5 сек. и о чём пишет Vovan555 , не понятно.
А что не понятного-то? В данной программе счётчики (регистры), это младший, средний и старший байты. Если-бы они работали по очереди, то их задержки складывались-бы. А так перемножаются. Плюс время выполнения программы счёта. Команда декрементирования - один машинный цикл. Команда перехода - два машинных цикла. Итого имеем, при значении в регистре 0, задержку в 770 машинных циклов. Если в младший регистр занесено значение ( в данном случае 85), то по достижении в младшем регистре нуля, откуда счёт начнётся в младшем? Правильно, с нуля: 00-FF-FE и т.д.. И до тех пор, пока счёт не закончится. Перед началом счёта начальные значения в счётчики заносятся, а во время выполнения счёта, кто вносить будет? Где это в программе?
Вы наблюдаете это в симуляторе или косвенно на железе?
И в симуляторе и на железе наблюдаю. Становится ли переменная равной нулю не понятно, но этот сегмент программы выполняется очень долго, хотя как заметил otest, должен выполняться пол секунды.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения