Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Кафедра КСА
Звіт до лабораторної роботи №3
на тему «Вивід інформації на семисегментні елементи, що працюють
в режимі динамічної індикації»
з предмету «Програмування мікроконтролерів систем автоматики»
Варіант № 3
Львів 2015
Мета роботи: ознайомитися з принципами виводу інформації на семи- сегментні дисплеї у режимі динамічної індикації.
Короткі теоретичні відомості
Семисегментний графічний індикатор складається зі світлодіодних сегментів. Засвічуючи певні сегменти, можемо вивести необхідне число. Семисегментні індикатори є зі спільним анодом (+) та спільним катодом (–). Це означає, що у такому індикаторі в усіх сегментах один з виводів об’єднаний з рештою подібних виводів інших сегментів. І тоді на спільний вивід подається або високий рівень напруги (+), або низький (–), у залежності від конструкції вибраного індикатора. На решта виводів подають протилежні за рівнем напруги для засвічування сегментів.
Розглянемо індикатор зі спільним анодом. На спільний вивід подаємо високий рівень рівень, а для засвічування сегментів необхідно з МК подавати низькі рівні. На рис. 1 зображено вигляд індикатора з прийнятою літерною нумерацією сегментів, та наведена таблиця з відповідними кодами, які необхідно подати на індикатор, щоб засвітилася певна цифра.
Рис. 1. Кодування семисегментного індикатора зі спільним анодом
Для компактного для очей режиму спостереження за виводом значень на семисегментний дисплей частота блимання для кожного семисегментного елемента повинна бути в діапазоні не менше 60-70 Гц. Для шести наших елементів частота повинна бути в районі 400 Гц.
Завдання до лабораторної роботи
На основі мікроконтролера ATmega32A зібрати у пакеті симуляції Proteus схему таймера зворотного відліку та написати програму мовою Ci для реалізації алгоритму роботи пристрою:
Таймер зворотного відліку.
Реалізувати 2 таймери, що працюють незалежно один від одного. Перемикання між таймерами виконується кнопкою.
Відображаються години, хвилини, секунди. Відлік здійснюється у зворотному порядку, від встановленого значення до нуля. При досягненні значення нуль запускається звуковий сигнал (короткими гудками) тривалістю 0,5-1 хв.
Кнопка 1 – виставляє значення годин.
Кнопка 2 – виставляє значення хвилин.
Кнопка 3 – переключає між собою таймери.
Кнопка 4 – запускає на виконання відображуваний таймер або (якщо він вже запущений) скидає його значення в нуль та деактивує.
Рис. 2. Принципова схема пристрою, що зібрана у пакеті Proteus
Код програми пристрою мовою Сі
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
typedef struct{ // Масив змінних для зміни часу
int second[2];
unsigned char minute[2];
unsigned char hour[2];
}time;
time t;
unsigned char number[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc8,0x8e};
unsigned char a[6],c[6],flag[2];
volatile unsigned char b=0b00000001,d=0b00000001,count=0,count1=0,count3=0,count4=0,i=0;
volatile unsigned short count2=0;
signed char nomer1=5,nomer2=5;
int main(void)
{
DDRD =0b00111111;
DDRB =0xff; // Порт B на вихід з високим початковим рівнем
PORTB=0xff;
DDRC =0xff; // Порт C на вихід з низьким початковим рівнем
PORTC=0x00;
DDRA =0x00; // Порт A на вхід з підтягуючим резистором
PORTA=0xff;
TCCR1B |=(1<<WGM12)|(1<<CS12);
// Таймер 1 по співпад, 360Hz(2.77778ms), Prescaler=256, OCR=0x0077
OCR1AH = 0x00; // Спочатку старший біт
OCR1AL = 0x77;
TCCR0 |=(1<<WGM01)|(1<<CS02)|(1<<CS00);
// Таймер 0 по співпадінню, 20msec, Prescaler=1024, OCR=0xD7
OCR0=0xD7;
TIMSK |=( _BV(OCIE0)|_BV(OCIE1A));// дозвіл на переривання по співпадінню T0 та T1
sei(); // Дозвіл на глобальне переривання
while(1) // Основна програма
{
if(PINA==0b11111011) // Виставлення годин(кнопка 1)
{
t.hour[i]++;
_delay_ms(500);
if(t.hour[i]>23)
{t.hour[i]=0;}
}
if(PINA==0b11110111) // Виставлення хвилин(кнопка 2)
{
t.minute[i]++;
_delay_ms(500);
if(t.minute[i]>59)
{t.minute[i]=0;}
}
if(PINA==0b11011111) // Запуск таймера(кнопка 4)
{flag[i]=1;}
if(PINA==0b11011111) // Деактивація робочого таймера(кнопка 4)
_delay_ms(500);
{if(PINA==0b11011111)
{
flag[i]=0;
t.hour[i]=0;t.minute[i]=0;t.second[i]=0;_delay_ms(500);
}}
}
return 0;
}
void segment_timer1() // Формування чисел на семигментниках(перший таймер)
{
a[0]=t.second[0]%10;
a[1]=(t.second[0]-a[0])/10;
a[2]=t.minute[0]%10;
a[3]=(t.minute[0]-a[2])/10;
a[4]=t.hour[0]%10;
a[5]=(t.hour[0]-a[4])/10;
}
void segment_timer2() // Формування чисел на семигментниках(другий таймер)
{
c[0]=t.second[1]%10;
c[1]=(t.second[1]-c[0])/10;
c[2]=t.minute[1]%10;
c[3]=(t.minute[1]-c[2])/10;
c[4]=t.hour[1]%10;
c[5]=(t.hour[1]-c[4])/10;
}
ISR(TIMER1_COMPA_vect) // Підпрограма переривання таймера 1
{
// ---------------------- затримка для звучання при обнуленні таймера ----------------------
if((flag[i]==1)&&(t.hour[i]==0)&&(t.second[i]==0)&&(t.minute[i]==0))
{
if(PINA==0b11011111) // Передчасне виключання звуку після досягення нуля
{_delay_ms(300);
if(PINA==0b11011111)
{count2=10800;goto end1;}}
count2++;
if(count3==107)
{
if(count4==107)
{
count3=0;count4=0;
}
else{count4++;PORTC &= ~(1<<5);PORTD=0b00111111;}
}
else{count3++;PORTD=0x00;PORTC |= 1<<5;PORTB=number[0];}
end1:
if(count2==10800)
{
flag[i]=0;count2=0;count3=0;count4=0;PORTC &= ~(1<<5);goto end;
}
}
end:
if(i==0) // Вивід на екран чисел активного таймера
{
PORTD=~b;
PORTB=number[a[nomer1]];
if(b==0b00010000)
{PORTB &=~(1<<7);}
b=b<<1;
nomer1--;
if(nomer1==-1)
{b=0b00000001;nomer1=5;}
segment_timer1();
if(PINA==0b11101111) // Переключення таймерів(кнопка 3)
{i=1;_delay_ms(300);}
}
if(i==1)
{
PORTD=~d;
PORTB=number[c[nomer2]];
if(d==0b00100000)
{PORTB &=~(1<<7);}
d=d<<1;
nomer2--;
if(nomer2==-1)
{d=0b00000001;nomer2=5;}
segment_timer2();
if(PINA==0b11101111) // Переключення таймерів(кнопка 3)
{i=0;_delay_ms(300);}
}
}
ISR(TIMER0_COMP_vect) // Підпрограма переривання таймера 0
{
if((flag[0]==1)|(flag[1]==1))
{
start:
if(count==50)
{
count=0;
if(flag[0]==1) // Таймер1
{
if(t.second[0]==0)
{goto minute1;}
else{t.second[0]--;goto end;}
minute1:
if(t.minute[0]==0)
{goto hour1;}
else{t.minute[0]--;t.second[0]=59;goto end;}
hour1:
if(t.hour[0]!=0)
{t.hour[0]--;t.minute[0]=59;t.second[0]=59;}
if((t.hour[0]>=23)&&(t.second[0]>=59)&&(t.minute[0]>=59))
{t.second[0]=0;t.minute[0]=0;t.hour[0]=0;}
}
end:
if(flag[1]==1) // Таймер2
{
if(t.second[1]==0)
{goto minute2;}
else{t.second[1]--;goto start;}
minute2:
if(t.minute[1]==0)
{goto hour2;}
else{t.minute[1]--;t.second[1]=59;goto start;}
hour2:
if(t.hour[1]!=0)
{t.hour[1]--;t.minute[1]=59;t.second[1]=59;}
if((t.hour[1]>=23)&&(t.second[1]>=59)&&(t.minute[1]>=59))
{t.second[1]=0;t.minute[1]=0;t.hour[1]=0;}
}
}
else{count++;}
segment_timer1();
segment_timer2();
}
}
Висновки: при виконанні лабораторної роботи я закріпив навики роботи в середовищі AvrStudio, використовуючи Сі компілятор, навчився працювати з семи сегментними дисплеями, підключеними по схемі зі спільним анодом, керувати динамічною індикацією.