АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Програма

Читайте также:
  1. III. ПРОГРАМА НАВЧАЛЬНОЇ ТА ВИРОБНИЧОЇ ПРАКТИКИ В ОРГАНАХ ДЕРЖАВНОЇ ВИКОНАВЧОЇ СЛУЖБИ УКРАЇНИ
  2. IV ПРОГРАМА ПРАКТИКИ
  3. V. Програма підготовки
  4. Діагностична програма.
  5. Економічна програма народництва.
  6. Інформаційна програма на радіо
  7. Інформаційна програма на ТБ
  8. Конкурсна програма до Дня святого Валентина Серця двох
  9. МОДУЛЬНА ПРОГРАМА
  10. НАВЧАЛЬНА ПРОГРАМА КУРСУ «Політична риторика».
  11. Особливості приватизації в Україні. Державна програма, приватизаційні папери
  12. Пізнавально-розважальна програма ВАЛЕНТИН і ВАЛЕНТИНА

Вимірювання напруги та струму будемо виробляти по перериванню закінчення перетворення АЦП. Якщо був обраний канал 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);

}

}

 


1 | 2 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.008 сек.)