В подпрограмме генератор прямоугольных импульсов (меандра) вычислим частоту звукового сигнала на выводе микроконтроллера.

Программа генератор для микроконтроллера ATtiny13 работающего на частоте ядра 9600000 Гц:

;******************************************************************************
;***** Программа включает и выключает порт PB2 микроконтроллера ATtiny13 ******
;***** Created: 2015-02-05 01:28 ******** Site: http://integrator.adior.ru ****
;******************************************************************************
.includepath "/home/dior/AVR"		; Папка с файлами заголовками         
.include "tn13def.inc"			; Используем ATtiny13                 
;==============================================================================
		rjmp reset		; начало программы
reset:
		ldi r23, RAMEND		; Загрузить в R23 адрес последней ячейки памяти
		out SPL, r23		; Инициализация стека
		sbi DDRB, DDB2		; PB2 будет работать на выход
		ldi r23, 4		; Загрузить в R23 4
		out PORTB, r23		; PB2 установить уровень 1. На PB2 подкл. динамик.
main:
		ldi r25, 4		; Длительность звучания
		ldi XL, 255		; Длительность полупериода (младший байт)
		ldi XH, 4		; Длительность полупериода (старший байт)
		rcall duratone		; Вызов подпрограммы генерации ноты

stop:		rjmp main		; Останов или бесконечный цикл

; Подпрограммы

duratone:				; Подпрограмма генератор тона с таймером
					; Длительность таймера R25
					; Высота тона (точнее, длительность полупериода) XH:XL
		movw YL, XL		; ╔>Загрузить в счетчик Y длительность полупериода из X
		swap r23		; ║Поменять местами полубайты в r23
		out PORTB, r23		; ║Инвертировать сигнал на PB2
halfcycle:	sbiw YH:YL,1		; ║╔>Y=Y-1 (65535...0)
		brcc halfcycle		; ║╚<Повторять пока не было переноса
		sbiw r25:r24,1		; ║R25:R24=R24:R24-1
		brcc duratone		; ╚<Повторять пока не было переноса
		ret			; Возврат из подпрограммы


; Задействованы регистры R23, R24, R25, R26, R27, R28, R29

; Компилировать avra test.s
; Загрузить avrdude -C/home/dior/AVR/avrdude.conf -v -v -v -v -pattiny13 -cstk500v1 -P/dev/ttyUSB0 -b19200 -Uflash:w:test.s.hex:i
; Фьюзы avrdude -C/home/dior/AVR/avrdude.conf -v -v -v -v -pattiny13 -cstk500v1 -P/dev/ttyUSB0 -b19200 -e -Uhfuse:w:0xff:m -Ulfuse:w:0x7a:m

В симулятор simulavr всю программу, предварительно установив XL=2, XH=0. Читайте Simulavr - эмулятор микроконтроллеров Atmel AVR

Для анализа выделим интересующий нас фрагмент кода, собственно генератор с таймером времени звучания:

     duratone:				; Подпрограмма генератор тона с таймером
   					; Длительность таймера R25
   					; Высота тона (точнее, длительность полупериода) XH:XL
1 16		movw YL, XL		; ╔>Загрузить в счетчик Y длительность полупериода из X
2 18		swap r23		; ║Поменять местами полубайты в r23
3 1a		out PORTB, r23		; ║Инвертировать сигнал на PB2
4 1c halfcycle: sbiw YH:YL,1		; ║╔>Y=Y-1 (65535...0)
5 1e		brcc halfcycle		; ║╚<Повторять пока не было переноса
6 20		sbiw r25:r24,1		; ║R25:R24=R24:R24-1
7 22		brcc duratone		; ╚<Повторять пока не было переноса
8 24		ret			; Возврат из подпрограммы

В левой колонке адрес каждой команды №п/п в словах и в байтах подпрограммы duratone в Flash памяти микроконтроллера ATtiny13.

Составим таблицу всех используемых в подпрограмме команд и время их выполнения в тактах микроконтроллера:

КомандаОперацияОписаниеЧисло тактов
movw Rd, Rr Rd+1:Rd=Rr+1:Rr Пересылка двух байтов 1
swap Rd bit 7 6 5 4 ↔ bit 3 2 1 0 Обмен местами полубайтов 1
out A, Rr A=Rr Пересылка из регистра РОН в РВВ
sbiw Rdh:Rdl, K Rdh:Rdl=Rdh:Rdl-K Вычитание константы из регистровой пары 2
brcc k Если C=0, то PC=PC+1+k Переход если нет переноса 1/2

Номер команды выполняемой за 2 такта подкрасим в зеленый цвет, а номер команды, выполняемой за количество тактов,зависящее от направления ветвления, в красный.

Составим диаграмму сигнала на ножке PB2 с момента отрицательного перепада произошедшего сразу после 1-го выполнения команды №3 out PORTB, r23

Осцилограмма сигнала на выходе микроконтроллера

На выводе микроконтроллера PB2 оба полупериода сигнала одинаковы. Если значение двухбайтового регистра X=2, длительность полупериода выходного сигнала равна 18 тактов.

Если значение двухбайтового регистра X=3, длительность полупериода выходного сигнала равна 18+4 тактов. В общем случае:

T/2(n)=n*4+10 тактов

Один такт выбранного нами микроконтроллера ATtiny13 равен 1/F=1/9600000 сек.

Длительность периода меандра на выходе PB2 микроконтроллера:

Частота сигнала на выводе PB2 микроконтроллера ATtiny13 (с собственной тактовой частотой 9600000 Гц)

Расчет числа n, загружаемого в регистр X микроконтроллера исходя из требуемой частоты f