Как релизовать задержку времени на секунды, миллисекунды, микросекунды на attiny13a

attiny13 задержка времени 0,5с

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

Таблица 1. Зависимость частоты от времени одного полного колебания.

Частота Время Коментарий
1 Герц (Hz) 1 секунда (s) Одно полное колебание за секунду
1 Килогерц (kHz) 1 миллисекунда (ms) В одной секунде 1000 миллисекунд
1 Мегагерц (mHz) 1 микросекунда (us) В одной миллескунде 1000 микросекунд


Как организовать задержу на 0,5 секунд в микроконтроллере attiny13?

1. Нам нужна частота, на которой работает микроконтроллер, для простоты возьмем 1 Мегагерц (миллион операций в секунду), тогда делаем константу
F_CPU = 1000000; 

2. Возьмем заданное количество секунд, 0,5 с. для того чтобы вычислить глубину задержки умножить на секунды.
delayTime = F_CPU * 0,5;
// delayTime = 500000;

3. Оценка памяти, в которое можно запихнуть предыдущее константное число
1 байт занимают числа от 255, 2 байта занимают числа от 65 536, пролетаем и тут, в три байта 16 777 216, то что нужно!
Так как 500 000 < 16 777 216, то нам нужно 3 байтовый счетчик

4. Составляем программу на ассемблере

.include "tn13Adef.inc"

.equ Z_CPU=1000000

.cseg
.org 	0x00
ldi	    r16,(1<<PINB0)	; load 00000001 into register 16
out     DDRB, r16		; write register 16 to DDRB
out     PORTB, r16		; write register 16 to PORTB


; Настройка стека (онли attiny13)
ldi	r16,LOW(RAMEND)
out	SPL,r16		

; END настройка стека

loop:
	rcall delay05s
	; Сделать регистр пустым и записать в порт
	clr r16
	out     PORTB, r16
	rcall delay05s
	; Сделать ругистр полным и записать в порт
	ser r16
	out     PORTB, r16
	rjmp    loop	; stay in infinite loop
	

delay05s:
	; 500 000 делим на количество тактов (на 5 тактов задержки) и получаем 100 000 в десятичной системе
	; Переводим 100 000 в hex 1 86 A0 и загружаем в  памят
	ldi r16, 0xA0
	ldi r17, 0x86
	ldi r20, 0x01
	
	ldi r18, 1
	ldi r19, 0

subCount:
	sub r16, r18 ; минус старший разряд
	sbc r17, r19 ;
	sbc r20, r19 ;
	brne subCount 
	ret


Как организовать задержку на 20 миллисекунд на микроконтроллере attiny13?

1. Все нижесказанное актуально для частоты attiny13 1 мегагерц (Z_CPU=1000000)

2. Возьмем заданное количество миллисекунд в тактах, это 20 000 тактов. 

3. Оценка памяти, в которое можно запихнуть предыдущее константное число
1 байт занимают числа от 0 до 255, 2 байта занимают числа от 65 536, то что нужно!
Так как 20 000 < 65 536, то нам нужно 2 байтовый счетчик

4. Составляем программу на ассемблере

.include "tn13Adef.inc"

.equ Z_CPU=1000000
.equ ms20delay=(20000/4) ; 4 это 4 инструкции выполняется задержка

.cseg
.org 	0x00
ldi	    r16,(1<<PINB0)	; load 00000001 into register 16
out     DDRB, r16		; write register 16 to DDRB
out     PORTB, r16		; write register 16 to PORTB


; Настройка стека (онли attiny13)
ldi	r16,LOW(RAMEND)
out	SPL,r16		

; END настройка стека

loop:
	rcall delay20ms
	; Сделать регистр пустым и записать в порт
	clr r16
	out     PORTB, r16
	rcall delay20ms
	; Сделать ругистр полным и записать в порт
	ser r16
	out     PORTB, r16
	rjmp    loop	; stay in infinite loop
	

delay20ms:
	; если там че-то было то сохраним, а потом восстановим
	mov r0, r16 
	mov r1, r17
    mov r2, r18
	mov r3, r19
	;
	ldi r16, low(ms20delay)
	ldi r17, high(ms20delay)
	ldi r18, 1
	ldi r19, 0
	;
subCount:
	sub r16, r18
	sbc r17, r19 ; есть sbci с переносом за 1 такт
	brne subCount 
	ret


Как организовать задержку 5 микросекунд на микроконтроллере avr attiny13a?

1. Все нижесказанное так же актуально для частоты attiny13 1 мегагерц (Z_CPU=1000000)

2. Программа выполняется на принципе использования оператора NOP которая ничего не делает 1 такт

Задержка 5мкс на attiny13

3. Проверим в симуляторе программу ниже. Вышило примерно 5 пульсаций за 50 микросекунд.
Делим 50 / 5 = 10. Это значит что у нас произошло 10 задержек, что и требовалось. Так как команды в теле цикла loop выполняются за один такт, кроме rjmp, она за два такта выполняется.

.include "tn13Adef.inc"

.cseg
.org 	0x00
ldi	r16,(1<<PINB0)
out     DDRB,r16
out     PORTB,r16

loop:	
	nop
	clr r16
	out PORTB,r16
	; 5 микросекундный цикл
	nop
	nop
	nop
	ser r16
	out PORTB,r16
	; 5 микросекундный цикл
rjmp loop

Вывод, какой промежуток можно задавать с помощью примеров выше?

С помощью этих трех программ можно задавать задержку для получения меандра от 4 микросекунд до 17 секунд с минимальной модификацией. После того как добавить еще 4тый бит в программе задержки секунд, можно будет делать задержки до 70 минут и выше, чисто теоретически добавить в цикл задержки 5 nop инструкций выростет задержка до двух часов без добавления еще одного регистра.

{{ x.text }}