Есть ли возможность переделать схему (добавить функцию вольтметра пинов у м.к. свободных куча ещё осталась?)Добавлено (07.02.2016, 23:11)
---------------------------------------------
это под семисегментник но думаю переделать и добавит вам не составит труда
Входом АЦП является линия PC0(ADCO), т.к. вольтметр должен измерять напряжение до 25V, а 25V для порта
контроллера это очень много, в таких случаях используют делитель
напряжения. Например, если напряжение на входе будет меняться от 0 до
25V, то на выходе оно будет меняться от 0 до 5V.Рассчитаем максимальное напряжение Uemax подаваемое на вход АЦП по формуле:Uemax = 1023*Uref/1024Uemax = 1023*2.56/1024 = 2,5575VРассчитаем максимальное входное напряжение делителя, исходя из параметров: R1=100k, R2=10k, Uemax=2,5575, применим такую формулу:Uemax = Uin*R2/R1+R2,где Uin максимальное напряжение подаваемое на вход делителя.Uin = 2,5575*110k/10k = 28,1325VИз этого мы знаем, что больше 28,1325V на вход вольтметра подавать нельзя. Также надо знать какой результат будет сохраняться в регистре
ADC при изменении напряжения на входе АЦП. Результат преобразования
вычисляется по формуле:ADC = 1024*Uemax/UrefНапример при максимальном напряжении на входе 2,5575V результат преобразования будет таким:ADC = 1024*2,5575/2,56 = 1023При напряжении на входе 2V результат будет таким:ADC = 1024*2/2.56 = 800Чтобы на индикаторе получить реальные цифры в Вольтах результат преобразования надо умножить на коэффициент равный отношению
максимального напряжения(4 разряда) подаваемого на вход делителя к
максимальному результату преобразования АЦП.k = 2813/1023 = 2,75В программе обработчика прерываний от АЦП результат преобразования перемножаем на этот коэффициент и получаем величину напряжения
подаваемого на вход делителя, т.к для операции умножения на дробное
число микроконтроллеру потребуется много памяти, существует способ
представить число 2,75 по другому, например: (ADC*11)/4. Настраиваем
регистры АЦП и Таймера2, глобально разрешаем прерывания, так же в коде
вычисляем средний показатель результата преобразования и выводим данные
на индикатор.
//Использование АЦП. Цифровой вольтметр.#include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h>//------------------0-----1-----2-----3-----4-----5-----6-----7-----8------9----dp char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80};volatile unsigned char segcounter = 0;volatile unsigned int display = 0;// Прерывание по переполнению T2, динамическая индикацияISR (TIMER2_OVF_vect){ PORTD = 0xFF; // Гасим все сегментыPORTB = (1 << segcounter); // Последовательно зажигаем общие аноды switch (segcounter){ 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; }if ((segcounter++) > 1) segcounter = 0; }volatile unsigned long value;volatile unsigned int adc_counter;// Прерывание по окончанию преобразования АЦПISR (ADC_vect){value = value + (ADC*11/4); // Суммируем старое и новое значения АЦП, преобразуемadc_counter++; // Увеличиваем счетчик измерений}// Главная функцияint main (void) { DDRB = 0xFF; // Выходы на общие анодыPORTB = 0x00; // Ноль на выходеDDRD = 0xFF; // Выходы на сегментыPORTD = 0x00; // Ноль на выходе// Настройка Таймера 2TIMSK |= (1 << TOIE2); // Разрешение прерывания по таймеру2TCCR2 |= (1 << CS21); // Предделитель на 8 // Настройка АЦП ADCSRA |= (1 << ADEN) // Разрешение АЦП |(1 << ADSC) // Запуск преобразования |(1 << ADFR) // Непрерывный режим работы АЦП |(1 << ADPS2)|(1 << ADPS1) // Предделитель на 64 (частота АЦП 125kHz) |(1 << ADIE); // Разрешение прерывания от АЦПADMUX |= (1 << REFS1)|(1 << REFS0); // Внутренний ИОН 2,56V, вход ADC0 sei(); // Глобально разрешаем прерывания// Главный цикл while(1){ if(adc_counter > 300) // Если количество измерений больше 300{display = value/adc_counter; // Вычисляем среднее значение АЦПadc_counter = 0; // Обнуляем счетчик измеренийvalue = 0; // Обнуляем буфер АЦП} _delay_ms(50);}}