У меня такой код - все светодиоды включаются и выключаются каждую 1 секунду (используется MPLAB X IDE, ассемблер, частота генератора 4МГц):
#include <p16f84a.inc>
__CONFIG _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _FOSC_HS
;General registers for delay
CounterA equ h'0c'
CounterB equ h'0d'
CounterC equ h'0e'
org 0
Start:
; select bank 1
bsf STATUS, RP0
; set port B as output
movlw b'00000000'
movwf TRISB
; select bank 0
bcf STATUS, RP0
MainLoop:
; turn on LEDS
movlw b'11111111'
movwf PORTB
call Delay_1s
movlw b'00000000'
movwf PORTB
call Delay_1s
goto MainLoop ;Repeat
Delay_1s:
movlw d'6'
movwf CounterC
movlw d'24'
movwf CounterB
movlw d'168'
movwf CounterA
loop:
decfsz CounterA,1
goto loop
decfsz CounterB,1
goto loop
decfsz CounterC,1
goto loop
return
end
Может ли кто-нибудь объяснить, как работает Delay_1s? Я пытался умножить 168 * 24 * 6 = 24192 мкс, но это неверно, я должен получить 1000000 мкс.
ИЗМЕНИТЬ:
Я приближаюсь - decfsz CounterA,1 занимает 1 мкс, а goto loop занимает 2 мкс для обработки. Поэтому я думаю, что ответ должен выглядеть так (168 * 3) * (24 * 3) * (6 * 3) = 653184 мкс. Конечно, я должен добавить 6 мкс при установке значений CounterA, CounterB и CounterC. Я что-то упускаю?
EDIT2:
Ниже я добавил значения времени для каждой операции. Я правильно понимаю?
Delay_1s:
movlw d'6' ; 1µS
movwf CounterC ; 1µS
movlw d'24' ; 1µS
movwf CounterB ; 1µS
movlw d'168' ; 1µS
movwf CounterA ; 1µS
loop:
decfsz CounterA,1 ; 1µS
goto loop ; 2µS (the same while skipping)
decfsz CounterB,1 ; 1µS
goto loop ; 2µS (the same while skipping)
decfsz CounterC,1 ; 1µS
goto loop ; 2µS (the same while skipping)
return ; 1µS ??
Ответ 1 · рейтинг 1 · Neujahr
Извините, что я не умею объяснять, но я надеюсь, что это даст вам некоторую подсказку:
Using a 4MHz Xtal OSC
Set OPTION_REG to b'11010100'
'xxxxx100' = 1 instruction :32 uSeconds
32 uSeconds * 250 = 8 milliseconds
8 milliseconds * 125 = 1 second
PORTB (all outs) = B'00000000'
EIGHT_MS EQU 0x10
INIT
BSF STATUS, RP0
MOVLW B'11010100'
MOVWF OPTION_REG
MOVLW B'00000000'
MOVWF TRISB
BCF STATUS, RP0
CLRF PORTB
RETURN
START
L0 CLRF TMR0
L1 MOVF TMR0, W
XORLW .250
BTFSS STATUS, Z
GOTO L1
CLRF TMR0
INCF EIGHT_MS
MOVF EIGHT_MS, W
XORLW .125
BTFSS STATUS, Z
GOTO L1
CALL LIGHT_LED
GOTO L1
LIGHT_LED
...
CALL DELAY
...
RETURN
MAIN
CALL INIT
CALL START
GOTO MAIN
Ответ 2 · рейтинг 1 · user13819772
Я просмотрел эту программу и обнаружил, что количество циклов, которые эта процедура тратит, составляет 1 003 827, что эквивалентно 1,003827 секундам.
Я делал это тремя разными способами и всегда получал один и тот же результат.
Метод 1: Формула Метод 2: Моделирование в Python Метод 3: Использование симулятора MPLAB, установка точек останова и наблюдение за счетчиком циклов до и после вызова функции.
Формула выводится следующим образом
Давайте сначала спросим себя, сколько циклов занимает программа, подобная следующей:
цикл: decfsz x, f Эта строка выполняется x раз, x-1 раз не выполняется переход и 1 раз выполняется переход, поэтому количество циклов равно x-1) +2 цикл перехода Это выполняется x-1 раз, поэтому циклов 2 (x -1) всего циклов (x-1) + 2 + 2 (x-1) = 3x-1 циклов
Предположим, что x находится в диапазоне от 1 до 256 (включает в себя 1 и 256, если x равен 0, это равно 256)
Таким образом, количество циклов полной программы равно
Циклы счетчика A Первый раз, когда B имеет начальное значение 3A-1 Следующие времена счетчика B (B-1) * (3 * 256-1) Следующие времена счетчика C (C-1) * 256 * 767 Счетчик Циклы B Первый раз, когда C равно 6 3B-1 Последующие времена C (C-1) * 767 Циклы счетчика C Первый и единственный раз 3C-1 Вызов, Возврат и 6 строк инициализации 10 ----- -------------------- итого: 3А+770В+197 122С-197879
Подстановка A вместо 168, B = 24 и C = 6 дает значение 1 003 837, лучшими значениями были бы A = 172 B = 19 C = 6, что дает 999 999, добавление nop в инициализацию переменной дало бы 1 000 000