4' lü 7 Segment sürme algoritması ( Standart Display değil )

Başlatan M_B, 27 Temmuz 2013, 17:31:36

M_B

Merhabalar;
Elimde bitisik olarak 4 haneli 7 segment display var. Alt resimdeki  ( 4 adet nokta mevcut )



Kartta 4 tane sn74hc595 5 tanede uln2003 entegre kullanılmıs.
uln2003 bir tanesini noktaları yakmak ıcın kullanılmıs.  Diger 4 tanesi de Displayi surmek icin.
İlk veri giren 595  in Qa-Qb-Qc-Qd cıkıslarını noktalar icin kullanmış diğer cıkısları da 1-dijit ıcın kullanmış.
1 dijit icin 1. 595 'in Qe-Qf-Qg-Qg ve ikinci 595'in Qa-Qb-Qc lerini kullanmış ( Tablodan da gozukeceği üzerine )

   

Bu displayı sürebilmem icin nasıl bir algoritma kurmalıyım.  595 'ler birebir dijitlere baglı olsa sorun olmayacaktı.
Tablodan da gorulecegi üzerine bir dijiti sürmek icin iki 595 'den yararlanmış. ( mecburen veri kayması olmus )

Altaki sema ise Displayların baglantı şekli


ete

Neden çok kolay halledilecek bir işi çok zor bir hale getirmişler?. Neden böyle deli saçması bir bağlantı yapılmış?
Bunun algoritması falan olmaz. Resmen oturup kim kime gidiyor hesaplayacaksın ve ona göre değer vereceksin. Oda yetmez. Veri kaydırılırken diğerine ne geçiyor dikkat etmek lazım. Yada şöyle diyelim her seferinde 4 adet byte vermen lazım. birini verdin diğerinde kim kime kayıyor dikkat etmen gerekiyor. Çok zor bir iş bu. Tabiiki imkansız değil. Ama gerçekten neden böyle yapılmış anlamak isterdim doğrusu.

Gelelim Sürme tekniğine; Bunu açıklamadan önce bu bağlantıların doğruluğundan iyice emin olmanı isterim doğrusu.
Data sol baştan girdiğine göre her girilen byte ileri kayacak demektir. O halde ilk verilen bilgi en sağdaki displaye ait olacak.
Öncelikle bir varsayım yapalım. En sağdan sola doğru 1-2-3-4  şeklinde rakamların displaylerde yer alacağını varsayalım.
BU sayıların basmaklara göre 7 segment karşılıkları şöyle olsun.
BIRLER=%01100110   '4
ONLAR=%01001111   '3
YUZLER=%01011011  '2
BINLER=%00000110  '1

Bu durumda öncelikle 4 bilgisini önden göndermemiz gerekecek. 4'ün 7 segment karşılığı, 102 yada binary olarak %01100110
Ancak bu bilgiyi vermesi gereken 595'in bacak çıkışları şöyle %4d-4e-4f-4a-4b-4c-4g-3d Şimdi Birler basamağını bu çıkışlara göre düzenleyelim.
TEMP=((BIRLER & %00000111) REV 3)<<2  önce (a-b-c segment bitlerini alıyoruz yalnız sıralama c-b-a şeklinde. Sonra bunu sıralamasını a-b-c şekline getirip 2 bit sola kaydıracağız.

B=(A REV 3)<<2   REV komutu A sayısının sağdan sola doğru 3 bitini kendi içinde yer değiştirir. Bunu 2 bit sola kaydırınca B sayısı B=%xxxabcxx şeklini alacaktır.
Sonra bunu VERI4 isimli değişkenimizde yerine yerleştirelim. VERI4=VERI4 | TEMP
Şimdi  g segment değerini yerine yerleştirelim  VERI4.1=BIRLER.6
Şimdi BIRLER değişkeninden f-e-d segment değerlerini çekelim. Sonra bunun bitlerini ters çevirip sıralamayı d-e-f şeklinde sokalım ve 5 bit sola kaydırarak tam yerine yerleşecek hale getirelim.   TEMP=((BIRLER & %00111000) REV 6) <<5
Bunuda VERI4 isimli değişkenimize yerleştirelim VERI4=VERI4 | TEMP
Dikkat ederseniz sondaki VERI4 değişkeninin sıfır NOLU biti 3 nolu displayin "d" biti değerini taşıyacaktır. O halde bunuda yerleştirirsek sondaki 595'in verisi hazır hale gelmiş olacaktır.
ONLAR= %01001111  'bu 3 sayısının 7 segment karşılığıdır. 3. nolu displayde bu sayı gözükecektir. Bu sayının "d" biti ONLAR.3 dür. O halde VERI4.0=ONLAR.3 şeklinde vereceğimiz eşitlik ile sonda yer alan 595 verisi tamamlanmış olacaktır.

Şimdi devamla 3nolu displayin verisini hazırlayalım.
VERI3  formatı şöyle olacak=%3e-3f-3a-3b-3c-3g-2d-2e 
ONLAR=%01001111 idi. İlk yapmamız gereken  c-b-a bitlerini alıp yerine yerleştirmek olmalı.
TEMP=((ONLAR & %00000111) REV 3)<<3   şeklinde bir satırla bunu halledebileceğiz. Bu satırda ONLAR değişkeninin sağdan 3 biti alınıyor. Bitler c-b-a sıralamasından a-b-c sıralamasına çevriliyor ve 3 bit sola kaydırılıyor. Şimdi bunu VERI3 isimli değişkenimize yerleştirebiliriz.  VERI3=VERI3 | TEMP
Şimdi YUZLER değişkenininde d ve e bitlerini alıp sıfır ve 1 nolu bitlerin yerine yerleştirerek bu segmenti de tamamlamış olacağız.  VERI3.1=YUZLER.3  ve VERI3.0=YUZLER.4
g segment değerinide aktaralım VERI3.2=YUZLER.6
Böylece ikinci 595 in veriside hazır olmuş oldu.

Şimdi devamla 2 nolu displayin verisini hazırlayalım.  VERI2  formatı şöyle olacak=%2f-2a-2b-2c-2g-1d-1e-1f 
YUZLER=%01011011  idi
TEMP=((YUZLER & %00000111) REV 3)<<4   'c-b-a bitlerini alıp a-b-c yapıp 4 bit sola kaydırdık
VERI2=VERI2 | TEMP 'yerine yerleştirdik.
VERI2.7=YUZLER.5
VERI2.3=YUZLER.6
TEMP=(BINLER & %00111000) REV 6
VERI2=VERI2 | TEMP  böylece ilk displayin d-e-f bitlerinide VERI2 ye yerleştirmiş olduk.  böylece VERI2 işlemide tamamlanmış oldu.

Şimdi son display verisini hazırlayalım.
VERI1 formatı şöyle olacak =%1a-1b-1c-1g-n4-n3-n2-n1 (n1=Nokta1)
BINLER=%00000110 idi.
TEMP=((BINLER & %00000111) REV 3)<<5   c-b-a bitlerini alıp ters çevirip 5 bit sola kaydırdık.
VERI1=VERI1 | TEMP
VERI1.4=BINLER.6
VERI1.3=Nokta.3
VERI1.2=Nokta.2
VERI1.1=Nokta.1
VERI1.0=Nokta.0
Böylece bütün display değişkenleri tamamlanmış oldu.

Şimdi bunları aktarmak için aşağıdaki satırı kullanacağız.
SHIFTOUT DTA,CLK,1,[VERI4,VERI3,VERI2,VERI1]
PULSOUT KILIT,1
bu şekilde displaylerde 1234 rakamşlarını görmemiz gerekir.

Umarım gerisini becerirsin . Beceremez isende örnek program ilişiktedir.

Ete

Edit: ufak birde kusur varmış onu düzelttim dosya yenilenmiştir.

M_B

Ete Hocam Allah sizden razı olsun.
Mantığını çok güzel anlatmışsınız. Ptesi günu ilk işim sizin kodu deneyip sonucu bildirmek olacak.
Bağlantı şekli gerçekten cok farklı düşünülmüş ben cihazın eski olmasına yorumluyorum.
Aynı kartan bir tane daha var display bağlantıları aynı onda ek olarak 40 pinli mc68 hc705c9 işlemci var.
Bu cihaz network uzerinden saat ve tarih bilgisi alıp gösteriyor. Bunu ben modifiye edip saat tarih ısı şekline sokmak istiyorum.
Ekranlar çok canlı ve güzel diye uğraşmak istedim. Ama bağlantının bu şekilde olacağı hiç aklıma gelmemişti.

Şimdi hocam basicteki  REV komutunu C de yapmaya calışacam. Hocam REV komutun acılımı nasıldır.

Hocam size tekrardan Teşekkür ederim.
Hocam sizin algoritma kurma mantıgınıza hayranım ;)





ete

REV komutu revers sin kısaltılmışı olup açılımı aşağıdaki şekilde verilmiş;

REV reverses the order of the lowest bits in a value. The number of bits to be reversed is from 1 to 16.

Example :   B0 = %10101100 REV 4 ' Sets B0 to %10100011

REV  x   şeklinde kullanılıyor veya  A=B REV x  şeklinde de kullanılabiliyor.
X burada ters çevrilecek bit sayısını ifade ediyor. Diyelimki 3 adet bit ters çevrilecek SAYI=%00000cba şeklinde bitleri olsun
SAYI=SAYI REV 3  şeklinde bir komut kullandığımız zaman SAYI=%00000abc şekline dönmektedir. Tamamen bit sıralamasını değiştiren ve değiştirmeyide istediğin adet de yapan bir komut. x olarak 8 kullanırsanız bitlerin tamamını yer değiştirir.
AKıllıca kullanılırsa sizin displayde lazım olan çevirme işlemlerini gördüğünüz gibi yapar.
Dikkat etti isen senin işinde bazı bitler 8 bitlik sayının ortasında yer alıyordu. Mesela SAYI=%00cba000 şeklinde. Bu gibi durumlarda değişecek bit den itibaren sona kadar olan bitleri değiştirmek gerekiyor. Bu örnekte şöyle yapılmalı,
SAYI=SAYI REV 6  ve SAYI değişim sonucu şu şekli alıyor. SAYI=%00000abc göreceğin gibi değişecek bit sayısı kendi içinde yer değiştirmektedir. Dahada formülize edersek SAYI=%00123456  REV 6 denildiğinde SAYI=%00654321 şeklini almaktadır.
Umarım açıklayıcı olmuştur. Güzel bir komut aslında bir parametre daha eklense daha da mükemmel olurdu. REV başla,bitir şeklinde. Ama bunada şükür. C dilinde de benzer bir komut olduğunu düşünüyorum. Önce araştır. Yok ise döngü kurarak da hallede bilirsin. REV komutu olmasa şöyle yapardım.
SAYI=%00654321 olan dizilişi SAYI=%00123456 şeklinde çevirmek için

önce DEGISMIS diye bir değişken tanımlar ve sonra döngüyü kurardım.
DEGISMIS=SAYI:X=5     '(SAYI nın değişmeyen bitlerini almak için önce DEGISMIS=SAYI diyoruz.)
FOR I=0 to 5
DEGISMIS.0[I]=SAYI.0[X]
X=X-1
NEXT
bu şekilde toplam 6 adet bit de yer değiştirmiş olacaktır.
Ete

Bu arada verdiğim örneği biraz daha geliştirip RAKAM isimli değişkenden digitleri alarak ekrana verme şeklinde düzenledim.
Dosyayı yeniledim.

M_B

Gunaydın Hayırlı Haftalar Ete hocam;
Son verdiğiniz kodu denedim goruntu altaki gibi.
Not: Hocam ekranda 4 nokta varya onlardan bir tanesi sekılde gozuktugu gibi diğerleri 7 ile 8 arasında iki tane ust uste diğer 4. ise sagdaki 8 in alt kısmında. Sadece noktaların nerde cıktıgını bildirmek istedim.

Not: Sımulasyonda calısıp burda yarım calısması acaba baglantıları mı yanlıs bıldırdım dıye dusunuyorum. Gun icinde tekrar baglantıları kontrol edecem. (Simulasyonda ki baglantı ile mi uyusmadı dusuncesi var )



ete

Displayin 2 adedi düzgün diğe rikisi yanlış ise bağlantı sorunu gibi gözüküyor. Elbette başka bir garip bağlantı daha yapmış olabilirler. Devrede 5 adet ULN olması gerektiğini sen söylemişsin. Bunlarıda isis şemasına eklesen fena olmaz. Belki onlara bağlı bir kusur vardır.
Ekrana 5-6-7-8 verdiğimize ve 7-8 in doğru çalıştığını gördüğümüze göre ilk iki displayin bağlantılarını dikkatlice kontrol etmen gerekiyor.

Ete

M_B

Hocam baglantıları tekrar kontrol ettim. Farklı bir şey goremedim.
Hatta şu şekilde yaptım.
ULN cıkıs uclarını GND ye cekerek hangi Displayın aktif oldugunu gordum.

Pcb üzerinde acıklama yaptım

Ornegin:
ULN 10 pin ucu  g segmentini yakıyor.
İsis dosyasının Uln li cizimini ekledim.

M_B

Hocam artı olarak ta söyleyim.
595 lerin cıkıs uclarını Uln2003 in giriş üclarını da kontrol ettim.
Semadaki gibi bire bir gidiyor. İşin kotu tarafı simulasyonda calısıp kartta calısmaması ilginc.


Ekleme-1:

Hocam ilk verdiğiniz programı denediğimde de goruntu yoktu. Ama simulasyonda vardı

Ekleme-2 :
Hocam aslında 7 ve 8 de duzgun cıkmamış oluyor.  Cunku Ters miş.
Orjinalini calıstırdım ve baktım.
Durması gereken durum  resimdeki gibi ( Orjinali )



ete

Bu display bozuk olmasın.?
Zira 2 display çalışıyor 2 tane si çalışmıyor. Ama daha da enteresanı çalışmayanların bütün segmentleri yanıyor.
Bunun tek bir sebebi olabilir. Çalışmayan displaylerin bağlı olduğu 595 lerin çıkışlarını kontrol et hepsi HIGH mıdır?
Aynı 595 lerin kilit ucu ile MR ve OE uçları arasında bir kısa devre varmıdır onuda kontrol et. Özellikle MR ucu ile kilit ucu arasında kısa devre var ise bütün çıkışlar HIGH olmaktadır.

Başkada söylenecek laf yok sanırım. Elindeki diğer displayide deneyebilirsen iyi olur tabiiki.

Ters olma meselesine gelince verilen bağlantıların ters olduğunu düşünmekteyim.
Denemek için ekrana verilecek rakamı 1356 şeklinde değiştir bakalım. Şayet 5 ve 6 rakamını ters olarak yine görüyor isen sorun bağlantıların ters çizilmiş olmasındadır.

Ete

ete

Ortada komik bir durum var. Bana kalırsa sen uçları tespit ederken displayi ters tutmuşsun.
Hal böyle olunca ilk verdiğin şemada 4 nolu display i süren 595 çıkışlarını şöyle vermişsin.
%3d-4g-4c-4b-4a-4f-4e-4d  bu şekilde bağlayınca 7 rakamı ters çıkıyor. Peki 7 rakamını düz görmek için nasıl bağlantı gerek diye bakınca şunu buldum %3d-4g-4f-4e-4d-4c-4b-4a buda neyi gösteriyor. Aslında çıkan uçların öyle abuk subuk olmadığını göstermektedir.

Bu durumda 4 Nolu display için 595 çıkışı sıralı bir şekilde 3a-4g-4f-4e-4d-4c-4b-4a şeklinde çıkmaktadır.
Şimdi de 3 nolu displaye bakalım. O da  %2b-2a-3g-3f-3e-3d-3c-3b.
2 nolu display için  %1c-1b-1a-2g-2f-2e-2d-2c şeklinde
1 nolu display için ise %n4-n3-n2-n1-1g-1f-1e-1d
şeklinde çıkmaktadır. Böylece bağlantıda belirli bir mantık olduğu görülmektedir. İşin sırrı şimdi ortaya çıktı bence.
Adamlar mantıklı bağlamışlar gözüküyor.

Sen bağlantılarını iyice kontrol et bence. Programda ona göre yeniden düzenlensin.

Ete

M_B

Ete Hocam haklısınız.
Displayı ters tutarak semayı tabloyu cıkarmısım.  Şu an simulasyon dosyasını da düzenledim.
Birazdan da Displayı calısan da deneyecem. Son durumu nedir diye.



ete

Programın son düzenlemeye göre değiştirilmiş hali ilişktedir.
Umarım çalışır.
Ete

M_B

Ete hocam sonunda yaptım
yalnız sizi cok ugrastırdım Hakkınızı helal edin.
Olayın yanlıslıgı ilk basta tersten sema cizmem ve tablo cıkarmam mış.
Calısan ekran goruntusu ve yeni tablo aşagıda.
Şimdi verileri hazırlama kısmı kaldı.


M_B

Sonunda Ekranı tam manasıyla kullanabildim.
İlgili kod


#include <pic.h>

#define _XTAL_FREQ 4000000

#define DATA RB2   // Pin 8   Beyaz
#define CLK  RB1   // Pin 7   Sari
#define ENB  RB3   // Pin 9   Yesil




// sigorta ayarları yapılıyor.
__CONFIG(FOSC_INTOSCIO&MCLRE_OFF&WDTE_OFF&LVP_OFF&PWRTE_ON&BOREN_ON);

volatile unsigned char sayac = 0;

// Ortak Anot display için veri değerleri
char Digit[10]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6};
//              [0   ,1,  2 ,   3 ,  4 ,  5 ,  6 , 7,   8 ,   9 ,o ,c ,- ,r ]
unsigned char temp;



typedef  union
              {
              int all;
              struct {
                      unsigned  d0  :1;
                      unsigned  d1  :1;
                      unsigned  d2  :1;
                      unsigned  d3  :1;
                      unsigned  d4  :1;
                      unsigned  d5  :1;
                      unsigned  d6  :1;
                      unsigned  d7  :1;                     
                      };
             }bittype;
   
bittype  Data1,Data2,Data3,Data4;


// *****************************************************

void gonder(char veri)
{
  int i;
    for(i = 0; i<8; i++)
        { 
    if((veri & 0x80 ) == 0x80 )
      DATA =1;
    else
      DATA =0;
    veri<<=1;
    CLK =0;
          __delay_ms(10);
    CLK =1;
  }




void ekrana_yaz(void)
{

          Data1.all = sayac % 10 ;
          Data2.all = (sayac/10)%10;
          Data3.all = (sayac/100 );
          Data4.all = 0;

  Data4.all=Digit[Data4.all];
  Data3.all=Digit[Data3.all];
  Data2.all=Digit[Data2.all];
  Data1.all=Digit[Data1.all];

  Data4.d0=Data3.d7;   // Data4 hazır

    temp=Data3.all; 
temp=temp<<1;
Data3.all=temp;

Data3.d0=Data2.d6;
Data3.d1=Data2.d7;  // Data3 hazır

temp=Data2.all; 
temp=temp<<2;
Data2.all=temp;

Data2.d2=Data1.d7;
Data2.d1=Data1.d6;
Data2.d0=Data1.d5;


temp=Data1.all; 
temp=temp<<3;
Data1.all=temp;

ENB = 0;
gonder(Data4.all);
gonder(Data3.all);
gonder(Data2.all);
gonder(Data1.all);
ENB = 1;                   
}

 
// *********************************************************
// ana program
main(void)
{
    TRISA = 0b00000000;
    TRISB = 0b00000000;

    PORTA = 0b00000000;
    PORTB = 0b00000000;

    OPTION_REG = 0b00000001; // PullUp dirençleri devreye sokar.

    CMCON = 0x07; // PORTA analog pinlerini kapatır. PortA Dijitale dönüştür.



    while(1)
            { // program döngüsü
            sayac++; // Sayacı bir artır.
         
__delay_ms(20);
ekrana_yaz();
__delay_ms(20);

            }       
}


Powered by EzPortal