№
вывода
|
Название
|
Функция
|
1
|
Vss
|
Общий
(GND)
|
2
|
Vdd
|
Напряжение
питания
|
3
|
Vo
|
Контрастность
|
4
|
RS
|
Команды/Данные
|
5
|
R/W
|
Чтение/запись
|
6
|
E
|
Выбор
модуля
|
7
|
Линия
данных 0
|
8
|
DB1
|
Линия
данных 1
|
9
|
DB2
|
Линия
данных 2
|
10
|
DB3
|
Линия
данных 3
|
11
|
DB4
|
Линия
данных 4
|
12
|
DB5
|
Линия
данных 5
|
13
|
DB6
|
Линия
данных 6
|
14
|
DB7
|
Линия
данных 7
|
Таблица 5. Назначение выводов WH1602D
ЖКИ-модули могут оснащаться задней подсветкой,
размещённой между ЖКИ и печатной платой, для чего ЖКИ производится
полупрозрачным или прозрачным задним слоем. Сама подсветка может быть
реализована несколькими способами: с помощью электролюминисцентной панели,
представляющей собой тонкую плёнку, излучающей свет при прикладывании переменного
тока повышенного напряжения порядка 100…150 В; люминисцентной лампой с холодным
катодом(также работающей при повышенном напряжении), излучение которого
равномерно распределяется по всей площади ЖКИ с помощью отражателя или
светодиода; третий вариант - подсветка на основе светодиодной матрицы. Этот
вариант не требует высоковольтного источника, кроме того имеет значительно
большее время наработки. А также только она допустима к эксплуатации в
расширенном диапазоне температор(-20оС…+70 оС). Этот вариант подсветки и
используется в выбранном дисплее.
.АНАЛИЗ ПРИНЦИПА ДЕЙСТВИЯ РАЗРАБОТАННОЙ СХЕМЫ
Рисунок 2.1 - Принципиальная схема прибора ЧБ-1.
Основным элементом схемы является
микроконтроллер Atmega8 фирмы ATMEL. К порту D контроллера подключён
знакосинтезирующий ЖКИ дисплей WH1602D следующим образом: нулевой пин порта D
подключён к входу RS - командный флаг - если подать 0, то мы посылаем команду.
Если 1 -посылаются данные.
Первый пин к входу RW - Чтение/запись - 1 -
читаем данные, 0 - записываем.
Второй пин на вход E - импульс - чтобы модуль
начал обработку данных с остальных контактов, необходимо установить 1 на время
подачи сигналов.
Третий мин оставляем свободным.
С четвёртого по седьмой - четырёхразрядная шина данных(4
пин порда D соответствует четвёртому пину порта данных, пятый пятому и т.д.).
Первые четыре разряда порта данных дисплея подводим к «земле».
Также в LCD дисплее имеются контакты VDD и VSS,
к которым подводят +5 вольт и «землю» соответственно.
Оставшийся контакт - VEE - отвечает за
контрастность изображения. Если закоротить на минус, то получим максимальную
контрастность. Необходимо этот контакт подключить к минусу через резистор
номиналом 4.7 кОм(номинал определён опытным путём с помощью переменного
резистора).
Далее рассмотрим пины порта B микроконтроллера.
Порт используется для настройки часов и будильника, а также для подачи
информационного сигнала на динамик.
Так, к нулевому пину порта подключена кнопка «+1
Hour», которая добавляет 1 час к значению времени(при замыкании на пин подаётся
низкий уровень).
Первый пин используется для подключения динамика
и вывода мелодии во время срабатывания будильника.
Ко всем последующим пинам также подключены
кнопки:
Пин два - плюс 10 минут к значению времени\будильника.
Пин три - плюс 1 минута к значению
времени\будильника.
Пин четыре - плюс 1 день к значению
даты\будильника.
Пин пять - плюс 1 месяц к значению
даты\будильника.
Пин шесть - останавливает проигрывание мелодии
при срабатывании будильника.
Пин семь - переключает между отображением
времени-даты и настройкой будильника.
От порта С задействованы лишь выводы SDA и
SDL(пин четыре и пять соответственно). Они используются для образования связи с
часами реального времени(RTC) DS1307 по I2C шине.
Ко входам X1 и X2 подключается кварцевый
резонатор с частотой 32768 Гц(«часовой» кварц). Производитель DS1307
рекомендует заземлить корпус кварца, для уменьшения погрешности.
Ко входам SCA и SCL подводится +5 вольт через
подтягивающие резисторы. Также эти входы образуют шину I2C с соответствующими
входами микроконтроллера.
3.РЕАЛИЗАЦИЯ ПРОГРАММНОЙ ЧАСТИ
.1 Описание работы программы
Реализовать инкрементирование секунды можно
несколькими способами:
. Используя встроенный в микроконтроллер таймер,
сконфигурированный на вызов прерывания по совпадению.
. Используя внешнюю микросхему.
Рассмотрим оба варианта.
В первом случае необходимо настроить таймер на
определённую частоту, кратную основной частоте микроконтроллера (в нашем случае
она равна 4 МГц). Предделитель должен быть кратен степени двойки. Например,
возьмём предделитель равный 1024. Тогда 4 * 106 / 1024 = 3906 - частота работы
таймера, Гц. Для вызова прерывания необходимо задаться каким-либо числом для
сравнения. Если взять число 7812(вдвое больше частоты работы таймера), то
прерывание будет срабатывать каждые две секунды(поскольку Гц = 1/с, то число
3906 означает число тактов в секунду. И с заданным числом для сравнения как раз
и сравнивается число тактов). Поскольку нам нужно инкрементировать значение
часов каждую секунду, то число для сравнения должно быть 3906. Этот вариант не
гарантирует высокой точности хода.
Второй вариант предусматривает использование
отдельной микросхемы, отвечающей за ход часов. Всё, что нужно для работы -
задать начальное значение даты и времени, а также подключить внешний «часовой»
кварц. Далее и будем использовать этот вариант.
Из всех существующих микросхем была выбрана
DS1307 ввиду её распространённости, простоты использования и дешевизны. Для
получения текущего значения времени будем использовать прерывания по таймеру
так, как было описано выше.
Средства используемой среды
разработки(CodeVisionAVR) позволяют сильно упростить работу с LCD дисплеем,
предлагая готовые функции инициализации и вывода символов. Но при этом мы
обязаны работать по четырёхразрядной шине, вместо восьмиразрядной, что повлияет
на скорость вывода информации. Обновлять информацию на дисплее будем сразу
после считывания значения времени с микросхемы DS1307 в том же прерывании.
Для обеспечения возможности настройки часов и
будильника, порт B микроконтроллера будет опрашивать состояние кнопок,
соединенных с «землёй».
.2 Описание исходного кода программы
Строки 1-19: подключение необходимых
заголовочных файлов, конфигурирование микроконтроллера для работы с внешними
устройствами.
Строки 21-39: объявление глобальных переменных с
заданием начальных значений.
Строки 43-50: функция, вызываемая по прерыванию
таймера. Обнуляет значение счётчика, изменяет изначально заданное число для
сравнения(поскольку при инициализации на дисплей выводится информационное
сообщение и во время его отображение прерывание срабатывать не должно) и
вызывает функцию Display();
Строки 52-67: функция About(). Выводит на
дисплей «бегущую» строку с информацией об устройстве и её авторе.
Строки 69-74: функция Delay_note(). Используется
для обеспечения возможности задания «паузы» в работе с помощью
переменной(встроенная функция delay_ms() способна принимать только константы).
Это необходимо при проигрывании мелодии, т.к. время задержки звука задана в массиве
и для каждой ноты разное значение задержки.
Строки 76-108: функция Alarm(). Вызывается,
когда значение даты и времени совпадает со значением переменных, хранящих
настройки будильника. Она выводит на дисплей сообщение о включении будильника и
проигрывает мелодию, задавая логические уровни на входе динамика с определённой
частотой, значение которых хранится в массиве.
Строки 110-222: функция Display(). Обрабатывает
значением переменных времени, предотвращая ввод неверных значений
времени(например, если значение hour=23, то нажимая на кнопку «+1 Hour»,
значение hour обнуляется, инкрементируя значение переменной day, после чего
выводит информацию на дисплей. Аналогичные операции функция проделывает, если
идёт работа с настройкой будильника.
Строки 224-298: функция Setting().Отвечает за
обработку нажатия кнопок, соответствующим образом подстраивая часы или
будильник. Также отвечает за остановку будильника.
Строки 300-354: функция main(). Производит
начальную настройку портов ввода\вывода, значение регистров таймера, включает
прерывания, после чего инициализирует LCD дисплей и сразу же вывод
информационное сообщение с помощью функции About(). Затем инициализирует работу
I2C шины и микросхемы RTC DS1307, задаёт ей начальные значения даты и времени,
после чего входит в бесконечный цикл, вызывая функцию Settings() для обработки
нажатия клавиш и проверяя необходимость включения будильника.
ЗАКЛЮЧЕНИЕ
В данном курсовом проекте была написана
программа для микроконтроллера Atmega8 фирмы ATMEL. Программа была написана на
языке С и составляет более 350 строк кода, реализующих взаимодействие со
сторонними устройствами, вместе образующие устройство часов с функцией
будильника. Разработка программы велась в среде программирования CodeVisionAVR
1.25.
Спроектированная принципиальная электрическая
схема и созданная «прошивка» микроконтроллера проверены с помощью программного
продукта Proteus 7.10 SP0, позволяющего симулировать работу электрических схем.
В процессе выполнения проекта были сделаны обоснования выбора способа решения
поставленной задачи, даны описания используемых компонентов.
СПИСОК ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ
http://piclist.ru/D-DS-DS1307-RUS/D-DS-DS1307-RUS.html
(дата обращения: 24.08.2012)
<http://my-avr.at.ua/publ/1-1-0-17> (дата
обращения: 24.08.2012)
Datasheet ATmega8. © Atmel
Corporation. <http://www.atmel.com/> (дата обращения:
24.08.2012)
Белов
Л.В. Самоучитель разработчика устройств на микроконтроллерах AVR. - СпБ.:
«Наука и техника», 2008 г. - 196 с.
ПРИЛОЖЕНИЕ
#include <mega8.h>
// I2C Bus functions
#asm
.equ __i2c_port=0x15 ;PORTC
.equ __sda_bit=4
.equ __scl_bit=5
#endasm
#include <i2c.h>
#include <ds1307.h>
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>
#include <stdio.h>
#include <delay.h>
#include <bcd.h>
al_cl=0;char lcd_buffer[33];char
hour=10; char min=2;char sec=30; char day=10; char month=9;char year=12; char
hour_b=12;char min_b=0; char day_b=10; char month_b=9;char melody[] =
{99,175,109,107,106,102,99,144,111,175,96,99,107,107,107,107,102,104,170,96,99,109,109,109,109,107,106,143,109,141,99,109,109,109,109,111,176,96,104,116,112,109,107,106,64,73,143,107,131,99,144,80,80,112,111,64,75,173,128,0};int
notefreq[] =
{0,4748,4480,4228,3992,3768,3556,3356,3168,2990,2822,2664,2514,2374,2240,2114,1996,1884,1778,1678,1584,1495,1411,1332,1257,1187,1120,1057,998,942,889,839,792};int
pausedelay[] = {32,64,128,256,512,1024,2048,4096};
max_day[]={31,28,31,30,31,30,31,31,30,31,30,31};
#pragma rl+ char arr[] = "
Курсовой проект студента группы #113319 Гундина
Александра. 2012. (Часы-будильник)
" ;
#pragma rl- Display();
// Timer 1 output compare A
interrupt service routine[TIM1_COMPA] void timer1_compa_isr(void)
{H=0;L=0;AH=0x0F;AL=0x42;();
}About(void)
{ int i=0 , a=0;
_gotoxy(0,0);
(i=0; i < sizeof(arr)-16 ; i++)
{(a=0; a<15 ; a++)
{_gotoxy(a,0); _putchar(arr[i+a]);
}_ms(50);
}
} delay_note (unsigned int delay)
{ i;(i=0; i< delay; i++) _ms(1);
}Alarm()
{ char freqnote;// Код
нотыchar
delaynote;// Код длительностиchar
tmp;// Временная
переменная
cnt;
_clear();(lcd_buffer,"
ALARM!!!");
lcd_puts(lcd_buffer);=0;// На начало мелодии
while (melody[cnt]!=0)
{ (PINB.6==0) // Stop ALARM;
=melody[cnt];= tmp&0x1F;// Код
ноты
delaynote = (tmp>>5)&0x07;// Код
длительности(freqnote!=0)// Если не пауза
{// включаем
звукA=notefreq[freqnote];A=0x40;
}_note(pausedelay[delaynote]); // выдерживаем
длительность
нотыA=0x00;
//выключаем
звук
delay_note(8); //выдерживаем паузу
//чтоб две ноты не сливались в одну++;//
Следующая нота
} _clear();
} Display()
{ (al_cl==0) //режим
Alarm/clock(+)
{
/// Условия часов.(sec>59) // если сек = 60
{++; // добавляем 1 к переменной
"минута"
sec=0; //зануляем
переменную
"секунда"
_set_time(hour,min,sec);
}(min>59) // если мин = 60
{++; // добавляем 1 к переменной "час"
min=0; // зануляем
переменную
"минута"
_set_time(hour,min,sec);
}(hour>23) // так как у нас часы имеют 24
часовый формат
{ // при достижении 24 часов, онулируем все
переменные.
hour=min=sec=0;++;
_set_time(hour,min,sec); _set_date(day,month,year);
} ((month==2) &&
((year%4)==0))
{(day > max_day[month-1]+1)
day=1;(day==0) day = max_day[month-1]+1;
}
{(day > max_day[month-1])
day=1;(day==0) day = max_day[month-1];
}
(month>11)
{=day=1;++;
_set_date(day,month,year);
}
_get_time(&hour,&min,&sec); //считать
время_get_date(&day,&month,&year);
//считать
дату
_gotoxy(4,0);
_putchar(hour/10+0x30);_putchar(hour%10+0x30);_putchar(':');_putchar(min/10+0x30);_putchar(min%10+0x30);_putchar(':');_putchar(sec/10+0x30);_putchar(sec%10+0x30);
_gotoxy(4,1);_putchar(day/10+0x30);_putchar(day%10+0x30);_putchar('.');_putchar(month/10+0x30);_putchar(month%10+0x30);_putchar('.');_putchar(year/10+0x30);_putchar(year%10+0x30);
}
{ (min_b>59) // если
мин
= 60
{_b++; // добавляем 1 к переменной
"час" =0; // зануляем переменную "минута"
}(hour_b>23) // так как у нас часы имеют 24
часовый формат
{ // при достижении 24 часов, онулируем все
переменные.
hour_b=0;_b=0; _b++;
} ((month_b==2) &&
((year%4)==0))
{(day_b > max_day[month_b-1]+1)
day_b=1;(day_b==0) day_b = max_day[month_b-1]+1;
}
{(day_b > max_day[month_b-1])
day_b=1;(day_b==0) day_b = max_day[month_b-1];
}(month_b>11)
{=1;=1;
} _gotoxy(0,0);
_putchar('A');_putchar('l');_putchar('.');_putchar('
');_putchar(hour_b/10+0x30);_putchar(hour_b%10+0x30);_putchar(':');_putchar(min_b/10+0x30);_putchar(min_b%10+0x30);_gotoxy(4,1);_putchar(day_b/10+0x30);_putchar(day_b%10+0x30);_putchar('.');_putchar(month_b/10+0x30);_putchar(month_b%10+0x30);
}
}Setings()
{ (al_cl==0) //режим
Alarm/clock(+)
{(PINB.0==0) //+1 HOUR
{_ms(250); // задержка
1/4 сек.
(для
удобства)
выбора++;_set_time(hour,min,sec);
}(PINB.2==0) // +10 MIN
{_ms(250); (min<50)min+=10;
_set_time(hour,min,sec);
}(PINB.3==0) // +1 MIN
{_ms(250); ++;
_set_time(hour,min,sec);
}(PINB.4==0) // +1 DAY
{_ms(250); ++;
_set_date(day,month,year);
} (PINB.5==0) // +1 MONTH
{_ms(250); ++;
_set_date(day,month,year);
} (PINB.7==0)
{_ms(250); _cl=1;
}
}
{ (PINB.0==0)
{_ms(250); _b++;
}(PINB.2==0)
{_ms(250); (min_b<50)min_b+=10;
}(PINB.3==0)
{_ms(250);_b++;
}(PINB.4==0)
{_ms(250); _b++;
}(PINB.5==0)
{_ms(250); _b++;
} (PINB.7==0)
{_ms(250); _cl=0; _clear();
}
}
}main(void)
{tmp;=0xFF; =0x02;=0xFF;=0x00;
=0xFF;=0x00;
=0x80;A=0x00;B=0x05;H=0x00;L=0x00;H=0x00;L=0x00;AH=0xB7;AL=0x00;BH=0x00;BL=0x00;
// Timer(s)/Counter(s) Interrupt(s)
initialization=0x10;
// LCD module
initialization_init(16);();
// Global enable interrupts
#asm("sei")c_init();_init(0,1,0);=rtc_read(0x00);=tmp&0b01111111;_write(0x00,tmp);=rtc_read(0x02);=tmp&0b10111111;_write(0x02,tmp);_set_date(day,month,year);
//установить
дату:
день,месяц,год
rtc_set_time(hour,min,sec); //установить время:
часы, минуты, секунды
lcd_clear(); (1)
{ ();(hour==hour_b &&
min==min_b && day==day_b && month==month_b) // срабатывание
будильника
Alarm();
};
}
1.