// Включение заголовочных файлов
#include <avr/io.h>
#include <avr/interrupt.h>
// Задание частоты процессора 10 МГц
#define F_CPU 10000000UL
// Если частота не задана, то 16 МГц
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#include <math.h>
#include "lcd.h"
/*Глобальные переменные
i - переменная-счетчик
a - номер действия
lim_i - целочисленное значение предела счета
f - частота для вывода на ЖКИ */
int i = 0, a = 0, lim_i = 0, f = 0;
// Прерывание по переполнению счетчика 1
ISR(TIMER1_OVF_vect) {
/* new_d - значение коэффициента заполнения ШИМ
lim - предел счета i
s - коэффицент для пересчета i в градусы */
int new_d;
double lim, s;
// Запуск преобразования АЦП
ADCSRA |= (1 << ADSC);
while ((ADCSRA & (1 << ADIF)) == 0);
// Если результат преобразования больше 20 (Напряжение на ножке больше 0.1 В)
if(ADCW >= 20) {
// Расчет предела счета i
lim = 10230 / ADCW;
// Защита от выхода за предел счета
if(i >= lim_i)
i = lim_i;
// Расчет коэффициента s
s = 90 / lim;
// Сохранение целочисленного предела счета
lim_i = ceil(lim);
// Расчет коэффиицента заполнения
new_d = sin(i * s * M_PI / 180) * 10000;
// Обновление коэффициента заполнения
|
|
ICR1 = 10000;
OCR1A = new_d;
// Расчет частоты для вывода на дисплей
f = ceil(500 / lim);
}
// Если меньше
else {
// Частота равна 0
f = 0;
// Коэффициент заполнения равен 0
OCR1A = 0;
}
// Выбор действия над i
switch(a) {
case 0:
i++;
if(i >= lim_i)
a++;
break;
case 1:
i--;
if(i == 0)
a--;
break;
}
}
int main(void) {
// str - буфер строки для вывода на ЖКИ
// f_b - буфер частоты для вывода на ЖКИ
char str[32], f_b;
// Инициализация портов
DDRA = 0x70;
DDRB = 0x20;
PORTA = 0x00;
PORTB = 0x00;
// Инициализация дисплея
lcd_init();
// Инициализация таймера-счетчика в режиме Fast PWM
ICR1 = 10000;
OCR1A = 5000;
TCCR1A |= (1 << COM1A1) | (1 << WGM11);
TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
TCCR1C = 0x00;
TIMSK |= (1 << TOIE1);
ETIMSK = 0x00;
// Инициализация АЦП
ADCSRA |= (1 << ADEN) | (1 << ADPS0);
ADMUX |= (1 << REFS0) | (1 << MUX0);
SFIOR = 0x00;
// Разрешение прерываний
sei();
// Рабочий цикл
while(1) {
if(f_b!= f) {
// Создание строки
sprintf(str, "freq = %d Hz", f);
// Очистка дисплея
lcd_clear();
// Вывод строки на дисплей
lcd_put_str(str);
f_b = f;
}
}
}
Проверка работы программы
Проверка работы программы осуществлялась на симуляторе. Результаты проверки показали, что работа программы соответствует условию задания.
Вывод
В результате выполнения лабораторной работы:
1. Изучены устройство и порядок работы с аналого-цифрового преобразователем (АЦП) МК ATmega128
2. Разработана программа, использующая АЦП. Алгоритм работы программы выполнен в виде блок-схем и представлен в отчете вместе с исходным кодом, содержащим необходимые комментарии. Произведена проверка, в результате которой программа показала корректную работу. Задача решена.