Продолжим изучать аналого-цифровой преобразователь микроконтроллеров AVR на примере цифрового вольтметра постоянного напряжения, с пределами измерения от 0 до 25V. Измеряемое напряжение будет отображаться на четырехразрядном семисегментном индикаторе с общим анодом. В этом примере применим динамическую индикацию о которой подробней рассказано на одном из предыдущих занятий, кусок кода возьмем от туда же. Микроконтроллер Atmega8 тактируется от внутреннего генератора частотой 8MHz.

Входом АЦП является вывод PC0(ADCO), установлен по умолчанию в регистре ADMUX. Так как вольтметр у нас должен измерять напряжение от 0 до 25V, а 25V для порта контроллера это очень много, в таких случаях используют делитель напряжения, на схеме это резисторы R1 и R2. Например, если напряжение на входе будет меняться от 0 до 25V, то на выходе оно будет меняться от 0 до 5V. Резистор R3 - подстроечный, служит для подстройки отображаемого на дисплее уровня напряжения, желательно многооборотный. Источником опорного напряжения будет вывод питания AVCC с внешним конденсатором на выводе AREF, режим активируется установкой бита REFS0 в регистре ADMUX. Для снижения влияния шумов на результат преобразования вывод AVCC необходимо связать с цифровым питанием VCC через LC-цепь.

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

Применим такую формулу, где: R1 = 100k, R2 = 25k, Uin = 5V,

Umax = Uin*(R1+R2)/R2
Umax = 5*125k/25k = 25V

Из этого мы знаем, что больше 25V на вход делителя напряжения подавать нельзя.

Результат преобразования в Вольтах вычисляется по формуле:

U = ADC*Uref*K/1024

где ADC - результат преобразования;
Uref опорное напряжение(V);
K - коэффициент делителя напряжения.
1024 - Разрядность АЦП 10 бит

Коэффициент делителя напряжения напряжения вычисляется по формуле:

K = (R1+R2)/R2
K = (100k + 25k)/25k = 5

В нашем примере максимальная разрешающая способность будет 10 разрядов, поэтому частота на входе схемы последовательного приближения должна быть в диапазоне 50…200 кГц. Установим ее впределах 125kHz, включим предделитель на 64 путем установки битов ADPS2 и ADPS1 в регистре ADCSRA.

В программе используем прерывание по окончании преобразования АЦП, для этого включим непрерывный режим работы АЦП путем установки бита ADFR и активируем прерывание битом ADIE в этом же регистре ADCSRA

В обработчике прерывания от АЦП 10-ти битный результат преобразования(ADC) после каждого измерения помещаем в буфер, а уже в основном цикле значение буфера делим на количество измерений для усреднения показаний. Далее, применив формулу, вычисляем результат преобразования, переводим результат вычисления в милливольты, путем умножения на 100, и выводим его на дисплей. Полный текст программы ниже.

// Использование АЦП. Цифровой вольтметр 0-25V

#include <avr/io.h>
#include <avr/interrupt.h>

// Массив комбинаций сегментов                    
unsigned char SEGMENTE[] = 
{
0x3F, // 0 
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F  // 9
};

volatile unsigned char seg_counter, adc_counter;
volatile unsigned int display = 0;
volatile unsigned long adc_buffer;

// Прерывание по переполнению T2, динамическая индикация
ISR (TIMER2_OVF_vect)
{	
PORTD = 0xFF; // Гасим все сегменты
PORTB = (1 << seg_counter); // Последовательно зажигаем общие аноды
	
switch(seg_counter)
{	
case 0:
PORTD = ~(SEGMENTE[display % 10000/1000]); // Выводим первый разряд
break; 
case 1:
PORTD = ~((SEGMENTE[display % 1000/100])|0x80); // добавляем десятичную точку
break;	
case 2:
PORTD = ~(SEGMENTE[display % 100/10]); // Выводим третий разряд 
break;			
case 3:
PORTD = ~(SEGMENTE[display % 10]); // Выводим четвертый разряд 
break;	
}
if (seg_counter++ > 2) seg_counter = 0;	
}

// Прерывание по окончанию преобразования АЦП
ISR(ADC_vect)
{
adc_buffer += ADC; // Накапливаем в буфер значения АЦП
adc_counter++; // Увеличиваем счетчик измерений
}

// Главная функция
int main (void) 
{ 
// Настройка портов ввода/вывода
DDRB = 0xFF; // Выходы на общие аноды
PORTB = 0x00; // Ноль на выходе
DDRD = 0xFF; // Выходы на сегменты
PORTD = 0x00; // Ноль на выходе

// Настройка Т2
TIMSK |= (1 << TOIE2); // Разрешение прерывания по таймеру2
TCCR2 |= (1 << CS21);  // Предделитель на 8 

// Настройка АЦП    
ADMUX |= (1 << REFS0); // ИОН - AVCC с внешним конденсатором на выводе AREF, вход ADC0
ADCSRA |= (1 << ADEN)  // Разрешение АЦП
        |(1 << ADSC)   // Запуск преобразования
        |(1 << ADFR)   // Непрерывный режим работы АЦП
        |(1 << ADPS2)|(1 << ADPS1) // Предделитель на 64 (частота АЦП 125kHz)
	|(1 << ADIE); // Разрешение прерывания от АЦП

sei(); // Глобально разрешаем прерывания

// Главный цикл 
while(1)
{ 
if(adc_counter == 250) // Если количество измерений равно 250
{
display = ((adc_buffer*5*5*100)/1024)/adc_counter; // Вычисляем среднее значение АЦП
adc_counter = 0; // Обнуляем счетчик измерений
adc_buffer = 0; // Обнуляем буфер АЦП
}     

}
}

При программировании установить такие Fuse -  биты:

Обсуждение статьи на форуме.


Архив для статьи "АЦП микроконтроллеров AVR. Делаем цифровой вольтметр 0 - 25V"
Описание: Файлы проекта для AVR Studio
Размер файла: 16.51 KB Количество загрузок: 8 646 Скачать