Поклонники продукции Microchip Technology Inc тусуются тут.
Вс апр 21, 2019 09:27:23
Здравствуйте. По долгу службы мне пришлось осваивать микроконтроллеры и ассемблер, я нашел замечательный сайт 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 ; <<< переход на метку (зацикливание)
;delay = 500000 machine cycles
Pause movlw .85
movwf Reg_1
movlw .138
movwf Reg_2
movlw .3
movwf Reg_3
wr decfsz Reg_1, F
goto wr
decfsz Reg_2, F
goto wr
decfsz Reg_3, F
goto wr
return
end ; конец программы
Вс апр 21, 2019 12:09:02
Во первых, код нужно публиковать в тегах кода, а не как простое сообщение.
Во вторых, при написании программы на ассемблере нужно присоединять к исходнику хедер контроллера (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 ; <<< переход на метку (зацикливание)
;delay = 500000 machine cycles
Pause movlw .85
movwf Reg_1
movlw .138
movwf Reg_2
movlw .3
movwf Reg_3
wr decfsz Reg_1, F
goto wr
decfsz Reg_2, F
goto wr
decfsz Reg_3, F
goto wr
return
end ; конец программы
Затем, в среде стоит включить симулятор и пройти свой код по шагам. Это тут же даст ответ на Ваш вопрос.
Но могу сказать, что двигать выходной порт - плохая идея. Нужно двигать переменную в ОЗу, которую выводить в порт.
- Код:
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
Вс апр 21, 2019 15:36:25
Да и IDE последняя (под старые компы с ХР) не 8.91, а 8.92....
И помимо *.inc еще и линкер скрипт *_g.lkr в проекте указывать надо...
Вс апр 21, 2019 17:10:41
Скрипт линкера для MPASM не обязателен.
Пн апр 22, 2019 06:35:57
...на макетной плате...
Проверить макетную плату.
Вт апр 23, 2019 07:28:45
Затем, в среде стоит включить симулятор и пройти свой код по шагам.
Симулятор выполняет код нормально, ошибок не находит
Ср апр 24, 2019 12:52:00
Если кому интересно, я понял в чем проблема была. Калькулятор паузы Pause_ver1.2, который я использовал, выдавал неправильный код и при задержке более 700 машинных циклов пауза повторялась бесконечно.
Ср апр 24, 2019 12:59:21
А я ни чего не понял.
Ср апр 24, 2019 13:14:09
И я. Объясни.
Ср апр 24, 2019 14:05:21
Ну когда симулятор доходил до сегмента паузы он зацикливался на строчках
- Код:
wr decfsz Reg_1, F
goto wr
выполнял их по очереди и дальше не шел
я даже осциллографом проверил, если пауза менее 1 милисекунды ноги выдают прямоугольные импульсы, если больше, то сигнал постоянный
в чем же проблема, господа программисты, помогите понять?
Последний раз редактировалось
Сиддха Ср апр 24, 2019 14:20:33, всего редактировалось 1 раз.
Ср апр 24, 2019 14:11:41
Должен идти , только не куда.
Ср апр 24, 2019 14:23:01
как это некуда
Ср апр 24, 2019 14:28:44
а куда ???
Ср апр 24, 2019 14:51:26
а куда ???
вот же в начале я код писал
- Код:
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 ; <<< переход на метку (зацикливание)
;delay = 500000 machine cycles
Pause movlw .85
movwf Reg_1
movlw .138
movwf Reg_2
movlw .3
movwf Reg_3
wr decfsz Reg_1, F
goto wr
decfsz Reg_2, F
goto wr
decfsz Reg_3, F
goto wr
return
end ; конец программы
на этих строчках зацикливается
- Код:
wr decfsz Reg_1, F
goto wr
команда decfsz подразумевает вычитание из f единицы, а когда f достигает нуля то пропускается следующая строчка. но почему то этого не происходит
Ср апр 24, 2019 15:13:09
но почему то этого не происходит
Вы наблюдаете это в симуляторе или косвенно на железе? То есть по шагам в симуляторе переменная становится равной нулю, а переход на return не происходит?
Ср апр 24, 2019 15:19:02
выполнял их по очереди и дальше не шел
МК выполняет команды
- Код:
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
return
Ср апр 24, 2019 15:24:00
Не полинился симульнуть и всё сработало как и должно быть. По адресу 0СН=0 и есть переход.ТС наводиш тень на плетень.
Задержка у него 0.5 сек. и о чём пишет Vovan555 , не понятно.
Ср апр 24, 2019 17:34:36
А что не понятного-то?
В данной программе счётчики (регистры), это младший, средний и старший байты. Если-бы они работали по очереди, то их задержки складывались-бы. А так перемножаются.
Плюс время выполнения программы счёта.
Команда декрементирования - один машинный цикл. Команда перехода - два машинных цикла. Итого имеем, при значении в регистре 0, задержку в 770 машинных циклов.
Если в младший регистр занесено значение ( в данном случае 85), то по достижении в младшем регистре нуля, откуда счёт начнётся в младшем? Правильно, с нуля: 00-FF-FE и т.д.. И до тех пор, пока счёт не закончится.
Перед началом счёта начальные значения в счётчики заносятся, а во время выполнения счёта, кто вносить будет? Где это в программе?
Ср апр 24, 2019 17:52:24
Может так понятней будет.
Ср апр 24, 2019 20:49:29
Вы наблюдаете это в симуляторе или косвенно на железе?
И в симуляторе и на железе наблюдаю. Становится ли переменная равной нулю не понятно, но этот сегмент программы выполняется очень долго, хотя как заметил
otest, должен выполняться пол секунды.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.