Wyświetlacz siedmiosegmentowy jest podstawowym urządzeniem, który w powszechnym użytkowaniu zdolny jest wyświetlać znaki.

Dziś podłączymy i zaprogramujemy mikrokontroler Atmega32 do pracy z czteroznakowym, siedmiosegmentowym wyświetlaczem, zawartym w zestawie uruchomieniowym Gotronik. 

Wyświetlacz siedmiosegmentowy, to nic innego jak zbiór diód LED. Jednemu segmentowi, odpowiada jedna dioda. W jednym wyświetlaczu zazwyczaj znajdziemy ich osiem (siedem na znaki + kropka). Można wyróżnić dwa typy wyświetlaczy siedmiosegmentowych:

  • Ze wspólną anodą – wspólnym biegunem wyświetlacza jest anoda – co oznacza że jest ona podłączona do pinu zasilania, a wyświetlacz sterowany jest katodami, czyli masą.
  • Ze wspólną katodą – wspólnym biegunem wyświetlacza jest katoda – czyli katody diód LED w segmentach podłączone są do masy, a na konkretne anody podajemy zasilanie.

Ale samo zapalenie diód w segmencie nie spowoduje jego świecenia. Za zasilenie odpowiedniego wyświetlacza odpowiada tranzystor, który też musi zostać wysterowany.

Zatem, po krótkim wstępie, możemy przejść do praktyki. Najpierw, podłączmy sobie segmenty wyświetlacza do portu mikrokontrolera. W moim przypadku, podłączyłem kolejno segmenty:

A -> PD1

B -> PD2

C -> PD3

D -> PD4

E -> PD5

F -> PD6

G -> PD7

dp -> PD0

Następnie, musimy podłączyć tranzystory zasilające wyświetlacze. Cyfra:

1 -> PA3

2 -> PA2

3 -> PA1

4 -> PA0

Sprawę sprzętową mamy już za sobą. Czas na oprogramowanie.

Aby uruchomić wyświetlacz musimy postąpić analogicznie, jak w przypadku diód LED których używaliśmy w poprzednim wpisie.

Najpierw, stwórzmy sobie tablicę znaków, które będą wyświetlane na wyświetlaczu. Pamiętasz, jak liczyliśmy którą diodę LED chcemy sobie zapalić? Analogicznie jest w tym przypadku. Rozkład segmentów przedstawia się następująco:

Wyświetlacz siedmiosegmentowy

Wyświetlacz siedmiosegmentowy

Patrząc na powyższą rozpiskę podłączonych pinów, bez problemu można stworzyć tablicę znaków. Powiedzmy, że chcemy zapalić diody które ułożą się w cyfrę 3. A więc, musimy zapalić segmenty: a,b,g,c,d. Są one podłączone do pinów, kolejno : PD1, PD2, PD7, PD3, PD4. Sumujemy ich wagi: 2 + 4 + 128 + 8 + 16 = 158. Tyle właśnie wynosi wartość dziesiętna, którą będziemy wpisywać do rejestru PD zapalając cyfrę 3. Z innymi postępujemy analogicznie.

Ale to nie wszystko. Pewnie domyślasz się, że gdy zapalimy wszystkie wyświetlacze, na wszystkich będzie ta sama liczba, tak jak w tym momencie.

Wyświetlacze bez multipleksacji

Wyświetlacze bez multipleksacji

Aby wyświetlać inny znak na każdym z wyświetlaczy, musimy dokonać tzw. multipleksacji wyświetlaczy, czyli szybkiego ich przełączania. Przełączanie to musi być na tyle szybkie, aby ludzkie oko tego nie wychwyciło.

Realizację multipleksacji można wykonać na dwa sposoby. Pierwszym z nich jest proste włączanie i wyłączanie wyświetlaczy z żądanym opóźnieniem. Jako iż mamy cztery wyświetlacze, możemy wyświetlić np. liczbę czterocyfrową. Algorytm wyłuskiwania części tysięcznych, setnych, dziesiętnych i jedności napisałem „na piechotę”. Omawiane rozwiązanie przedstawiam poniżej:

 

/*
 * WYSW_1.c
 *
 *  Created on: 23 lip 2015
 *      Author: Gotronik_1
 */


#include <avr/io.h>
#include <util/delay.h>

uint8_t tysiace, setki, dziesiatki, jednosci, wyswietl[]={126, 12, 182, 158, 204, 218, 250, 14, 254, 222};

int main (void){
	DDRD = 0xff;
	DDRA = 0x0f;

	uint16_t liczba=1342;

			jednosci = liczba % 10;
			liczba = liczba/10;
			dziesiatki = liczba%10;
			liczba = liczba/10;
			setki = liczba%10;
			liczba = liczba/10;
			tysiace = liczba%10;

	while(1){
		PORTD = ~wyswietl[tysiace];
		PORTA=~1;
		_delay_ms(20);
		PORTD = ~wyswietl[setki];
		PORTA = ~2;
		_delay_ms(20);
		PORTD = ~wyswietl[dziesiatki];
		PORTA =~4;
		_delay_ms(20);
		PORTD=~wyswietl[jednosci];
		PORTA=~8;
		_delay_ms(20);
	}
}

 

Bardziej powszechnym rozwiązaniem jest zastosowanie licznika i przerwań. Atmega32 posiada 3 liczniki. W naszym przykładzie skorzystamy z 16 bitowego Timera1. Preskaler, czyli dzielnik częstotliwości, pozwala wybrać nam z jaką częstotliwością mają być zliczane impulsy. Gdy licznik doliczy do końca swojego zakresu (2^16 ) ustawia flagę przepełnienia. Flaga ta generuje przerwanie, które następnie obsłużymy. Należy również pamiętać o włączeniu przerwań globalnych funkcją sei().

Kod źródłowy przedstawiam poniżej:

/*
 * WYSW.c
 *
 *  Created on: 21 lip 2015
 *      Author: Karol
 */

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


uint8_t tysiace, setki, dziesiatki, jednosci, wyswietl[]={126, 12, 182, 158, 204, 218, 250, 14, 254, 222};
uint8_t  wysw=0;


int main (void){
	uint16_t liczba=2222;

		jednosci = liczba % 10;
		liczba = liczba/10;
		dziesiatki = liczba%10;
		liczba = liczba/10;
		setki = liczba%10;
		liczba = liczba/10;
		tysiace = liczba%10;

	DDRD = 0xff;
	DDRA = 0x0f;
	TCCR1B |= (1<<CS10 ); //ustawienie preskalera
	TIMSK |= (1<<OCIE1A); //ustawienie bitu przepełnienia
		sei();				//włączenie przerwań globalnych



	while(1){


	}

}

ISR(TIMER1_COMPA_vect) //obsługa przerwania
{

	switch(wysw){
	case 0: {
		PORTA = ~1;
		PORTD = ~wyswietl[tysiace];
		wysw++;
		break;
		}
	case 1:{
		PORTA = ~2;
		PORTD = ~wyswietl[setki];
		wysw++;
		break;
		}
	case 2:{
		PORTA = ~4;
		PORTD = ~wyswietl[dziesiatki];
		wysw++;
		break;
		}
	case 3: {
		PORTA = ~8;
		PORTD = ~wyswietl[jednosci];
		wysw=0;
		break;
		}
				}

}


 

A efekt prezentuje się następująco:

Wyświetlacze z multipleksacją

Wyświetlacze z multipleksacją

 

Niestety aparat słabo oddaje świecenie wyświetlacza, na codzień używa się jeszcze filtrów które bardziej uwidaczniają świecące segmenty.

 

 

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *