В настоящее время при построении систем управления различным технологическим оборудованием все чаще стали использовать микроконтроллеры. Причем наиболее распространенными из них являются микроконтроллеры фирмы ATMEL. В работе рассматривается один из подходов практического использования микроконтроллера ATmega8 для решения трех практических задач:
1.Определение температуры с использованием датчика DS18B20 и в зависимости от ее значения моделирование управлением оборудованием.
2.Измерение постоянного напряжения в диапазоне от 0 до 15 вольт.
3. Измерение времени (цифровые часы).
Принципиальная схема устройства для решения перечисленных задач представлена на рис.1.
Рис.1
Для отображения информации о времени, измеряемом напряжении, температуре, используется жидкокристаллический индикатор с числом столбцов и строк 16х2 соответственно (LCD 16x20), который поддерживает систему команд, совместимую с контроллером HD44780 (фирма Hitachi) и его аналогами, например, KS0066 (фирма Samsung), SED1278 (фирма Epson), ST7066 (фирма Sitronix). В качестве микроконтроллера выбран ATmega8-16 илиATmega8L-8. Последняя модель отличается меньшей тактовой частотой (8МГц) и меньшим энергопотреблением. Для измерения температуры используется цифровой датчик DS18B20 температуры с точностью до 0,0625 C (при разрешающей способности температурного преобразователя 12 бит) и диапазоном от -55 до +125 С. Датчик с микроконтроллером сопрягается по протоколу 1wire. Иначе 1wire – это однопроводной интерфейс, позволяющий подключить к одной линии данных практически неограниченное количество периферии. Каждое устройство имеет уникальный 64-х битный идентификационный номер.
При включении устройство на индикаторе отображает в течение 5 секунд свое назначение и далее в бесконечном цикле отображает время, постоянное напряжение любого подключенного источника питания в пределах от 0 до 15 вольт и температуру. Если температура превысит 32 градуса C (по представленной программе), загорается светодиод (моделирование управлением оборудования). Если температура опускается ниже 32 градусов, светодиод гаснет (оборудование отключается).
После изготовления устройства по схеме на рис.1. в микроконтроллер должна быть загружена программа с помощью программатора. В качестве программатора был использован простой, но надежно работающий адаптер для COM порта (рис.2) и программа PonyProg ( http://www.lancos.com/prog.html )
Рис.2
Программирование устройства (рис.1) выполнялось на языке Си. И если учесть, что в архитектуру AVR изначально были заложены принципы оптимизации Си-процедур, то альтернативы этому алгоритмическому языку нет.
Для программирования микроконтроллера ATMega8 воспользуемся компилятором языка Си CodeVision AVR фирмы HP InfoTech, Румыния (http://www.hpinfotech.ro/html/cvavr.htm). Он популярен тем, что включает в себя
- Кросс-компилятор Си, обеспечивающий выполнение почти всех элементов языка Си, разрешенных архитектурой AVR;
- Интегрированную среду разработки, в состав которой входит программатор чипов AVR для автоматической пересылки кодов после компиляции в микроконтроллерный чип через адаптер, а также набор библиотек Си для работы с LCD модулями, температурными датчиками, часами реального времени и т.д.;
- Автоматический генератор программ CodeWizardAVR, позволяющий написать за несколько минут весь код необходимый для выполнения таких функций, как инициализация таймеров/счетчиков, инициализация LCD, инициализация АЦП и др.
Рассмотрим последовательно этапы программирования микроконтроллера для решения представленной выше задачи. Предположим, что пакет CodeVision AVR установлен на компьютере. В работе в качестве примера используется CodeVision AVR Version 1.25.8 Professional. Перед запуском программы CodeVision AVR создаем каталог, где будут храниться файлы.
1. Запускаем CodeVision AVR и выбераем пункт CodeWizardAVR:
2.Выбираем тип микроконтроллера и частоту:
3.Выбираем LCD и подключаем его к порту D:
Видно, что автоматически устанавливается соответствие между подключаемыми битами микроконтроллера и выводами LCD модуля.
4.Инициализируем шину 1Wire и температурный датчик DS1820, хотя по заданию используется датчик DS18B20. Это делается для подсказки вызова необходимых библиотек. Впоследствии в программе будут произведены необходимые замены. Датчик устанавливаем на 3-й бит порта C:
5.Заходим во вкладку Timers. Выбираем для ATMega8 Timer 1:
В качестве источника тактовой частоты (Clock Source) выбираем System Clock, т.е. таймер будет тактироваться с частотой, на которой работает микроконтроллер (8MHz). Выберем тактовую частоту для таймера-счетчика (ClockValue) равную 7,813kHz. Она получается делением частоты работы микроконтроллера на коэффициент деления(1024). Включаем прерывание (Interrupt on), которое должно произойти, если в регистре A появиться значение, указанное в поле Comp.A. Поле Value определяет начальное значение таймера-счетчика. Таким образом, наш таймер должен «тикнуть» 7813 раз, чтобы прошла ровно 1 секунда, если кварцевый резонатор идеально настроен на частоту 8 MHz. Однако при делении 8 MHz на делитель частоты 1024 получается 7.8125kHz. Поэтому в поле Comp.A необходимо поставить или 7812 или 7813 тактов (1e84 или 1e85 для шестнадцатеричной системы исчисления). Однако, как показал опыт с практически используемым кварцевым резонатором на 8 MHz, значение 7811 тактов оказалось наилучшим, что привело к опережению времени только на 1 секунду в сутки. Эта величина и установлена в программе после практической корректировки. Для получения наибольшей точности часов можно программно через каждые 24 часа от полученного времени отнимать 1 секунду.
6.Заходим последовательно в вкладки File -> Generate, Save and Exit:
Даем имена проекту и исходному файлу. В результате появится окно с текстом программы на языке Си:
7. Корректируем программу в окне текстом программы, который представлен ниже:
#include
#include
#include
#include
// Вставка ассемблерного кода (1 wire)
#asm
.equ __w1_port=0x15 ;PORTC
.equ __w1_bit=3
#endasm
#include <1wire .h=""> 1wire>
// Вставка ассемблерного кода (LCD)
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include
#include // подключаем библиотеку задержки
#define VREF 5000 // Определяем опорное напряжение в миливольтах
unsigned int s; // переменная сек.
unsigned int m; // пересенная мин.
unsigned int h; // переменная часов
// Вызов функции обработки прерывания Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Увеличиваем секунду на 1 в случае появления в регистре A числа 7813(изм. на 7811)
TCNT1H=0;
TCNT1L=0;
s++;
}
void main(void)
{
// Declare your local variables here
int temp,temp3;
float temp1,temp2,volt1;
unsigned long volt;
char lcd_volt[8],znak[2],lcd_buffer[16];
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0xFF;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x03;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x1E; // Частота работы таймера
OCR1AL=0x84; // Скорректирована на 7812 (1E84)
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// LCD module initialization
lcd_init(16); // Инициализация LCD
// Глобальное разрешение прерываний
#asm("sei")
w1_init(); // Инициализация линии 1 wire
lcd_gotoxy(0,0); // Позиционируем вывод на начало 1-й строки
lcd_putsf(" Time Voltmetr"); // Выполняем вывод
lcd_gotoxy(0,1); // Позиционируем на начало 2-й строки
lcd_putsf(" Termoregulator"); // Выполняем вывод
DDRB.0=1; // Переводим в режим вывода 0-й бит порта B
PORTB.0=1; // Устанавливаем на выходе 0 порта B логическую единицу
delay_ms(5000); // Удерживаем вывод в течении 5 секунд
lcd_clear(); // Очищаем экран LCD
m=0; // Обнуляем минуты
h=0; // и часы
// Устанавливаем режим работы АЦП
ADMUX &= 0xDF & 0x7F & 0xF2; ADMUX |= 0x40 | 0x02; // Разрядность 10бит, опорное напряжение AVCC Вольт,
// внутренний источник опорного напряжения, линия PC2
// ADCSRA &= 0xFE;
ADCSRA |= 0x80 | 0x40 | 0x20 | 0x07; // Включить АЦП, запуск нового замера, постоянное измерение,
//частота АЦП=8.0МГц/128
while (1) // Запуск бесконечного цикла измерений
{
if (PINC.0==0) // если нажата первая кнопка (порт C бит 0)
{
m++; // к значению минуты добавляем единицу
}
if (PINC.1==0) // если нажата вторая кнопка (порт C бит 1)
{
h++; // к значению часов добавляем единицу
}
// Условия часов.
if(s==60) // если сек = 60
{
m++; // добавляем 1 к переменной "минута"
s=0; // зануляем переменную "секунда"
}
if(m==60) // если мин = 60
{
h++; // добавляем 1 к переменной "час"
m=0; // зануляем переменную "минута"
}
if (h==24) // так как у нас часы имеют 24 часовый формат
{ // при достыжении 24 часов, зануляем все переменные.
h=0;
m=0;
s=0;
}
// Выводим переменные (время)
lcd_gotoxy(0,0);
lcd_putchar(h/10+0x30);
lcd_putchar(h%10+0x30);
lcd_putchar(':');
lcd_putchar(m/10+0x30);
lcd_putchar(m%10+0x30);
lcd_putchar(':');
lcd_putchar(s/10+0x30);
lcd_putchar(s%10+0x30);
// Определяем напряжение
volt=ADCL;
volt += ((int)ADCH << 8);
volt=volt*VREF/1024;
volt1=volt/1000.0;
volt1=3.224*volt1; // Вычисляем напряжение в соответсвии с выбранным делителем напряжения
// Выводим напряжение
sprintf(lcd_volt," U=%5.2f",volt1);
lcd_puts(lcd_volt);
// Определяем и выводим температуру
temp1=ds18b20_temperature(0); // Функция определения температуры для одног датчика
sprintf(znak,"+");
if (temp1 < 0.0 ){ // Определяем знаки температуры
temp1=-temp1;
sprintf(znak,"-");
}
// Формируем дробное значение температура при работе с целыми числами (это полезно
// в целях экономии памяти)
temp=temp1;
temp2=temp1-temp;
temp3=100*temp2;
if (temp>=32){ // Если температура больше или равна 32 град.
PORTB.0=0; // Выставит ноль на нулевом выходе порта B (включится светодиод)
}
if (temp<32 32="" nbsp="" o:p="">32>
PORTB.0=1; // Выставит единицу на нулевом выходе порта B (выключится светодиод)
}
// Вывод температуры
lcd_gotoxy(0,1);
sprintf(lcd_buffer," temp = %s%i.%i",znak,temp,temp3);
lcd_gotoxy(0,1);
lcd_puts(lcd_buffer);
}; // Закрыть бесконечный цикл
} // Закрыть программу main()
8. Выбираем закладку Project->Configure->C Compile и устанавливаем в поле (s)printf Features значения float,width,precision
9.Компилируем проект (команда Compile):
10. Собираем проект командой Make:
В каталоге, где расположена программы на Си, появится файл с расширением .hex, который необходимо будет переслать в микроконтроллер с помощью адаптера и программатора. Для этой цели воспользуемся программой-программатором PonyProg, которая должна быть предварительно установлена на компьютере со свободным COM портом. После установки PonyProg должна быть выполнена процедура ее калибровки. Для этого необходимо зайти в закладки Setup->Calibration и нажать на Yes.
Рассмотрим следующие этапы использования программы PonyProg.
1.Запускаем программу и настраиваем интерфейс связи между компьютером и микроконтроллером:
Указываем использование адаптера для связи с COM портом:
2.Открываем файл с расширением .hex
3.После загрузки файла заходим в закладку Command->Security and Configuration Bits и устанавливаем фьюз-биты (биты конфигурации). Ниже на рисунке представлена заводская конфигурация фьюз-битов для ATMega8. Для нашей конфигурации необходимо снять все галочки и нажать на Write.
4.Выполняем передачу файла микроконтроллеру по команде Ctrl-P. Или можно зайти во вкладку Command и курсором мышки выбрать Program. В случае успешной передачи программы в микроконтроллер должно появиться окно с надписью Program succesful. При программировании необходимо не забыть на устройство подать напряжение (10…15В). После ввода программы устройство должно сразу же заработать.
Выводы.
1.Показан на простом примере возможный способ управления с помощью распространенных и недорогих микроконтроллеров технологическим оборудованием на основе таймера, температуры, напряжения.
2.На основании используемого пакета CodeVision AVR показано, как просто и прозрачно на языке Си создается программное обеспечение для функционирования микроконтроллера фирмы Atmel.
3.Приведена схема простейшего надежно работающего адаптера и последовательность работы с программатором для пересылки откомпилированной программы в микроконтроллер.
Литература.
1. Рюмик С.М. Микроконтроллеры AVR. Ступень 1. http://forum.radiospec.ru/index.php?showtopic=5612 - 2007
Комментариев нет:
Отправить комментарий
Создайте свой комментарий.