Registerlere Erişim hakkında anlayamadığım en can alıcı nokta ?

Başlatan tekniker_murat, 25 Kasım 2021, 03:20:11

tekniker_murat

Herkese merhabalar. özellikle de @Tagli hocama :D ( yüzssüzlüğüm için özür dilerim ama öğrenmek istiyorum )

Stm32f407vg nin datasheet kısmını inceliyorum örneğin moder registerini ele almak istiyorum.



Burada 0 dan başlayıp 32 ye kadar 32 tane register adresi var. ben bu gpiox moder registerini a portu için düşünüyorum evet A portunda pa0.. pa15 arası 16 tane i/o olarak kullanabileceğim pin mevcut.

Gpioa_moder registerinde de moder0 dan moder15 e kadar 2 bitlik toplamda 32 bitlik register mevcut.

Şimdi misal porta nın 10. bitini ve porta nın 8. bitini giriş yapmak istiyorum geriye kalanını ise çıkış yapmak istiyorum. datasheette ki verilen bilgiye göre genel amaçlı çıkış yapmak için ilgili bite 00 yüklersem o bit giriş olur 01 yüklersem de çıkış olur diyor.

///////////////////////////////////////
00: Input (reset state)
01: General purpose output mode
10: Alternate function mode
11: Analog mode
///////////////////////////////////

SORU 1 :

GPIOA_MODER=0X00000000; Şeklinde 8 basamaklı a portunun moder registerinde 8. ve 10. biti giriş yapmak istediğim zaman GPIOA_MODER=0X00000000; ne şekilde değişmesi gerekir ?

Çünkü toplamda 8 basamaklı bir hex sayı var her bir basamak 4 biti temsil eder ise 8 basamak ile toplamda 32 bit elde edebilirim. en sağda olan en düşük değerli basamak 0 dan F e kadar toplamda 16 farklı değer alabilir Bu durumda ben en değerliksiz olan en sağdaki basamak ile moder0 ve moder 1 e değer yükleyebilirim.

En sağdan 2. basamak ile ise moder2 ve moder 3e değer yükleyebilirim şeklinde en son soldaki basamak ile ise moder 14 ve moder 15 e değer yükleyebilirim BU MANTIK DOĞRU MUDUR ?

SORU 2 : BU YUKARIDAKİ MANTIK İLE GPIOA,GPIOB,GPIOC....GPIOI Gibi diğer registerlerin moderlerine de erişebilir miyim ?

Soru 3 : 

GPIOA_MODER=0X00040000; yaparsam 8. pin giriş diğerleri çıkış olmuş olur mu ?

Bir biti 00 yaparsam giriş 01 yaparsam genel amaçlı çıkış oluyordu. bu durumda sağdan sola doğru 5. basamağı 4 yaparsam moder8 ile moder 9 a ulaşıp moder8e 00 moder9 a 01 yüklemiş olmam gerekiyor bu da binary olarak 0100 a denk geliyor bu da hex de 4 e denk geliyor  bu kanı doğru mu ?

Soru 4 :

GPIOA_MODER=0X55445555; Gpio_moder registerinin 5. ve 6. basamaklarına 4 yüklersem geriye kalan bütün basamaklar 5 olursa yani 0101  gpio 8 ve 10. pinleri giriş geri kalanlarını çıkış yapmış olur muyum ?

Aslında yukarıda anlatmaya çalıştığım şey bu register olayına erişim ve değer atamakla ilgili bir mantığı çözmek için kafamda kurduğum teoriyi anlatmaya çalıştığımdan konu biraz dağıldı ama sadece teorim doğru mu onu merak ediyor ve eğer yanlış ise doğrusunu öğrenmek istiyorum.

[email]murat.yagci.1984@gmail.com[/email]

Tagli

Hex sayılarla düşünmek bu durumda kafa karıştırıcı olabilir. Aslında işin doğrusu bu hesapları hiç yapmamak ve işi derleyiciye bırakmak. Aşağıdaki gibi:

GPIOA->MODER |= (0b01u << (2 * 4))  // PA4 çıkış
             |  (0b00u << (2 * 5))  // PA5 giriş (gereksiz aslında)
             |  (0b01u << (2 * 6)); // PA6 çıkış

Burada GPIO_MODER register'ının başlangıçta 0 yüklü olduğunu varsayıyoruz - ki reset durumu bu. Eğer daha önce yapılan bir ayar değiştirilecekse öncelikle ilgili bölgenin sıfırlanması lazım, yoksa işler karışır.

Register zaten başlangıçta 0 olduğu için yukarıdaki örnekte PA5 ayarı gereksiz. Ancak ben pin ayarlarını yaparken bu gereksiz satırı da yazarım ki yukarıdan aşağı okurken hangi pinlerin kullanımda olduğunu net bir şekilde göreyim.

Bunu bir kütüphane haline getirirken enum kullanmak okunurluğu attıracaktır:

enum PinMode {
    PinMode_Input = 0b00u,
    PinMode_Output = 0b01u,
    PinMode_Alternate = 0b10u,
    PinMode_Analog = 0b11u
};

GPIOA->MODER |= (PinMode_Output << (2 * 4))
             |  (PinMode_Input << (2 * 5))
             |  (PinMode_Output << (2 * 6));

Bu şekilde kullanımlar daha önceki bir mesajımda bahsettiğim Magic Number kullanımını en aza indirerek hata yapma ihtimalini azaltır.
Gökçe Tağlıoğlu

magnetron

HAL library içinde hazır fonksiyonlar var outputları set reset eden

onları kullanın - projede drivers klasörü içinde hal-gpio dosyasına bakın

yeni başlıyorsanız register seviyesinden başlamak yorucu olur

gold3nnn

Alıntı yapılan: Tagli - 25 Kasım 2021, 09:28:26Hex sayılarla düşünmek bu durumda kafa karıştırıcı olabilir. Aslında işin doğrusu bu hesapları hiç yapmamak ve işi derleyiciye bırakmak. Aşağıdaki gibi:

GPIOA->MODER |= (0b01u << (2 * 4))  // PA4 çıkış
             |  (0b00u << (2 * 5))  // PA5 giriş (gereksiz aslında)
             |  (0b01u << (2 * 6)); // PA6 çıkış

Burada GPIO_MODER register'ının başlangıçta 0 yüklü olduğunu varsayıyoruz - ki reset durumu bu. Eğer daha önce yapılan bir ayar değiştirilecekse öncelikle ilgili bölgenin sıfırlanması lazım, yoksa işler karışır.

Register zaten başlangıçta 0 olduğu için yukarıdaki örnekte PA5 ayarı gereksiz. Ancak ben pin ayarlarını yaparken bu gereksiz satırı da yazarım ki yukarıdan aşağı okurken hangi pinlerin kullanımda olduğunu net bir şekilde göreyim.

Bunu bir kütüphane haline getirirken enum kullanmak okunurluğu attıracaktır:

enum PinMode {
    PinMode_Input = 0b00u,
    PinMode_Output = 0b01u,
    PinMode_Alternate = 0b10u,
    PinMode_Analog = 0b11u
};

GPIOA->MODER |= (PinMode_Output << (2 * 4))
             |  (PinMode_Input << (2 * 5))
             |  (PinMode_Output << (2 * 6));

Bu şekilde kullanımlar daha önceki bir mesajımda bahsettiğim Magic Number kullanımını en aza indirerek hata yapma ihtimalini azaltır.


Merhaba; Konu ile alakalı değil ama ufak bir sorum olacak.
PinMode_Input = 0b00u Burada kullanılan "u" harfinin görevi nedir neyi betimliyor acaba ?

Tagli

Sabit değerin unsigned int olduğunu vurguluyor. Aksi halde değer signed int olarak algılanır. İşaretli değerlerde kaydırma işlemi sorun çıkarabilir. Özellikle kaydırmanın ardından sonucun signed int üst sınırını (32 bit ise 2^31 - 1) geçebileceği durumlarda "u" son ekinin kullanılması gerekir. MODER register'ına kaydırma yöntemi ile değer ataması yaparken bu durum ortaya çıkabilir.

Dediğim gibi, her zaman gerekli olmasa da, tatsız sürprizlerle karşılaşmamak için kaydırılacak değerlerde bunu kullanmayı alışkanlık haline getirmekte fayda var.
Gökçe Tağlıoğlu

tekniker_murat

Değerli usta abilerim ve yine çok değerli hocam @Tagli hocam. Ben aslında problemimin büyük çoğunluğu olan kısmını çözdüm. Pic programlarken de sık sık kullandığım ama bazı problemleri olan bir program MikroC programının arm için olan versiyonu var onu kullanmaya karar verdim en azından belirli bir noktaya varasıya kadar mantığı çözesiye kadar bana yardımcı olacak.

Aslında benim Bunca yazıda sormaya çalıştığım şeyi de kafamda oturttum ve daha anlaşılır hale getirdim ama çözdüğüm için böyle oldu sanırım.

Mesela gpioa_moder registerinden yine yola çıkalım, bu register 32 bit ama a portu 16 bit fakat moder registeri hangi porta ait moder ise o portun giriş mi çıkış mı özel amaçlı bir çıkış mı vs olacağını belirtiyor.

16 pinlik A portunda toplamda her pin e 2 bit ile giriş çıkış vs ayarı yaptığımız için toplamda 32 bit olması gerekiyor doğal olarak...

Şimdi benim bir türlü çözemediğim işte tam olarak burası idi..

Mesela ben diyorum ki a portunun 0. pini çıkış olsun 9.pini giriş olsun 14. pini çıkış olsun 15. pini giriş olsun.

İşte bütün mesele bunu moder A ya nasıl yazacağımdı.

Ama https://www.youtube.com/watch?v=xcXlv_bFJw0&list=PLz18cfhgoJEOUU-NB2jHd2yBobvFuQeR_&index=6 videosunda bir örnekte gördüm ve öğrendim.

GPIOA_MODER.MODER150=0;   // ( 2 BİT İLE GİRİŞ ÇIKIŞ AYARI YAPILIYOR )  MODER 15 REGİSTERİNİN  0. BİTİ = 0 DEMEK
GPIOA_MODER.MODER121=0;   // MODER 12 REGİSTERİNİN 1. BİTİ = 0 DEMEK

şeklinde bir yazılışı varmış mikroc dilinde.

Mesela ben diyorum ki a portunun 0. pini çıkış olsun 9.pini giriş olsun 14. pini çıkış olsun 15. pini giriş olsun.

İşte bütün mesele bunu moder A ya nasıl yazacağımdı.

Dolayısı ile benim istediğim şeyi şu şekilde yapabiliyorum.

**************************************A 0 çıkış olsun*************************
GPIOA_MODER.MODER00=1;   // moder a registerinin pin 0 a ait moder 0 ın 0. biti
GPIOA_MODER.MODER01=0;   // moder a registerinin pin 0 a ait moder 0 ın 1. biti
*******************************************************************************

*************************************A 9 giriş olsun**************************
GPIOA_MODER.MODER90=0;   // moder a registerinin pin 9 a ait moder 9 un 0. biti
GPIOA_MODER.MODER91=0;   // moder a registerinin pin 9 a ait moder 9 un 1. biti
*******************************************************************************

*************************************A 14 çıkış olsun**************************
GPIOA_MODER.MODER140=1;   // moder a registerinin pin 14 a ait moder 14 un 0. biti
GPIOA_MODER.MODER141=0;   // moder a registerinin pin 14 a ait moder 14 un 1. biti
*******************************************************************************

*************************************A 15 giriş olsun**************************
GPIOA_MODER.MODER150=0;   // moder a registerinin pin 15 a ait moder 15 un 0. biti
GPIOA_MODER.MODER151=0;   // moder a registerinin pin 15 a ait moder 15 un 1. biti
*******************************************************************************

Şeklinde moder registerinin istediğim registerinin istediğim bitine bu kod şekli ile ulaşabiliyormuşum.

Umarım benim gibi işi anlamamış olan insanlara yol gösterici bir şey olur. ( eğer ben doğru anladıysam :D )

Anlamadığım yerler oldukça sizlerin bilgilerine tekrar başvuracağım inşallah beni yanlız bırakmazsınız sizleri seviyorum.
[email]murat.yagci.1984@gmail.com[/email]