Курсовая работа (т): Генератор сигналов синусоидальной формы

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

ATtiny2313 поддерживается различными программными средствами и интегрированными средствами разработки, такими как компиляторы C, макроассемблеры, программные отладчики/симуляторы, внутрисхемные эмуляторы и ознакомительные наборы.

3. Способы генерации аналоговых сигналов

.1 Генерация аналоговых сигналов с помощью ШИМ

Для генерации импульсов используется режим быстрой ШИМ с переменным заполнением импульсов на выходе OC1A (PB1). Для получения из цифрового ШИМ-сигнала сигнала синусоидальной формы на выходе должен быть предусмотрен аналоговый фильтр.

Преимущества высокоскоростного ШИМ - расширение частотного диапазона аналогового выходного сигнала и возможность применения более компактных и недорогих компонентов в фильтре за счет более высокой частоты.

ШИМ в сочетания с аналоговым фильтром может использоваться для генерации аналоговых выходных сигналов, т.е. в качестве цифро-аналогового преобразователя (ЦАП). В качестве основы используется последовательность прямоугольных импульсов с постоянным периодом следования (фиксированная частота преобразования). Для генерации различных аналоговых уровней регулируется заполнение импульсов и, таким образом, изменяется длительность импульсов. Если необходимо сформировать высокий аналоговый уровень, то длительность импульса увеличивают и наоборот.

Усреднение аналогового сигнала за один период (с помощью аналогового фильтра) позволяет сгенерировать аналоговый сигнал. При заполнении импульсов 50% аналоговый сигнал равен половине напряжения питания, а при 75%-ом заполнении импульсов - аналоговый сигнал равен 75% от напряжения питания.

Аналоговый ФНЧ можно выполнить с помощью простого пассивного RC-фильтра. Фильтр удаляет несущую высокую частоту ШИМ и, таким образом, формирует аналоговый сигнал. Настроечная частота фильтра должна быть выбрана достаточно высокой, чтобы не исказить форму аналогового сигнала. В то же время настроечная частота должна быть достаточно низкой для минимизации пульсаций от несущей частоты ШИМ.

Рисунок 2 - Низкочастотный RC-фильтр

Если аналоговый сигнал поступает к низкоомному входу, то между выходом фильтра и нагрузкой должен быть включен буферный усилитель. Это предотвращает нагружение конденсатора и появление пульсирующего напряжения.

В микроконтроллерах AVR для генерации ШИМ-сигналов используются таймеры-счетчики. Для изменения несущей частоты ШИМ изменяется частота синхронизации таймера и вершина счета. Повышение частоты синхронизации и/или снижение вершины счета приводят к повышению частоты переполнения таймера и, как следствие, увеличивается частота ШИМ. Максимальной разрешающей способности (вершина счета 255) соответствует максимальная частота ШИМ 250 кГц. Дальнейшее увеличение частоты ШИМ возможно путем уменьшения разрешающей способности, но в этом случае сокращается количество шагов при установке заполнения импульсов от 0 до 100%.

Изменение содержимого регистра сравнения (OCR) влияет на заполнение импульсов. Увеличение значения OCR увеличивает заполнение импульсов. До достижения счетчиком значения из регистра OCR ШИМ-выход находится в высоком состоянии, затем переходит в низкое состояние до достижения вершины счета, после чего счетчик переходит в нулевое состояние и цикл повторяется. Такой способ генерации у AVR-микроконтроллеров получил название быстрой ШИМ.

Рисунок 3 - Значения счетчика и ШИМ-выход

При использовании высокочастотной ШИМ для генерации аналоговых сигналов ширина аналоговых уровней зависит от разрешающей способности ШИМ. Чем выше несущая частота, тем более просто ее подавить и тем самым минимизировать уровень пульсаций. Таким образом, необходимо оптимизировать соотношение разрешающей способности и несущей частоты.

.2 Генерация аналоговых сигналов с помощью R-2R матрицы

Если к цифро-аналоговому преобразователю не предъявляются серьёзные требования, то его можно сделать самостоятельно из обычных резисторов. Называется такой ЦАП - R-2R. Своё название он получил из-за номиналов применяемых в нём резисторов с сопротивлениями R и 2*R. Сопротивления по идее могут быть любыми, но в разумных пределах. Если поставить очень большие сопротивления, например, по несколько мегаом, то нагрузка которая подключена к выходу, внесет существенные искажения в сигнал. Напряжение начнёт проседать. В курсовой работе используются резисторы, сопротивление которых 1Ком и 2Ком.

Если есть много резисторов одного сопротивления, то получить сопротивление вдвое меньшее, можно просто включив параллельно два одинаковых резистора. Для такого ЦАП желательно использовать резисторы с 1%-м допуском.

Рисунок 4 - ЦАП R-2R

Каждый вход ЦАП имеет свой «вес». Входы расположены в порядке уменьшения веса слева направо. Левый вход оказывает самое большое влияние на выходной сигнал, следующий за ним вдвое меньше и так далее. Ну а самый последний (правый) вход изменяет выходной сигнал на ничтожные милливольты. Если известна комбинация бит, поступающая на вход ЦАП, то рассчитать напряжение очень легко. Предположим, что на входе у нас число 10010101 тогда выходное напряжение можно рассчитать по формуле:


Согласно формуле, напряжение на выходе будет равно 2.91 вольта. Uпит - напряжение питания микроконтроллера. При расчете использовалось значение 5 вольт. Таким образом, восьмибитный ЦАП способен выдать 256 различных напряжений с шагом около 20 милливольт, что вполне неплохо.

К преимуществам таких ЦАП можно отнести:

1)      возможность увеличения разрядности;

)        неплохая частота дискретизации;

)        схемотехническая простота и повторяемость.

Недостатки:

)        качество ЦАП сильно зависит от применяемых резисторов;

)        сопротивление ключей порта микроконтроллера вносят искажения;

)        громоздкость на плате

4. Разработка программ генерации синусоидального напряжения

.1 Хранение значений синусоиды в памяти программ

Микроконтроллеры AVR имеют отдельную память данных и отдельную память программ.

Память программ (Flash ROM или Flash ПЗУ) предназначена для хранения последовательности команд, управляющих функционированием микроконтроллера, и имеет 16-ти битную организацию. Все AVR имеют Flash-память программ, которая может быть различного размера - от 1 до 256 КБайт. Ее главное достоинство в том, что она построена на принципе электрической перепрограммируемости, т. е. допускает многократное стирание и запись информации. Программа заносится во Flash-память AVR как с помощью обычного программатора, так и с помощью SPI-интерфейса, в том числе непосредственно на собранной плате. Возможностью внутрисхемного программирования (функция ISP) через коммуникационный интерфейс SPI обладают все микроконтроллеры AVR, кроме Tiny11 и Tiny28.

Гарантированное число циклов перезаписи Flash-памяти у микроконтроллеров AVR второго поколения составляет не менее 10 тыс. циклов при типовом значении 100 тыс. циклов. (В официальной технической документации Atmel Corp. указывается значение 10 тыс. циклов.).

Некоторые виды данных удобно хранить в памяти программ. К таким данным относятся наборы различных констант. В нашем случае в памяти программ удобно хранить набор значений синусоиды, соответствующих одному периоду. Для извлечения данных из памяти программ используется команда lpm.

;************************************************************

;Генератор сигнала синусоидальной формы

;Хранение значений синусоиды в памяти программ

;Микроконтроллер ATtiny2313

;************************************************************

.nolist; Отменяем листинг всех подсоединяемых файлов

.include "tn2313def.inc"         ; Присоединение файла описаний

.list; Разрешение листинга

.def temp=r16; Регистр для хранения промежуточных данных

.def temp1=r17; Регистр для хранения текущего значения синусоиды

;--------------------------- Начало программного кода---------------------------

.cseg; Выбор сегмента памяти команд

.org 0; Установка счетчика команд в 0

;--------------------------- Инициализация стека-----------------------------------temp,RAMEND; Выбор адреса вершины стекаSPL,temp; Запись его в регистр стека

;-------------------------- Инициализация портов ввода-вывода ---------------

ldi temp,0; Записываем ноль в регистр temp

out DDRA,temp; Записываем ноль в DDRA (порт A на ввод)

ldi temp,0xFF; Записываем число $FF в регистр temp

out PortD,temp; Записываем temp в PortD (включаем подтяжки порта D)

out PortA,temp; Записываем temp в PortA (включаем подтяжки порта A)

out DDRB,temp; Записываем temp в DDRB (порт B на вывод)

; ----------------------------- Инициализация компаратора-----------------------

ldi temp,0x80 ACSR,temp;Выключение компаратора

;------------------------------ Основной цикл программы------------------------:temp,0; Записываем ноль в регистр tempZH,High(Array*2); Запись старшего и младшего байта начальногоZL,Low(Array*2); адреса массива в регистровую пару Z:r17, Z+       ; Загрузка с постинкрементом в r17(temp1)

; содержимого ячейки, адрес которой хранится в

; регистровой паре ZPortB,temp1; Вывод текущего значения синусоиды в порт PBtemp,255; Проверка счетчика (temp1) на равенство 255       t1; Если равно 255, то переходим на метку t1Temp; Увеличиваем счетчик на единицуP1; Безусловный переход на метку P1

;--------------------- Массив значений периода синусоиды --------------------

; Массив состоит из 256 чисел, то есть один период синусоиды строится по

; 256-ти точкам

Array:

.db128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,177,180,182,185,188,191,194,196,199,201,204,206,209,211,214,216,218,220,222,224,226,228,230,232,234,236,237,239,240,242,243,244,246,247,248,249,250,251,251,252,253,253,254,254,254,255,255,255

.db255,255,255,255,254,254,253,253,252,252,251,250,249,248,247,246,245,244,242,241,240,238,236,235,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,197,195,192,189,187,184,181,178,175,172,169,167,164,160,157,154,151,148,145,142,139,136,133,130

.db126,123,120,117,114,111,108,105,102,99,96,92,89,87,84,81,78,75,72,69,67,64,61,59,56,53,51,48,46,44,41,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,8,7,6,5,4,4,3,3,2,2,1,1,1,1

.db1,1,1,2,2,2,3,3,4,5,5,6,7,8,9,10,12,13,14,16,17,19,20,22,24,26,28,30,32,34,36,38,40,42,45,47,50,52,55,57,60,62,65,68,71,74,76,79,82,85,88,91,94,97,100,103,106,109,112,116,119,122,125,128

4.2 Хранение значений синусоиды в ОЗУ. Применение косвенной адресации

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

Адрес байта при обращении к SRAM может быть указан в коде команды с обращением к SRAM (прямая адресация) или предварительно записан в пару регистров X, Y или Z (косвенная адресация). Обращение к SRAM может выполняться с использованием адреса, хранящегося в регистре-указателе стека.

Байт для записи в SRAM поступает из регистра общего назначения. Байт, считанный из SRAM, поступает в регистр общего назначения.

В адресное пространство SRAM кроме адресов, по которым выполняется обращение к ячейкам памяти SRAM, включены 32 адреса для обращения к регистрам общего назначения (адреса от $00 до $1F) и 64 адреса для обращения к регистрам ввода-вывода (адреса от $20 до $5F).

Первой ячейке SRAM соответствует адрес $60.

Всего адресное пространство ОЗУ содержит 224 ячейки, из которых 128 ячеек составляют внутреннюю память данных.

Для всех способов адресации доступны все 32 регистра общего назначения, 64 регистра ввода-вывода и 128 байтов памяти данных SRAM микросхемы Attiny2313.

;*************************************************************

;Генератор сигнала синусоидальной формы

;Хранение значений синусоиды в ОЗУ

;Микроконтроллер ATtiny2313

;*************************************************************

.nolist; Отменяем листинг всех подсоединяемых файлов

.include "tn2313def.inc"; Присоединение файла описаний

.list; Разрешение листинга

.def temp1=r16; Главный рабочий регистр

.def temp2=r17; Регистр для хранения текущего значения синусоиды

;--------------- Резервирование ячеек памяти (SRAM)------------------------

.dseg; Выбираем сегмент ОЗУ

.org 0x60; Устанавливаем текущий адрес сегмента

buf: .byte 64; Резервируем 64 байта в ОЗУ под массив чисел со ;значениями четверти периода синусоиды

;--------------------------- Начало программного кода----------------------------

.cseg; Выбор сегмента памяти команд

.org 0; Установка счетчика команд в 0

;------------------------- Инициализация стека-------------------------------------temp1,RAMEND; Выбор адреса вершины стекаSPL,temp1; Запись его в регистр стека

;--------------------- Инициализация портов ввода-вывода -------------------

ldi temp1,0; Записываем ноль в регистр temp

out DDRD,temp1; Записываем этот ноль в DDRD (порт D на ввод)

out DDRA,temp1; Записываем ноль в DDRA (порт A на ввод)

ldi temp1,0xFF; Записываем число $FF в регистр temp

out PortD,temp1; Записываем temp в PortD (включаем подтяжки порта D)

out PortA,temp1; Записываем temp в PortA (включаем подтяжки порта A)

out DDRB,temp1; Записываем temp в DDRB (порт B на вывод)

; ---------------------------- Инициализация компаратора-------------------------

ldi temp1,0x80 ACSR,temp1;Выключение компаратора

;-----------------------------Основной цикл программы---------------------------

ldi XH, high(buf); В регистровую пару X записываем адрес

ldi XL, low(buf); начала буфера ОЗУ

ldi ZH, high(mas*2); В регистровую пару Z записываем старший и

ldi ZL,low(mas*2)         ; младший байт начального адреса массива

ldi temp1,0; Записываем ноль в temp1, регистр будет

; работать как счетчик

;---------------------------- Косвенная запись в память---------------------------

nn:

lpm temp2,Z+; Загрузка с постинкрементом в r17(temp1)

; содержимого ячейки, адрес которой хранится

; в регистровой паре Z

st X+,temp2;Совершаем запись содержимого регистра

; temp2 в ОЗУ по адресу, который хранится

; в регистровой паре X

inc temp1; Увеличиваем значение счетчика на единицу

brne nn; Если не равно 64, то переходим на метку nn,

; если равно 64, то есть если в ОЗУ записались

;все числа массива, то переходим на метку start

;---------------------- Косвенное чтение из памяти-------------------------

start:

ldi XH, high(buf); В регистровую пару X записываем адрес

ldi XL, low(buf); начала буфера ОЗУ

;-------------------------- Первая четверть синусоиды----------------------------

nn1:

ld temp2, X+; Чтение байта из ячейки ОЗУ, адрес которой

; хранится в регистровой паре X и запись

; прочитанного байта в регистр temp2. Затем

; содержание регистровой пары X увеличивается

; на единицу

out PortB,temp2; Вывод текущего значения синусоиды в порт РВ

dec temp1; Уменьшаем значение счетчика на единицу

cpi temp1,0; Сравниваем с нулем

brne nn1; Если не равно нулю, то переходим на метку nn1,

; если равно нулю, то есть если из ОЗУ были

; прочитаны и отправлены на порт B все 64 числа, то

; переходим на метку nn2

;---------------------- Вторая четверть синусоиды------------------------------

nn2:

ld temp2, -X; Чтение байта из ячейки ОЗУ, адрес которой

; хранится в регистровой паре X и запись

; прочитанного байта в регистр temp2. Затем

; содержание регистровой пары X уменьшается

; на единицу

out PortB,temp2; Вывод текущего значения синусоиды в порт РВ

inc temp1; Увеличиваем значение счетчика на единицу

cpi temp1,64; Сравниваем с 64

brne nn2; Если не равно 64, то переходим на метку nn2,

; если равно 64, то есть если из ОЗУ были

; прочитаны и отправлены на порт B все 64 числа,

; начиная с последнего числа массива, записанного в

Источник: https://www.bibliofond.ru/detail.aspx?id=792226