Чтобы получить точную задержку в 1 секунду, которая также работает во время прерываний, вам нужно использовать аппаратный таймер, а не программный таймер.Я бы посоветовал вам использовать один из доступных встроенных таймеров , как предложено Джерри Коффином .
Вот подход, включающий встроенный таймер и подсчет переполнений таймера.Поскольку текущий таймер обновляется каждые 12 тактов по умолчанию для обеспечения совместимости с 8051, он будет обновляться 921 600 раз в секунду.Немного умножения говорит нам, что для отсчета от 0 до 46080 требуется 50 мс, что также говорит о том, что мы можем запустить 16-разрядный таймер в 19456 и дождаться его переполнения 20 раз с задержкой на 1 секунду *.
Код может выглядеть примерно так:
CLR T0M ; set timer 0 to use a divide-by-12 of
; the crystal frequency (default)
MOV R0,TMOD ; set timer 0 to 16-bit mode without
ORL R0,#01h ; affecting the setup of timer 1
MOV TMOD,R0
LCALL Delay1sec ; call the delay subroutine
Delay1sec:
MOV R0,#20d ; set loop count to 20
loop: CLR TR0 ; start each loop with the timer stopped
CLR TF0 ; and the overflow flag clear. setup
MOV TH0,#4Ch ; timer 0 to overflow in 50 ms, start the
MOV TL0,#00h ; timer, wait for overflow, then repeat
SETB TR0 ; until the loop count is exhausted
JNB TF0,$
DJNZ R0,loop
RET
Примечание: накладные расходы на время выполнения инструкции исключены из примера.
* Как математика ломается:
11059200/12 = 921600
0,05 * 921600 = 46080
65536 - 46080 = 19456 = 0x4C00
Задержка программного обеспечения приводит к потере времени процессора и нарушается прерываниями.При этом, вы можете сделать это жестко закодированным способом.
Один из подходов заключается в знании количества тактов на один машинный цикл и количества машинных циклов, которые выполняются различными инструкциями.Согласно спецификации , DS89C430 обычно использует один машинный цикл для каждого байта команды и требует одного цикла для выполнения.Количество циклов для каждой инструкции указано в руководстве пользователя сверхскоростного флэш-микроконтроллера .
Поскольку ваша частота кристалла составляет 11,0592 МГц, ваша процедура будетнужно отложить на 11 059 200 тактов.Это часто выполняется с помощью вложенных циклов известной длины, а затем включает любые дополнительные настройки цикла и, возможно, подпрограммы вызова и инструкции возврата *.
Функция может выглядеть примерно так:
Delay1sec: ; <------------------------------+
; LCALL Delay1sec ; 3 cycles |
MOV R2,#42d ; 2 cycles |
MOV R1,#00d ; 2 cycles |
MOV R0,#00d ; 2 cycles |
loop: DJNZ R0,loop ; 4 cycles <-- l1 <- l2 <- l3 Delay1sec
DJNZ R1,loop ; 4 cycles <---------+ | |
DJNZ R2,loop ; 4 cycles <---------------+ |
RET ; 3 cycles <---------------------+
Давайте посмотрим, как математика ломается **:
l1
= 4 * 256 = 1024 цикла
l2
= (1024 + 4) *256 = 263168 циклов
l3
= (263168 + 4) * 42 = 11053224 циклов
Delay1sec
= 11072668 + 3 + 2 + 2 + 2 + 3 = 11053236 циклов
11053236 циклов * 1/11059200 секунд / цикл = 999,461 мс
* При необходимости команды вызова и возврата подпрограммы могут быть опущены.
** Я использовал Microsoft Excel для помощи в вычислениях, связанных с определением счетчиков циклов.