Міністерство освіти і науки, молоді та спорту України
Національний університет «Львівська політехніка»
ЗВІТ
про виконання лабораторної роботи №3:
з курсу «Програмування мікроконтролерів СА»
Тема: «Вивід інформації на семисегментні елементи, що працюють в режимі динамічної індикації»
Варіант № 1
Мета роботи:
Зібрати у пакеті симуляції Proteus схему на основі МК ATmega32A та написати програму мовою Ci для реалізації вказазаного алгоритму (таблиця 2).
Завдання:
Таблиця 1.
Завдання
У завданні вказується таймер за допомогою якого потрібно реалізувати відлік інтервалів часу для зазначеного пристрою. Динамічну індикацію дозволяється реалізувати за допомогою іншого таймера.
При використанні таймера 2 в асинхронному режимі передбачається, що він тактується від годинникового кварца 32768 Гц.
Тривалість звукових сигналів вибирається студентом самостійно, дотримуючись вказаних меж.
№
п/п
Таймер
відліку часу
Частота такту-вання, Гц
Кноп-ки
Сиг-нал
Порт ке-рування
7-сегментн.
Виводи ке-рування напругами
Алго-ритм
1
T0
7.3728
PC(0-3)
PC7
PORTA
PB(1-6)
1
Таблиця 2. Варіанти пристроїв
№
п/п
Опис алгоритму роботи пристрою
1
Годинник.
Відображає години, хвилини, секунди. Запускається одразу ж при подачі живлення на МК. При співпадінні значень будильника та годинника запускається звуковий сигнал (короткими гудками) тривалістю 0,5-2 хв.
Кнопка 1 – виставляє значення годин годинника або будильника.
Кнопка 2 – виставляє значення хвилин годинника або будильника.
Кнопка 3 – відображає значення будильника та дає можливість кнопками 1 та 2 змінювати його значення.
Кнопка 4 – активізує/відключає будильник (при натисненій кнопці 3), якщо будильник активований, то у секції секунд відображається літера А.
/
Рис. 1. Схема підключення в пакеті Proteus.
Остаточна версія програми:
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/io.h>
// 0 1 2 3 4 5 6 7 8 9
const unsigned char codes[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
const unsigned char codespoint[10] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
volatile long unsigned int clock = 0; //формування 1 с
volatile long unsigned int pause = 0; //формування
unsigned char data[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char counter=0;
unsigned long buzzer=0;
unsigned long indicator=0;
unsigned char buzflag = 0;
unsigned char OffInd[2] = {0x3f,0x71};
unsigned char OnInd[2] = {0x3f,0x54};
unsigned char ringstatus = 0;
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;
//knopki
unsigned char pc0status = 0;
unsigned char ringer = 0;
//ringer
unsigned int ringminutes = 0;
unsigned int ringhours = 0;
void init_timercl (void) {
TIMSK|=(1<<OCIE0); // Дозволити переривання по співпаданню.
OCR0=0x48; // Частота 7,3728 МГц, 10ms - 72 такта.
TCCR0|=(1<<WGM01)|(1<<CS00)|(1<<CS02); // Ділити частоту на 1024.
}
void init_timer (void)
{ TIMSK=(1<<TOIE2); //Включаємо переривання таймера по переповненню
TCCR2=(0<<CS20)|(1<<CS21)|(0<<CS22); //Prescaller = /1
}
//Формування затримки
void delayc(long unsigned int Pause_ms)
{
pause = 0;
while (pause < Pause_ms)
{
}
}
void convert_data (unsigned int seconds, unsigned int minutes, unsigned int hours) {
unsigned int temp,res;
temp=hours;
res=temp/10; //Calculate 10-h
if (ringstatus == 1) {
data[0]=OnInd[0];
} else if (ringstatus == 2) {
data[0]=OffInd[0];
} else {
data[0]=codes[res];
}
temp=temp-res*10;
if (ringstatus == 1) {
data[1]=OnInd[1];
} else if (ringstatus == 2) {
data[1]=OffInd[1];
} else {
data[1]=codespoint[temp]; //Calculate 1-h
}
temp=minutes;
res=temp/10; //Calculate 10-m
if (ringstatus == 2) {
data[2]=OffInd[1];
} else {
data[2]=codes[res];
}
temp=temp-res*10;
data[3]=codespoint[temp]; //Calculate 1-m
temp=seconds;
res=temp/10; //Calculate 10-s
if (pc0status == 1) {
data[4]=0x5C;
} else {
data[4]=codes[res];
}
temp=temp-res*10;
if (pc0status == 1) {
data[5]=0x63;
} else {
data[5]=codes[temp]; //Calculate 1-s
}
}
ISR (TIMER0_COMP_vect) {
clock++;
pause++;
if (clock == 100) {
seconds = seconds + 1;
if (seconds == 60) {
minutes = minutes + 1;
seconds = 0;
if (minutes == 60) {
hours = hours + 1;
minutes = 0;
if (hours == 24) {
hours = 0;
}
}
}
clock = 0;
}
TCNT0=0x00;
}
ISR (TIMER2_OVF_vect) {
PORTA=0xff;
PORTB=~_BV(counter); //Включаємо сегмент
PORTA=~data[counter]; //Вводимо код
counter=(counter+1)%6; //Інкремент лічильника сегментів
buzzer=(buzzer+1)%1000;
indicator=(indicator+1)%10000;
//Дзвінок будильника
if ((ringer == 1) && (ringhours == hours) && (ringminutes == minutes)) {
if ((buzzer == 0) && (buzflag == 0)) {
PORTC = 0xFF;
buzflag = 1;
} else if ((buzzer == 0) && (buzflag == 1)) {
buzflag = 0;
PORTC = 0x7F;
}
} else {
}
if ((ringstatus != 0) && (indicator == 0)) {
ringstatus = 0;
}
TCNT2=0x00; //Очищаємо таймер
}
int main(void) {
DDRA=0xff;
PORTA=0x00;
DDRB=0xFF;
PORTB=0xFF;
DDRC=0x80;
PORTC=0x7F;
init_timer();
init_timercl(); //Ініціалізація таймера
sei(); //Дозвіл на переривання
while(1) {
if (pc0status == 1) {
convert_data(0, ringminutes, ringhours);
} else {
convert_data(seconds, minutes, hours);
}
//Встановлення часу
if (!(PINC &(1 << PC2)) && (pc0status == 0)) {
delayc(40);
//тут буде затримка від брязкоту контактів
hours++;
if (hours == 24)
hours = 0;
}
if (!(PINC &(1 << PC3)) && (pc0status == 0)) {
delayc(40);
//тут буде затримка від брязкоту контактів
minutes++; //добавляємо хвилини будильника
if (minutes == 60)
minutes = 0;
}
//Встановлюємо будильник
if (!(PINC &(1 << PC0)) && (pc0status == 0)) {
delayc(40);
//тут буде затримка від брязкоту контактів
// Замість секунд будемо виводити каракулі, як засіб індикації режиму/////
pc0status = 1;
//convert_data(0, ringminutes, ringhours);
}
//добавляємо години будильника
if (!(PINC &(1 << PC2)) && (pc0status == 1)) {
delayc(40);
//тут буде затримка від брязкоту контактів
ringhours++;
if (ringhours == 24)
ringhours = 0;
}
//добавляємо хвилини будильника
if (!(PINC &(1 << PC3)) && (pc0status == 1)) {
delayc(40);
//тут буде затримка від брязкоту контактів
ringminutes++;
if (ringminutes == 60)
ringminutes = 0;
}
if (!(PINC &(1 << PC1)) && (pc0status == 1)) {
delayc(40);
//тут буде затримка від брязкоту контактів
pc0status = 0; //Повертаємось до показу годинника
}
//Кнопка включення - виключення будильника
if (!(PINC &(1 << PC1)) && (pc0status == 0) && (ringer == 0)) {
delayc(40);
//тут буде затримка від брязкоту контактів
ringer = 1; //будильник вкл
ringstatus = 1;
}
if (!(PINC &(1 << PC1)) && (pc0status == 0) && (ringer == 1)) {
delayc(40);
//тут буде затримка від брязкоту контактів
ringer = 0; ////будильник викл
ringstatus = 2;
PORTC=0x7F;
}
}
return 1;
}
/
Рис. 2. Результати роботи програми.
Висновок:
На даній лабораторній роботі ми навчилися користуватись Сі компілятором. Освоїли принцип динамічної індикації семисегментних індикаторів. Результатом роботи стала програма для годинника з функцією будильника на Atmega32 .