Bölüm-6 Sürücü Entegreleri İle Çalışmak

7447 ve 7448 BCD - 7-Segment Gösterge Sürücüleri

Mikrodenetleyiciler ile profesyonel düzeyde çalışırken fiziki sınırları zorlayan koşullarla karşılaşırız. Mikrodenetleyicilerin pin sayısının yetersiz kalması bu sorunlardan biridir. Bu tür sorunları aşmak amacıyla pin sayısını daha etkin ve idareli kullanmamızı sağlayan çeşitli sürücü entegreleri vardır. Amaca uygun ve doğru bir tercihle sınırlı sayıda pini bulunan mikrodenetleyicinizi daha fazla sayıda noktayı kontrol etmede kullanabilirsiniz.

Sürücü entegrelerinin kullanılmasının bir başka avantajı da mikrodenetleyicinin çıkış pinlerinin tamponlanması ve böylece akım koruması sağlanmasıdır. Sürücü entegreleri yardımıyla daha yüksek akım çeken devre bileşenleri ile mikrodenetleyici arasında koruma sağlanmış olur.

7-Segment göstergelerin mikrodenetleyiciler ile sürülmesi 3 numaralı başlık altında gösterilmişti. Dikkat edileceği üzere göstergenin sahip olduğu bacak sayısı kadar mikrodenetleyici çıkışı kullanılmıştı. Birden fazla göstergenin kullanılması durumunda, mikrodenetleyicinin pin sayısı yeterli gelmeyeceğinden göstergelerin paralel bağlanması ve tarama tekniğiyle sürülmesi de açıklanmıştı. Tek bir çıkış hattından çok daha fazla sayıda göstergenin tarama tekniğiyle sürülmesi belirgin bir kıpraşmaya neden olabilir. Bu durum görsel olarak istenmeyen bir durum yaratır. 7-segment göstergeleri kendi aralarında gruplayarak sürebiliriz. Bu durumda fazladan pin ihtiyacı ortaya çıkacaktır. Böyle bir durumda kullanacağımız pin sayısını azaltmak için 7-segment göstergeler için geliştirilmiş ve giriş pin sayısı daha az olan sürücü entegresi kullanmak gerekir.

Ek-I7’de ortak anotlu 7-segment göstergeler için kullanılan TTL seviyeli 7447 ve ortak katotlu 7 segment göstergeler için kullanılan 7448 sürücü entegreleri ayrıntılı olarak açıklanmıştır. Bu sürücü entegreleri yardımıyla ihtiyaç duyulan 7 pin sayısı BCD giriş formatında olan 4 pin sayısına düşürülür.

Şekil 6.1’de halı sahalarda da gördüğümüz ikişer haneli sonuç ekranı (skor board) uygulaması görülmektedir. Bu uygulamada her iki takım için de ikişer gösterge kullanılmıştır. Mikrodenetleyici olarak PIC16F887 seçilmiştir ve her ortak katotlu gösterge için bağımsız olarak birer 7448 BCD – 7 segment ortak katot sürücü entegresi kullanılmıştır. Bu uygulamada da tarama tekniği kullanılmıştır ancak göstergeler ikişer gruba ayrılmıştır. Dolayısıyla toplam 8 pin entegrelerin sürülmesi için tahsis edilmiştir. Mikrodenetleyicinin B portu üzerinden bağlanan butonlar yardımıyla A ve B takımları için skor değerlerinin ileri/geri yönde hareket ettirilmesi sağlanmıştır.

Şekil-6.1 İki haneli dijital skor ekranı

4.8 numaralı başlıkta harici zaman kesmesinin kullanımında anlatılan 4 segmentli dijital saat uygulamasından farklı olarak bu devrede UDN2981A kaynak sürücüsü entegresi kullanılmıştır. Uygulamanın gerçek fiziki hayatta anlamlı olabilmesi için bu tür sürücü entegrelerinden sıklıkla yararlanılır. Bilindiği üzere hobi amaçlı ya da küçük boyutlu uygulamalarda 9 mm genişliğinde ufak 7 segment göstergeler 5V çalışma altında yeterli gelmektedir. Ancak daha büyük boyutlu ve uzak mesafeden görülmesi gereken görüntü uygulamalarında doğal olarak bu tür göstergeler anlamlı olmayacaktır.

Uygulama aynı akımı çeken ancak bu akımı daha yüksek çalışma voltajı altında çeken büyük boyutlu göstergelerde kullanabilmek için tasarlanmıştır. UDN2981A sürücü entegresi, mikrodenetleyiciler ve TTL entegreleri gibi standart 5V çalışma voltajı altında çalışan devre bileşenleriyle daha yüksek DC gerilimlere ihtiyaç duyan devre bileşenlerinin sürülmesinde tercih edilir. Piyasada 100 mm ve 200 mm boyutlarında 7-segment göstergeler bulunmaktadır. Bu göstergeler ideal olarak 12-15V DC gerilime ihtiyaç duyar.

UDN2981A sürücü entegresi 8 giriş için 8 çıkış sunan çalışma kaynak gerilimi aralığı 5V – 50V arasında olan ve 15V çalışma altında her bir çıkışından 120 mA akım çekilebilen bir entegre devre bileşenidir. Girişleri 5V’luk TTL sitemlerle uyumlu çalışacak şekilde tasarlanmıştır. Daha ayrıntılı bilgi için veri kılavuzunu incelemeniz tavsiye edilir.

Şekil-6.2 UDN2981A entegre devresinin pinleri

Kitabın haberleşme protokolleri ve uygulamaları başlığı altında SPI seri iletişim tekniğinden bahsedilecektir. Bir SPI donanımı olan MAX7219 BCD – 7-segment ortak katot sürücü entegresinden yalnızca 1 adet kullanmak suretiyle bu uygulamanın daha az sayıda MCU pini kullanan modelini tasarlamak mümkündür.

Uygulamanın daha yüksek performansla çalışması için dâhili 8 MHz osilatörle çalışabilen PIC16F887 mikrodenetleyicisi tercih edilmiştir. Uygulamanın kaynak kodu Tablo 6.1’de gösterildiği gibidir.

Tablo 6.1 İki haneli dijital skor ekranı uygulaması mikroC kodu

#define AI1 PORTA.RA0
#define AI2 PORTA.RA1
#define BI1 PORTA.RA2
#define BI2 PORTA.RA3
#define ileriA PORTB.RB0
#define geriA PORTB.RB1
#define ileriB PORTB.RB2
#define geriB PORTB.RB3
unsigned short zaman, arttir, azalt;
unsigned char birlerA, onlarA, birlerB, onlarB;
unsigned int taramasuresi=40;
short sayacA=0, sayacB=0, sayac11, sayac22;
void port_Init(void);
void main() {
 port_Init();
 while(1){
  birlerA=sayacA%10; //sayaç A degerinin birler basamagi aliniyor.
  onlarA=(sayacA/10)%10;//sayaç A degerinin onlar basamagi aliniyor.
  birlerB=sayacB%10; //sayaç B degerinin birler basamagi aliniyor.
  onlarB=(sayacB/10)%10;//sayaç B degerinin onlar basamagi aliniyor.
  AI1 = 1; //A takimi 1'ler basamagi aktif yapiliyor
  AI2 = 1; //A takimi 10’lar basamagi aktif yapiliyor
  BI1 = 0; 
  BI2 = 0; 
  sayac11 = birlerA<<4;
  PORTC=sayac11+onlarA; /* Birler basamaginin bilgisi displaylere   
  gönderiliyor */
  Vdelay_ms(taramasuresi);
  AI1 = 0;
  AI2 = 0;
  BI1 = 1; //B takimi 1'ler basamagi aktif yapiliyor
  BI2 = 1; //B takimi 10'lar basamagi aktif yapiliyor
  sayac22 = birlerB<<4;
  PORTC=sayac22+onlarB; /* Onlar basamaginin bilgisi displaylere 
  gönderiliyor */
  Vdelay_ms(taramasuresi);
  if(ileriA==0){
   delay_ms(100);
   if(ileriA==0){
    sayacA++;
    if(sayacA>99) sayacA=0;
   }
  }
  if(geriA==0){
   delay_ms(100);
   if(geriA==0){
    if(sayacA==0) sayacA=99;
    else sayacA--;
   }
  }
  if(ileriB==0){
   delay_ms(100);
   if(ileriB==0){
    sayacB++;
    if(sayacB>99) sayacB=0;
   }
  }
  if(geriB==0){
   delay_ms(100);
   if(geriB==0){
    if(sayacB==0) sayacB=99;
    else sayacB--;
   }
  }
 }
}
//Portlar ve kesmeler ayarlaniyor
void port_Init(void){
 OSCCON = 0X72; //8MHz dâhili osilatör
 OPTION_REG = 0; //Dâhili pull-ap'lar aktif
 WPUB = 0X0F; //B potu ilk 4 pini için weak pull-up'lar aktif
 ANSEL = 0; //tüm portlar dijital I/O
 ANSELH = 0;
 CM1CON0 = 0; //karsilastiricilar kapali
 CM2CON0 = 0;
 TRISA = 0;
 PORTA = 0;
 TRISB = 0x0F; //B portu ilk 4 pini giris
 PORTB = 0;
 TRISC = 0;
 PORTC = 0;
 TRISD = 0;
 PORTD = 0;
 TRISE = 0;
 PORTE = 0;
}

74HC595 Kaydırmalı Kaydedicisi

Kaydediciler (Registers) sayesinde tek bir hat üzerinden seri bilgi paralel olarak işlenebilir. Mikrodenetleyicinin portları aynı anda çok sayıda cihazı kontrol etmeye yeterli gelmeyebilir. Kaydediciler sayesinde port çoklaması gerçekleştirilerek özellikle kayan yazı ve grafik LCD uygulamalarında yüksek performans elde edilebilir. Çok sayıda dotmatriks bir ekrana kayan yazı efektinin uygulanması kaydedici entegrelerinin kullanımıyla mümkün olmaktadır.

Yaygın olarak kullanılan kaydedici entegrelerinden olan 74HC595 bir kaydırmalı kaydedicidir (Shift Register). CMOS yapısıyla mikroişlemci ve mikrodenetleyici gibi CMOS yapısına sahip entegrelerin seri iletişim arabirimlerine doğrudan bağlanabilir. Paralel çıkışları hafıza özelliklidir, diğer bir ifadeyle bir önceki durumu tutabilir. Bu durum elektronikte ‘latch’ olarak adlandırılır. Şekil 6.3’te 74HC595 entegresinin entegre şeması ve lojik diyagramı gösterilmiştir. Çalışma voltajı aralığı 2-6 V arasıdır.

Şekil-6.3 74HC595 8 bitlik kaydırmalı kaydedici entegresi

Bu entegrenin doğru şekilde kullanılabilmesi için bacak işlevlerini kısaca bilmek gerekir. Tablo 6.2’de bacak isimleri ve işlevleri verilmiştir.

Tablo 6.2 74HC595 kaydırmalı kaydedici bacak isimleri ve işlevleri
Pin Noİsimİşlevi
14A veya DSSeri veri girişidir. Bu bacaktaki veri 8 bit seri kaydırmalı kaydediciye gönderilir.
11SH_CPKaydırma darbesi (Shift Register) girişi. Girişin düşükten yükseğe giden durumunda (low to high) seri veri girişi 8 bitlik kaydırmalı kaydediciye kaydırılır.
10MRAktif düşük, kaydırmalı kaydedici reset girişi. Girişe Lojik-0 uygulandığında cihazın yalnızca kaydırmalı kaydedici kısmını resetler. Tutma (Latch) kısmı etkilenmez.
12ST_CPTutma darbesi girişi. Girişin düşükten yükseğe giden durumunda kaydırmalı kaydediciye gelmiş olan veri tutulur.
13OEAktif düşük çıkış etkinleştirme girişi. Girişe Lojik-0 uygulandığında tutma kısmındaki verinin çıkışa aktarılması sağlanır. Girişe Lojik-1 uygulanması durumunda QA – QH (Q0 – Q7) çıkışları yüksek empedans durumuna geçer. Seri çıkış bu durumdan etkilenmez.
15, 1-7QA – QH veya Q0 – Q7Evirmeyen, 3 durumlu tutma çıkışlarıdır.
9SQH veya Q7’Evirmeyen, seri veri çıkışı. 8 bitlik kaydırmalı kaydedicinin sekizinci durumunun çıkışıdır. Bu çıkış 3 durumlu değildir.

74HC595 entegreleri kaskad bağlanarak çok sayıda 8 bitlik verinin sıralı olarak kaydırılması sağlanır. Bu entegrenin kaskad bağlanması için 9 numaralı SQH çıkışı bir sonraki entegrenin DS girişine bağlanır. 74HC595’in çalışma mantığının anlaşılması mikrodenetleyici ile kontrol etmenizi kolaylaştırır ve karmaşık uygulamaları hatasız hazırlamanızı sağlar. Şekil 6.4’te PROTEUS-ISIS® programında kaskad bağlı iki kaydırmalı kaydedici entegresinin çalışma ilkesi gösterilmiştir.

Şekil-6.4 Kaskad bağlı 74HC595'lerin çalışma ilkesi

Bu devrede CLK ve LATCH olarak isimlendirilmiş girişler PROTEUS-ISIS® programının LOGICTOGGLE aracı kullanılarak kontrol edilmektedir. CLK’nın her yükselen kenarında seri bilginin bir biti kaydırmalı kaydedicinin LSB bitine yazılır. Bu yazılan bilginin çıkışa aktarılması için LATCH girişine de yükselen kenar tetiklemesi uygulanmalıdır. Sıralı gelen bilginin diğer bitlerinin kaydediciye yazılması için CLK girişinin yeniden tetiklenmesi gerekir. Her tetiklemede seri olarak gelen bilginin tetikleme anındaki biti kaydedicinin LSB bitine yazılır. Daha önceden yazılmış bitler sırayla bir sonraki bite kaydırılır. LATCH girişi tetiklenmediği sürece bu sıralı kaydırılan bilgi çıkışa aktarılmaz. İlk kaydedicinin 9 numaralı çıkışı bir sonraki kaydedicinin seri girişi olur. Böylece en baştan gönderilen seri bilgi sıralı olarak diğer tüm kaskad bağlı kaydedicilere iletilmiş olur.

74HC595 kaydırmalı kaydedicisinin Darbe (SH_CP - Clock), Veri (DS - Data) ve Tutma (ST_CP - Latch) girişleri mikrodenetleyici tarafından sürülmek suretiyle kaydedici çıkışları istenildiği gibi kontrol edilebilir. Bilgi bir bit kaydırılıp bir kez saat darbesi gönderilir ve bu işlem 8 bitlik (genelde) byte halinde entegreye yazılır. Eğer peşi sıra bilgi yazılacaksa ve entegreler sıfırlanmaz veya resetlenmez ise gönderilen bir sonraki paket veri yazımında gelen veriler ilk entegreye yazılır ve daha önce ilk entegrede olan veriler 2. entegreye kaydırılır. Çıkış aktif yapılınca bilgiler görüntülenir.

Sadece port genişletme veya gösterge sürme gibi işlemler yapılacaksa bu entegreler Şekil 6.4’teki gibi bağlanıp reset ucu +5 Volta, Çıkış Etkinleştirme (Output Enable - OE) ucu – şaseye bağlanmalıdır. Eğer daha fonksiyonel bir devre yapılacaksa ve bilgi peşi sıra aktarılmayıp ayrı demetler halinde tüm entegrelere tek seferde yazılacaksa o zaman reset ucu da mikrodenetleyiciyle kontrol edilecektir.

Kaydırmalı Kaydediciye MCU İle Veri Yazma

Şekil 6.5’teki devrede mikrodenetleyicinin girişlerindeki bitlerin sıralı olarak çıkışa aktarılmasını sağlayan bir uygulama gösterilmiştir. Mikrodenetleyicinin 4 bit paralel veri girişi 74HC245 üç durumlu çift yönlü alıcı/verici (transceiver) entegresi üzerinden gerçekleştirilmiştir. Uygulamada Mikrodenetleyicinin port değişim algılama özelliğine sahip B portunun RB4-7 portları kullanılmıştır. Portlardan herhangi birinde meydana gelen değişim durumunda 4 bitlik veri tarama yöntemiyle seri olarak 74HC595 kaydırmalı kaydediciye gönderilmektedir.

Şekil-6.5 Mikrodenetleyici ile kaydırmalı kaydediciye veri yazılması

Uygulamada mikrodenetleyicinin RA0 portu Darbe (Clock), RA1 portu Veri (Data) ve RA2 portu Tutma (Latch) çıkışları olarak kullanılmıştır. 74HC245 alıcı/verici entegresinin 1 numaralı Yön Kontrol (Direction Control - DIR) pini lojik-1 olduğu müddetçe B portunun RB4-7 pinlerinden birinde gerçekleşecek değişim 74HC595 entegresine aktarılmaktadır. Bu uygulamada verinin okunup seri olarak gönderilmesi ve tekrar paralel olarak çıkışta gösterilmesi tamamen yazılım yöntemiyle yapılmaktadır.

Tablo 6.3 74HC595 kaydırmalı kaydedicisinin sürülmesi mikroC kodu

#define clock PORTA.B0
#define data PORTA.B1
#define latch PORTA.B2
unsigned short kesme_port_degeri=0,kesme_pin_ara_deger1=0,
kesme_pin_ara_deger2=0,kesme_pin_ara_deger3=0,
kesme_pin_ara_deger4=0,sayac,veri,temp;
unsigned short yuru_tablo[] ={1,2,4,8,64,128,256};

void spi (unsigned short veri)
{
 unsigned short i;
 unsigned char temp;
 temp = veri;// veri ara değişkene aktarılıyor
 i=4;
 if(temp!=0){ // RB4-7 portlarının sıfırdan farklı olma durumu
  while (i>0){
   if (temp.F7==0) data = 0; /* verinin kaydırılma işleminden sonra veya
           ilk kez 7. biti  kontrol ediliyor */
   else data = 1;
   temp = temp<<1;// veri bir bit sola kaydırılıyor
   clock=1;       // veri 595de  bir kez öteleniyor
   latch=1;       // veri dışarıya aktarılıyor*/
   delay_ms(1000);// Tarama görsel olarak görülebilecek bir hızda
   clock=0;
   latch=0;
   i--;
  }
 }
 else{ // RB4-7 portlarının 0 olması durumu
  while(i>0){
   data = 0;
   clock = 1;
   latch = 1;
   delay_ms(50); // Hızlı tarama yapılıyor
   clock = 0;
   latch = 0;
   i--;
  }
 }
}

void ayarlar(){
 CMCON=0x07; /*Karşılaştırıcı modül kapatıldı Portlar dijitale ayarlandı*/
 INTCON.GIE  = 1; // Tüm kesmelere izin verildi
 INTCON.RBIE = 1; // PortB4-7 kesmesi aktifleştiridi
 PORTB=0;
 TRISB=0xF0; // PortB4-7 kesmeye ayarlandığı için RB4-7 giriş
 PORTA=0;
 TRISA=0x00;
}

/* B portunun 4 ile 7 pinleri arasından hangisine veya hangilerine basıldığı bulunuyor */
void kesme_hesaplama(){
 if(PORTB.B4)kesme_pin_ara_deger1=16;
 if(PORTB.B5)kesme_pin_ara_deger2=32;
 if(PORTB.B6)kesme_pin_ara_deger3=64;
 if(PORTB.B7)kesme_pin_ara_deger4=128;

// Tüm ara değerler toplanarak PORTB 4 7 değeri hesaplanıyor
kesme_port_degeri=kesme_pin_ara_deger1+kesme_pin_ara_deger2+kesme_pin_ara_deger3
    +kesme_pin_ara_deger4;
 if((PORTB.B7==0)&&(PORTB.B6==0)&&(PORTB.B5==0)&&(PORTB.B4==0))kesme_port_degeri=0;

// Tüm ara değerler yeni kesme girişleri için temizleniyor
 kesme_pin_ara_deger1=0;
 kesme_pin_ara_deger2=0;
 kesme_pin_ara_deger3=0;
 kesme_pin_ara_deger4=0;
}

// Kesme alt yordamı
void interrupt(){
 if(INTCON.RBIF){
  kesme_hesaplama();
  spi(kesme_port_degeri);/* kesme gerçekleştiği anda spi alt programı
  çalıştırılıp kesme port değeri fonksiyona alınıp gönderiliyor */
  INTCON.RBIF = 0;
 }
}
void main(){
 ayarlar();
}


Kaydırmalı Kaydedici İle Çoklu Ekran Kontrolü

Mikrodenetleyicilerle kaydırmalı kaydedicilerin yaygın olarak kullanıldıkları alanlardan birisi kayan yazı uygulamalarıdır. 8x8 Hücreli nokta matris LED panellerden çok fazlası kullanılacak ve kayan yazı gibi bir uygulama yapılacaksa, çıkışı tutma özellikli kaydırmalı kaydedicilerin kullanımı tercih edilir. Şekil 6.6’da 8 satır (R1-R8) ve 8 sütundan (C1-C8) oluşan bir nokta matrisin LED diziliminden oluşan yapısı gösterilmiştir.

Şekil-6.6 8x8 Nokta matris iç yapısı

Bu matris göstergelerde karakter oluşturulması 8-bitlik ASCII kod ilkesine göre gösterilecektir. Her ne kadar tasarlanan uygulama 8x8 matrislerle gerçekleştirilmiş olsa da karakter genişlikleri 5x8 ölçüleriyle sınırlandırılmıştır. R1-R8 (Row) hatlarıyla gösterilen uçlar 74HC595 kaydırmalı kaydedicisinin çıkışlarına bağlanacak pinlerdir. C1-C8 hatları (Column) ise mikrodenetleyicinin ilgili portuna sırasıyla bağlanacak olan pinlerdir. Tasarımınıza bağlı olarak satır ve sütun hatlarının bağlantısını değiştirebilirsiniz.

5x8 bir düzlemde örnek olarak ‘A’ harfinin kodunun nasıl türetildiği Şekil 6.7 üzerinde gösterilmiştir (http://dotmatrixtool.com/# sitesinde karakter kodunun nasıl üretildiğini gösteren bir web tabanlı uygulama mevcuttur).

Şekil-6.7 8x8 Nokta matris için karakter üretilmesi

Şekilde görüldüğü üzere 8x8 nokta matris üzerinde 5x8 boyutunda üreteceğimiz karakteri öncelikle sağa hizalı olarak hazırlıyoruz. Her bir satırı 1 baytlık veri olarak düşünecek olursak 00h – FFh arasında değişen bir onaltılı kod elde edileceği görülür. D3-D0 arasını baytımızın LSB kısmı, D7-D4 arasını ise MSB kısmı olarak düşünürsek örnek karakter için şekilde elde edilmiş kodu bulursunuz.

Şekil 6.8’de benzer mantıkla tasarımı yapılmış 5 adet 8x8’lik nokta matris kayan yazı sürücü devresi gösterilmiştir. Yapılan uygulamada nokta matrislerin sütun hatları (katot bacakları) mikrodenetleyicinin portu üzerinden sürüldüğü için bu portların çıkışına yeterli sayıda 7404 entegresi bağlanmalıdır. 7404 entegresi içinde bağımsız olarak 6 adet NOT kapısı bulunduran bir lojik tersleme entegre devresidir. Dolayısıyla bu entegreden iki adet kullanılması gerekir.

PROTEUS-ISIS® programında çizim kolaylığı olması açısından 74HC595 ile nokta matris göstergeler arasına direnç çizilmemiştir. Gerçek uygulamada her bir bacak için olmak üzere toplamda 5x8 = 40 adet 330 Ω direnç bağlanmalıdır.

Şekil-6.8 8x8 Nokta matris ile kayan yazı uygulaması

ASCII kodu tablosunda ekrana yazdırılabilir karakterler “32” boşluk karakteriyle başlar. Yaygın olarak kullanacağımız tüm karakterleri 32 kodundan başlayarak sıralı şekilde gittiğimizde ‘ ~ ’ işaretine kadar toplamda 95 alfanümerik karakter elde ederiz. Tüm bu karakterler için bir look-up tablosu hazırlanmıştır.

Her bir karakterin 8x8 nokta matris alanı üzerine yazdırılması için 8 baytlık bir veri akışı olacaktır. Dolayısıyla program kodu içinde [95]x[8] boyutunda bir char tipinde dizi matris değişkeni oluşturulur. Ancak bilindiği üzere, mikroC’nin ANSI C standartı sayesinde char veri tipinde ilk değer ataması sırasında matris boyutunu belirtmek zorunluluğu yoktur. Bu nedenle sonradan başka karakterlerin de eklenmesi ihtimali de göz önünde bulundurularak [ ] x [8] şeklinde açık boyutlu bir dizi oluşturulur.

Tablo 6.4’te look-up tablosuyla birlikte tüm program kodu sunulmuştur. Program koduna dikkat edildiğinde [8][5] boyutunda bir tampon dizisi görülür. Bu dizi değişken ile her bir karakter kümesinin kademeli olarak bir sonraki matrise aktarılması sağlanır. 74HC595 seri veri girişi aynı anda tek bitlik veri aldığından bu tampon dizisindeki bitler okunur ve bilgi olup olmaması durumuna göre maskelenerek sıralı şekilde entegre seri veri girişine gönderilir. Diğer taraftan main() ana fonksiyonu içinde 8’lik döngüler halinde B portu sıralı şekilde aktif edilmektedir.

Tablo 6.4 8x8 Nokta matris ile kayan yazı uygulaması mikroC kodu

// 74HC595 bağlantıları tanımlanıyor
sbit Serial_Data at RA0_bit; // verinin iletildiği pin
sbit SH_Clk at RA1_bit; // veri entegre kaydedicisine alınır
sbit ST_Clk at RA2_bit; // kaydediciye alınan veri latch'e aktarılır
unsigned short Buffer[8][5] = {
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0}
};
unsigned int StringLength, uzunluk;
unsigned short i, l, k, row, scroll, temp, shift_step=1;
unsigned short m;
char default_message[]="ELEKTRONIK SEVERLER MERHABA... ";
char message[10], index;
/* ASCII karakter tablosunda 32 desimal kod numarasına sahip boşluk karakterinden
itibaren standart kullanılan karakterleri kapsayacak şekilde 8-bit
olarak oluşturulmuş nokta matris sütun kodları. LOOK-UP tablosu*/
const unsigned short CharData[][8] ={
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04}, //!
{0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}, //"
{0x00, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A}, //#
{0x07, 0x0C, 0x14, 0x0C, 0x06, 0x05, 0x0E, 0x1C}, //$
{0x19, 0x1A, 0x02, 0x04, 0x04, 0x08, 0x17, 0x13}, //%
{0x05, 0x0A, 0x12, 0x14, 0x09, 0x16, 0x2E, 0x09}, //&
{0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, //'
{0x02, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x02}, //(
{0x08, 0x04, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08}, //)
{0x15, 0x0E, 0x1F, 0x0E, 0x15, 0x00, 0x00, 0x00}, //*
{0x00, 0x00, 0x04, 0x04, 0x1F, 0x04, 0x08, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x08},
{0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
{0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10},
{0x0E, 0x11, 0x13, 0x11, 0x15, 0x11, 0x19, 0x0E}, //0
{0x04, 0x0C, 0x14, 0x04, 0x04, 0x04, 0x04, 0x1E},
{0x0E, 0x11, 0x11, 0x02, 0x04, 0x08, 0x10, 0x1E},
{0x0E, 0x11, 0x01, 0x0E, 0x01, 0x01, 0x11, 0x0E},
{0x10, 0x10, 0x14, 0x14, 0x1F, 0x04, 0x04, 0x04},
{0x1F, 0x10, 0x10, 0x1E, 0x01, 0x01, 0x01, 0x1E},
{0x07, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x11, 0x0E},
{0x1F, 0x01, 0x01, 0x01, 0x02, 0x04, 0x08, 0x10},
{0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x11, 0x0E},
{0x0E, 0x11, 0x11, 0x0F, 0x01, 0x01, 0x01, 0x01}, //9
{0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x04, 0x00}, //:
{0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x04, 0x08}, //;
{0x01, 0x02, 0x04, 0x08, 0x08, 0x04, 0x02, 0x01}, //<
{0x00, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x00}, //=
{0x10, 0x08, 0x04, 0x02, 0x02, 0x04, 0x08, 0x10}, //>
{0x0E, 0x11, 0x11, 0x02, 0x04, 0x04, 0x00, 0x04}, //?
{0x0E, 0x11, 0x11, 0x15, 0x15, 0x11, 0x11, 0x1E}, //@
{0x0E, 0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11}, //A
{0x0E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x11, 0x1E},
{0x07, 0x04, 0x10, 0x10, 0x10, 0x10, 0x08, 0x07},
{0x1C, 0x12, 0x11, 0x11, 0x11, 0x11, 0x12, 0x1C},
{0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10, 0x1F},
{0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10, 0x10},
{0x0E, 0x11, 0x10, 0x10, 0x17, 0x11, 0x11, 0x0E},
{0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11, 0x11},
{0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F},
{0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x14, 0x08},
{0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11, 0x11},
{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F},
{0x11, 0x1B, 0x1F, 0x15, 0x11, 0x11, 0x11, 0x11},
{0x11, 0x19, 0x19, 0x15, 0x15, 0x13, 0x13, 0x11},
{0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E},
{0x1E, 0x11, 0x11, 0x1E, 0X10, 0x10, 0x10, 0x10},
{0x0E, 0x11, 0x11, 0x11, 0x11, 0x15, 0x13, 0x0F},
{0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11, 0x11},
{0x0E, 0x11, 0x10, 0x08, 0x06, 0x01, 0x11, 0x0E},
{0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x15, 0x0A},
{0x11, 0x11, 0x0A, 0x04, 0x04, 0x0A, 0x11, 0x11},
{0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04},
{0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x10, 0x1F},
{0x0E, 0x08, 0x08, 0x08, 0x08, 0x18, 0x08, 0x0E},
{0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01},
{0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E},
{0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F},
{0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x0E, 0x12, 0x12, 0x12, 0x0F},
{0x00, 0x10, 0x10, 0x10, 0x1C, 0x12, 0x12, 0x1C},
{0x00, 0x00, 0x00, 0x0E, 0x10, 0x10, 0x10, 0x0E},
{0x00, 0x01, 0x01, 0x01, 0x07, 0x09, 0x09, 0x07},
{0x00, 0x00, 0x00, 0x1C, 0x12, 0x1E, 0x10, 0x0E},
{0x00, 0x03, 0x04, 0x04, 0x06, 0x04, 0x04, 0x04},
{0x00, 0x0E, 0x0A, 0x0A, 0x0E, 0x02, 0x02, 0x0C},
{0x00, 0x10, 0x10, 0x10, 0x1C, 0x12, 0x12, 0x12},
{0x00, 0x00, 0x0A, 0x00, 0x04, 0x04, 0x04, 0x04},
{0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x0C},
{0x00, 0x10, 0x10, 0x14, 0x18, 0x18, 0x14, 0x10},
{0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0C},
{0x00, 0x00, 0x00, 0x12, 0x15, 0x11, 0x11, 0x11},
{0x00, 0x00, 0x00, 0x14, 0x1A, 0x12, 0x12, 0x12},
{0x00, 0x00, 0x00, 0x0C, 0x12, 0x12, 0x12, 0x0C},
{0x00, 0x1C, 0x12, 0x12, 0x1C, 0x10, 0x10, 0x10},
{0x00, 0x0E, 0x12, 0x12, 0x0E, 0x02, 0x02, 0x01},
{0x00, 0x00, 0x00, 0x0A, 0x0C, 0x08, 0x08, 0x08},
{0x00, 0x00, 0x0E, 0x10, 0x08, 0x04, 0x02, 0x1E},
{0x00, 0x10, 0x10, 0x1C, 0x10, 0x10, 0x10, 0x0C},
{0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x12, 0x0C},
{0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04},
{0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x15, 0x0A},
{0x00, 0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11},
{0x00, 0x00, 0x11, 0x0A, 0x04, 0x08, 0x08, 0x10},
{0x00, 0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F},
{0x02, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02},
{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, //|
{0x08, 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08}, //}
{0x00, 0x00, 0x00, 0x0A, 0x1E, 0x14, 0x00, 0x00} //~
};

void Send_Data(unsigned short rw){
 unsigned short Mask, t, num, Flag;
 for (num = 0; num < 5; num++) {
  Mask = 0x01;
  for (t=0; t<8; t++){
   Flag = Buffer[rw][num] & Mask;
   if(Flag==0) Serial_Data = 0;
   else Serial_Data = 1;
   SH_Clk = 1;
   Delay_us(50); // Kenar geçişleri arasında süre bırakılıyor
   SH_Clk = 0;
   Mask = Mask << 1;
  }
 }
 ST_Clk = 1;
 Delay_us(50); // Kenar geçişleri arasında süre bırakılıyor
 ST_Clk = 0;
}

unsigned int Find_StrLength(){
 uzunluk = strlen(default_message);
 return uzunluk;
}

void main() {
 CMCON = 0X07;
 TRISA = 0X00;
 TRISB = 0X00;
 PORTA = 0;
 PORTB = 0;
 StringLength = Find_StrLength();
 do {
  for (k=0; k<StringLength+4; k++){
   for (scroll=0; scroll<(8/shift_step); scroll++) {
    for (row=0; row<8; row++){
     index = default_message[k]; // mesajın içinden sıradaki karakter çekiliyor
     temp = CharData[index-32][row]; /* çekilen karakterin tek bir satır değeri alınıyor */
     Buffer[row][4] = (Buffer[row][4] << Shift_Step) | (Buffer[row][3] >> (8-Shift_Step));
     Buffer[row][3] = (Buffer[row][3] << Shift_Step) | (Buffer[row][2] >> (8-Shift_Step));
     Buffer[row][2] = (Buffer[row][2] << Shift_Step) | (Buffer[row][1] >> (8-Shift_Step));
     Buffer[row][1] = (Buffer[row][1] << Shift_Step) | (Buffer[row][0] >> (8-Shift_Step));
     Buffer[row][0] = (Buffer[row][0] << Shift_Step)| (temp >> ((8-shift_step)-scroll*shift_step));
    // shif_step değeri ile karakterlerin kaç sütun ilerleyeceği
    // belirleniyor. Varsayılan olarak 1'e ayarlı
    }
    m = 1; // port çıkışlarını sıralı aktif etmek için
    for (i=0; i<8; i++) {
     Send_Data(i);
     PORTB = m;
     m = m << 1;
     Delay_ms(4); // Tarama geçişleri arasındaki süre.
    } // i
   } // scroll
  } // k
 }while(1);
}