AVR MAX7219 7-Segman Gösterge Modülü Kullanımı

Bu uygulamada Maxim firmasının 7 segman ve dotmatrix göstergeleri için üretmiş olduğu MAX7219 entegresini ve bu entegre kullanılarak yapılmış gösterge modülünü kullanmayı öğreneceğiz.

Öncelikle her zaman olduğu gibi kullanacağımız entegreyi tanımak için üreticinin sağlamış olduğu datasheeti açıyoruz.
https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf

Burada entegrenin özelliklerine geldiğimizde SPI, QSPI ve MICROWIRE destekli 10MHz seri arayüzünün olduğunu görüyoruz. Aynı zamanda parlaklık kontrolü, dekod gibi özelliklerin de yer aldığını görmekteyiz. Uygulama noktasında ise bargraf göstergeler, LED matrix göstergeler ve panelmetrelerde kullanıldığı yazmakta. Elimde dotmatrix için modül de yer alsa da ben burada sadece 7-segman modülü kullanmak üzere kodları yazacağım. İlerleyen uygulamalarda bu modül üzerine kütüphane yazacağız ve farklı uygulamalarda kullanacağız.

Elimizde modül olduğu için ayak haritalarını ve elektriksel karakteristikleri geçiyoruz. Biz sadece program yazma işiyle ilgileneceğiz.

Seri veri formatı kısmında bu modülü nasıl programlayacağımızı öğreniyoruz. Önceki uygulamalarda olduğu gibi önce adres üst bayt olarak yazılmakta sonra ise bu adrese yazılacak veri alt bayt olarak yazılmaktadır. Bunu I2C protokolü değil de SPI protokolü ile yaptığımızı unutmayalım. Burada aygıtın bir adresi olmayıp bunu CS ayağı ile biz kontrol etmekteyiz.

Şimdi yazmaçları açıklamadan önce size bir tecrübemi aktarmak istiyorum. Genellikle bir aygıt için kendi uygulamamı ve kütüphaneyi yazmaya başlamadan önce internetten örnek bir uygulama indirip deneme amaçlı bunu kullanırım. Böylelikle en azından elimdeki donanımın çalışıp çalışmadığımı öğrenmiş olurum. Bu noktada MAX7219 ile yapılmış pek çok uygulamayı bulsam da bunları çalıştırmak istediğimde hiçbirinin bende doğru düzgün çalışmadığını fark ettim. Hatta modülün bozuk olup olmaması noktasında şüpheye düştüm ve bozuk olduğuna kanaat getirdim. Ama kendi uygulamamı yazınca şaşılacak bir biçimde modül sorunsuz çalışmaya başladı. Ne yazık ki gömülü yazılımda başkalarının yazdığı kütüphanelere ve uygulamalara halen güvenemiyoruz. Yazılımın diğer alanlarında böyle bir durum olmasa da gömülü yazılımda böyle bir durum var.

Burada ise modülde yer alan yazmaçların adres haritasını görmekteyiz. Burada her bir rakam için Digit 0, Digit 1, Digit 2… diye yer ayrıldığını görebilirsiniz. Biz veri yazacağımız zaman buraya veri yazmaktayız. Aynı zamanda kod çözümleme özelliği ile örneğin bizim yazdığımız 1 verisi göstergede 1 rakamı şeklinde görünmesi gerekli. Eğer bu özelliği kullanmazsak ya rakam yerine göstergeye uygun kodlanmış değerleri yazacağız ya da karmakarışık bir görüntü ile karşılaşacağız.

Shutdown yazmacı oldukça önem arz etmekte. Normalde bu modüle güç verseniz de modül kapalı halde olmakta. Bunu açmak için D0 bitini 1 yapmanız gerekli.

Burada ise decode işleminin ne derece olduğunu belirliyorsunuz. Eğer dotmatrix gösterge kullanıyorsanız decode yapmanıza gerek yoktur. Ama biz bütün basamakları 7 segman gösterge için kullanacağımız için 0xFF diyip decode işlemini tamamına yapmamız gereklidir.

Decode olmadan hangi bitlerin hangi segmanlara denk geldiği yukarıda gösterilmektedir. Biz bu ham haliyle uğraşmayıp doğrudan 1, 2, 3… diye yazmak istiyoruz.

Burada ise parlaklk yazmacının alabileceği değerleri görmekteyiz. Sağ tarafta yer alan değerleri yazdığımıza emin olmak gerekli. Biz başlangıçta sabit bir parlaklık belirleyeceğiz.

Bu ise göstergede kaç adet rakamı göstereceğimizi belirleyen yazmaçtır. Bütün gerekli yerleri öğrendiğimize göre artık uygulamaya geçebiliriz.

Burada B portunun 2 numaralı ayağı CS olarak kullanılmıştır. Bu da Arduino’da 10 numaralı ayağa karşılık gelmektedir. Bunun dışında bildiğimiz SPI bağlantısı yapmamız yeterlidir.

Burada kendi yazdığım SPI kütüphanesini kullandım. Bunu daha önceki AVR uygulamaları kitabında ayrıntısıyla okuyabilirsiniz. Burada yazdığım makaleleri “C ile AVR Programlama” ve “AVR ile Mikrodenetleyici Uygulamaları” kitaplarını okumadan okumanızın çok verimli olacağını düşünmemekteyim.

spi_init(MASTER);

Öncelikle SPI birimini başlatmaktayız. SPI ayarları şu şekildedir.

#define SPI_DATA_ORDER MSB_FIRST
#define SPI_DEFAULT_MODE SPI_MODE_0
#define SPI_CLOCK_RATE SPI_CLOCKDIV_16
#define SPI_SPEED SPI_DOUBLESPEED

SPI protokolünde belli bir standart olmadığı için kullanırken modülün hangi modda çalıştığını öğrenmeniz gereklidir. Yukarıdaki ayarlar pek çok uygulamada işinizi görecektir.

Ondan sonra ise max_init() fonksiyonunu çalıştırıyoruz. Bu fonksiyonun içine bir bakalım.

void max_init(){
max_send_byte(0x09, 0xFF);
max_send_byte(0x0B, 7);
max_send_byte(0x0A, 0x00); // PARLAKLIK
max_send_byte
(0x0C, 1); // Aç-KAPA
max_clear_display
();
}

Bunu anlamak için önce max_send_byte() fonksiyonunun içine bakmamız gerekiyor.

void max_send_byte(uint8_t addr,uint8_t data)
{
PORTB &=~(1<<PORTB2);
spi_transceive(addr);
spi_transceive(data);
PORTB |= (1<<PORTB2);
}

Bu fonksiyon addr ve data olarak adres ve veri değerini almakta ve önce CS ayağını (PORTB2) sıfıra çekip önce adres ve sonra data verisini yazıp tekrar CS ayağını bire çıkarmaktadır. Eğer CS ayağı önce sıfıra çekilip sonra bire çıkarılmazsa iletişim gerçekleşmeyecektir.

max_send_byte(0x09, 0xFF);

Burada 0x09 adresine 0xFF verisini yazıyoruz. 0x09 adresi yukarıdan göreceğimiz üzere dekod modunu seçmemize yaramaktaydı. 0xFF diyerek tam bir dekod işlemi gerçekleştireceğiz. Böylelikle yazdığımız sayısal değerler 7 segman göstergede doğrudan görüntülenecek.

max_send_byte(0x0B, 7);

Burada ise tarama sınırını ayarlamaktayız. 7 dediğimize göre 0–7 arası toplamda 8 adet karakter kullanacağız.

max_send_byte(0x0A, 0x00);

Bu ise parlaklık yazmacı olup burada parlaklık değerini en düşük seviyeye aldım.

max_send_byte(0x0C, 1);

Burada ise aygıtı kapama modundan açma moduna alıyorum.

max_clear_display();

Burada ise göstergeyi sıfırlıyoruz. Bunun nasıl olduğunu ilgili fonksiyonu inceleyerek görelim.

void max_clear_display()
{
char i = 8;
do {
max_send_byte(i, 0xF);
} while (--i);
}

Öncelikle i değişkenine toplamda kaç karakter kullandığımızı yazıyoruz. Sonrasında ise bu değişkeni birer birer azaltarak her bir karaktere 0x0F verisini yazmaktayız. Her bir karaktere yazılan bu veri her bir göstergeyi sıfırlayacaktır. Bunu ise şu tablodan öğrenmekteyiz.

Görüldüğü gibi “blank” kısmı 0x0F değerine denk gelmekte. İsterseniz boş bırakmak yerine 0 değerini de yazabilirsiniz. Bu döngü Digit 7 yazmacından itibaren Digit 6, Digit 5… diyerek Digit 0'a kadar bu yazma işlemini yapmaktadır. Son olarak max_digit() fonksiyonuna bakalım.

void max_digit(uint8_t digit, uint8_t value)
{
max_send_byte(digit, value);
}

Bu fonksiyon max_send_byte() fonksiyonunun aynısı olup sadece anlaşılır olma adına farklı adlandırılmıştır.

while (1)
{
deger++;
if(deger > 999)
deger = 0;
max_digit(1, deger % 10);
max_digit(2, (deger / 10) % 10);
max_digit(3, deger / 100);
_delay_ms(250);
max_clear_display();
}

Burada daha öncesinde tam sayı tipinde bir değer değişkeni tanımlayıp değerini sıfırladık. Sonrasında ise bu değişkenin değerini 999'a kadar birer birer artırıyoruz. Yani bu uygulamada 1–999 arası bir sayaç yapacağız. Yalnız bu değeri doğrudan göstergeye yazdırmamız mümkün değil. Çünkü her bir yazmaca bir rakam yazdırmamız gerekli. Bunun için elimizdeki tamsayı değerini BCD formatına çeviriyoruz. BCD formatına çevirmek için çeşitli yöntemler olsa da ben yukarıdaki gibi bir çözüm buldum. Şimdi bunu inceleyelim.

max_digit(1, deger % 10);

En sağdaki basamak için değer ne olursa olsun bunun 10'a bölümünden kalanını yazmaktayız.

max_digit(2, (deger / 10) % 10);

Onlar basamağı için değeri 10'a bölüp bunun 10'a bölümünden kalanını bulmamız gereklidir. Örneğin elimizde 860 sayısı varsa bunu 10'a böldüğümüzde 86 buluruz ve bunun 10'a bölümünden kalanı ise 6 olur. Yani onlar basamağındaki rakamı bu şekilde elde etmiş oluruz.

max_digit(3, deger / 100);

Burada ise yüzler basamağındaki rakamı elde etmek için değeri 100' böldük. C’de bölme işlemi kalanı hesaba katmadığı için yuvarlatılmış bir değer elde etmeyiz. Bu yüzden bu kodun sorunsuz çalışacağına emin olabiliriz. Yalnız sadece 3 basamaklı sayılar için bunun geçerli olduğunu biliniz. Sonraki uygulamalarda bunun kapsamını genişleteceğiz.

En son olarak ise max_clear_display() fonksiyonunu çalıştırmaktayız. Böylelikle göstergeyi yeni değeri yazmak için temizlediğimize emin oluyoruz.

--

--