|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
ПрограмаВимірювання напруги та струму будемо виробляти по перериванню закінчення перетворення АЦП. Якщо був обраний канал ADC1 (напруга) то знімаємо показання c АЦП, підсумовуємо з минулими показаннями і поміщаємо в буфер, потім вибираємо канал ADC0 і проробляємо ті ж самі дії для вимірювання струму. Цей цикл повторюється 400 разів, потім обчислюємо середні значення виміряних величин напруги і струму, множимо на необхідні коефіцієнти і виводимо на екран. Вихідний код нашої програми з докладними коментарями наведено нижче: // Измерение постоянного тока с помощью AVR #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h>
unsigned int voltage, current, adc_counter; volatile unsigned long voltage_value, current_value;
// Функции работы с LCD #define RS PD0 #define EN PD2
// Функция передачи команды void lcd_com(unsigned char p) { PORTD &= ~(1 << RS); // RS = 0 (запись команд) PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); } // Функция передачи данных void lcd_data(unsigned char p) { PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); }
// Функция вывода строки на LCD void lcd_string(unsigned char command, char *string) { lcd_com(0x0C); lcd_com(command); while(*string!= '\0') { lcd_data(*string); string++; } }
// Функция вывода переменной void lcd_num_to_str(unsigned int value, unsigned char nDigit) { switch(nDigit) { case 4: lcd_data((value/1000)+'0'); case 3: lcd_data(((value/100)%10)+'0'); case 2: lcd_data(((value/10)%10)+'0'); case 1: lcd_data((value%10)+'0'); } }
// Функция инициализации LCD void lcd_init(void) { DDRD = 0xFF; PORTD = 0x00;
_delay_ms(50); // Ожидание готовности ЖК-модуля
// Конфигурирование четырехразрядного режима PORTD |= (1 << PD5); PORTD &= ~(1 << PD4);
// Активизация четырехразрядного режима PORTD |= (1 << EN); PORTD &= ~(1 << EN); _delay_ms(5);
lcd_com(0x28); // шина 4 бит, LCD - 2 строки lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея _delay_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0C); // включение дисплея, курсор не видим }
// Обработчик прерывания от АЦП ISR(ADC_vect) { ADCSRA = 0; // Выключаем АЦП if((ADMUX & 0x0F)==1) // Если был выбран канал ADC1 { voltage_value = voltage_value + ADC; // Суммируем измеренные значения напряжения и помещаем в буфер ADMUX = (ADMUX & 0xF0) | 0; // Выбираем канал ADC0 } else { current_value = current_value + ADC; // Суммируем измеренные значения тока и помещаем в буфер ADMUX = (ADMUX & 0xF0) | 1; // Выбираем канал ADC1 adc_counter++; // Увеличиваем счетчик выборок АЦП на 1 } // Включаем АЦП ADCSRA |= (1 << ADEN)|(1 << ADSC)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0)|(1 << ADIE); }
int main(void) { ADMUX |= (1 << REFS1)|(1 << REFS0); // Внутренний ИОН 2,56V ADMUX |= (1 << MUX0); // Подключаем канал ADC1
ADCSRA |= (1 << ADEN) // разрешение АЦП |(1 << ADSC) // запуск преобразования |(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0) // предделитель на 128 |(1 << ADIE); // разрешение прерывания от АЦП
sei(); // Глобально разрешаем прерывания
lcd_init(); // Инициализация LCD _delay_ms(25);
lcd_string(0x80,"VOLTS * AMPERES"); lcd_string(0xC0,". *. ");
while(1) { // вычисляем среднее значение АЦП if (adc_counter > 400) { ADCSRA = 0; // Выключаем АЦП // преабразуем данные в реальное значение напряжения voltage = (voltage_value/adc_counter) * 11/4; // преабразуем данные в реальное значение тока current = (current_value/adc_counter) * 10/4;
adc_counter = 0; // Обнуляем счетчик выборок АЦП voltage_value = 0; // Обнуляем буфер значений напряжения current_value = 0; // Обнуляем буфер значений тока
// Выводим данные на LCD lcd_com(0xC0); lcd_num_to_str(voltage/100, 2); lcd_com(0xC3); lcd_num_to_str(voltage, 2);
lcd_com(0xC9); lcd_num_to_str(current/1000, 1); lcd_com(0xCB); lcd_num_to_str(current, 3);
// Включаем АЦП ADCSRA |= (1 << ADEN)|(1 << ADSC)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0)|(1 << ADIE); } _delay_ms(1); } }
Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.008 сек.) |