Написание подпрограммы задержки? - PullRequest
2 голосов
/ 27 февраля 2011

Мне нужно написать подпрограмму задержки.Это должно задержать около 1 секунды.Это должно быть для среды 8051, микроконтроллера DS89C430 (11,09292 МГц XTAL).Как я могу написать эту подпрограмму?

Delay1sec: ...
....
...
....
...

Ответы [ 3 ]

3 голосов
/ 02 марта 2011

Чтобы получить точную задержку в 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 для помощи в вычислениях, связанных с определением счетчиков циклов.

2 голосов
/ 27 февраля 2011

Этот микроконтроллер имеет три встроенных таймера (см. Раздел 11 Руководства пользователя ), подключенных к системным часам (разделенным на 12), поэтому их программирование должно генерировать прерывание, когдавремя истекаетПоскольку разделенный вход составляет чуть менее 1 МГц, а наибольший счетчик составляет 16 бит, вам нужно посчитать 14 прерываний, чтобы достичь одной секунды (по крайней мере, если я правильно выполнил вычисление).

0 голосов
/ 14 марта 2011

А) Ссылка на аппаратный таймер.

B) Ссылка на таймер процессора.Некоторые процессоры имеют очень широкий таймер, то есть 64-битный, который работает с тактовой частотой.

C) Программный цикл.Для достижения наилучших результатов код и все данные должны находиться во внутренней памяти, которая имеет предсказуемое время.Запуск из SDRAM может вызвать проблемы с синхронизацией.

Для этого не нужно считать циклы сборки.Вместо этого вы можете «нарисовать» импульс на выводе (тянуть высоко перед петлей, низко за петлей), измерить ширину импульса с помощью логического анализатора, а затем изменить счетчик петли, чтобы настроить время.Для достижения наилучших результатов вы должны компенсировать внешнюю тактовую частоту / кристалл процессора, используя частотомер для его измерения, а затем компенсировать отклонение от центральной частоты, потому что большинство дешевых кристаллов не являются мертвыми.

Вы можете выполнить самокалибровку, используя таймер для расчета времени цикла.

...