gömülü sistemler etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
gömülü sistemler etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Gömülü Sistemler Ölçme Teknikleri

    Mikrodenetleyiciler ile Ne Ölçülebilir?

    Arduino ile ya da diğer gömülü sistemler ailesinden herhangi bir mikrodenetleyici ile herhangi bir şeyi ölçebilmek, ölçmek istediğimiz şeyin ancak elektriksel bir değere çevrilebilmesiyle mümkün olabilmektedir. Tam nokta atışı konuşmak gerekirse voltaja çevirebildiğimiz herşeyi ölçebiliyoruz. Mikrodenetleyiciler kendisine verilen referans sayesinde ölçülmek istenen potansiyel farkı karşılaştırarak bir değer üretebilirler. Malesef ölçme anlamında yetenekleri ancak bu kadardır. Bir de zamanı bilirler, onu da üzerlerinde bulunan clock kaynağı sayesinde yaparlar. Bu da beraberinde sayma yeteneği kazandırır mikrodenetleyiciye. Netice olarak bir mikrodenetleyici sadece voltaj ölçebilir.

    Sensör Nedir, Ne İşe Yarar?

Net olarak bir mikrodenetleyicinin algılayabildiği (sense) tek şey potansiyel farktır. Sense demişken sensör kavramının da çıkış noktası ortaya çıkmış oluyor. Ölçmek istediğimiz büyüklüğü, mikrodenetleyicinin ölçebildiği potansiyel farka çeviren cihazlara sensör diyoruz. Bazıları sadece bir direnç olmak kadar basit olabilirken bazıları çok karmaşık-bütünleşik yapılar olarak karşımıza çıkabilmekte. 

    Bazen analog bir ölçme ile bazen dijital bir ölçme ya da sayma yöntemiyle bu ölçümler yapılabilir. Analog bir ölçüm yapılması gerekiyorsa bunun için mikrodenetleyicinin ADC : Analog to Digital Converter birimi kullanılır. O sebeple kullanacağınız mikrodenetleyicinin ADC birimini detaylıca öğrenmeniz gerekir. Sonuçta elde edilen veri, voltaj seviyesini belirten sayısal bir değer olur. Bu noktadan sonra iş matematiğe kalır, sensör ölçmek istediğiniz büyüklüğü nasıl bir algoritmayla potansiyel farka çevirmişse yaklaşık olarak tam tersi bir yol izleyerek ölmek istediğimiz büyüklüğün değerine ulaşırız.

    Ölçmede Hata Payları    

Ölçme denilince yalnız başına da gelmez, yanında bir de hata payı diye bir olayı getirir ve o da yalnız gelmez, genellikle kalabalık olur. Sensörün hata payı vardır, ADC 'nin hata payı vardır, kullandığınız algoritmanın bir hata payı vardır, vardır da vardır. Gürültü dediğimiz bambaşka bir olayımız da vardır onu da es geçemeyiz, bu noktada da imdadımıza filtreler yetişir, amaç genel olarak hata paylarını en aza düşürerek daha gerçekçi sonuçlara ulaşmaktır.

    Bu yazı serisiyle, vakit buldukça tüm ölçme tekniklerini paylaşıyor olacağım. Her biri için ayrı bir sayfa yazarak tüm sayfa linklerini bu yazının altında paylaşacağım. Sizlerin de ilgisini çeken incelememi istediğiniz sensörler olursa, yorumlara yazarak talebinizi iletebilirsiniz.

C++ Dersleri | Dinamik Diziler

 C++ dizileri anlatırken -> C++ Diziler konusunda, dizilerin boyutlarının önceden belirtilmesi gerektiğinden bahsetmiştik, bunun nedeni olarak da programın çalışmadan evvel o dizi için ne kadar yer ayırmalı bilmesi gerektiğini söylemiştik, hatta iki boyutlu dizileri yazdığım yazıda dizi boyutlarını sabitler içerisine atarak tanımlama yapmıştık. Hadi deneysel düz bir kafada ilerleyelim ve bunu değişkenlerle yapmayı deneyelim : 

int n = 3;
int arr[n];

Bunu yaptığımız anda Visual Studio daha kodu bile derlemeden tanımlamayı yaptığımız ikinci satırda n 'in altını çizdi ve Error List 'e şu hatayı yazdırdı :

Error (active) E0028 expression must have a constant value

Şair burada; ifade sabit bir değer olmalı demek istiyor. Birisinin çıkıp sevgili şairimize her zaman bir dizinin eleman sayısının sabit olamayacağını bazen parametrik olarak kullanılabilmesi için bize imkan tanıması gerektiğini anlatması gerekecek. Ya da başka bir şekilde yapılmış bir hesaplama sonucu ortaya çıkıyor/belirlenebiliyor da olabilir, örnekler çoğaltılabilir, özetle sabit değil değişken bir eleman sayısı durumu elde etmek istiyoruz.

    Bu noktada ihtiyaç duyduğumuz şeyin adı Dynamic Arrays. Programlamada dinamik ne demek? Dinamik kelimesi literatürde, runtime yani programın çalıştığı süreçte oluşturulan anlamına gelir. Bu ne demek, biz bu kodu yazdığımızda bu değerin ne olduğunu bilmiyoruz, bilemiyoruz, yahut kullanıcının belirlemesini istiyoruz vesaire gibi sebeplerle, ben sana bu bilgiyi ancak sen çalışırken verebileceğim manasında, değişik alanlarda kullanabileceğimiz güzide bir kelime olur kendisi.

    Aslında konu bu noktada dizilerden çıkar, göstericiler olarak türkçeye çevirdiğimiz pointers konusundayızdır artık, işin aslı evvelce de söylediğimiz gibi; dizi dediğimiz şey arkaplanda bir göstericidir. Burada da göstericilerin bir kullanımını görmüş olacağız, uzatmıyalım nasıl yapıyoruz :

int n = 3;
int *arr = new int[n];

dediğimizde şair bizi üzecek herhangi bir hata vermiyor. Kullandığımız asteriks * işareti bu arkadaşın bir pointer olduğunu bildirmek için kullanılıyor. Artık üst satırlarda diziyi başlattığımız ana kadar ister bir hesaplamayla ya da kullanıcı girişiyle almış olalım, n değişkenini dizinin eleman sayısı olarak kullanabildik. Kullandığımız new keyword  başka bir yazının temel konusu olabilecek nitelikte bir arkadaş ama kısaca int türünde yeni bir nesne oluştur diyebiliriz.

Peki dizi elemanlarına nasıl değer atayacağız?

arr[0] = 3;

şeklinde atayabiliyoruz, dizi elamanlarına ulaşırken de değişen bir durum yok, değişkenadı[index].

Unutmamız gereken bir diğer nokta ise, bu diziyi new keyword ile oluşturduğumuz için, işimiz bittiğinde delete keyword ile silmemiz gerektiği, her new keyword ile oluşturulan nesne hafızada boyutu kadar yer kaplar, delete ile silinmezse de kaplamaya devam eder, hafıza organizasyonu konusunda önemli bir noktadır:

delete[] arr;

Dinamik arrayların kullanılmasındaki bir diğer handikap ise yine malesef new delete meselesinden kaynaklı, nesne new edilip delete edilemeden kod herhangi bir şekilde bir exception a düşer de nesneyi delete edemezse, ve bu kod parçacığı bir döngünün içindeyse yahut çok fazla yerde kullanılıp çağırılıyorsa, hafıza fonksiyon her çağırıldığında aynı miktarda artmaya devam eder, bu ram in tamamen dolmasına ve programın çakılıp kalmasına kadar gidebilir. Yaw bu program burda neden çakılıyor hata da yook diye kafayı yedirten bir meseleye sebebiyet verebilir, dikkat! :)

örnek olarak şu kod için :

void func_to_show_mem_leak()
{
	int* ptr = new int(5);
	return;
}
int main()
{
	while (true)
		func_to_show_mem_leak();
}

9 saniye gibi bir sürede 4gb RAM kullanımına sebebiyet verdiğini görebiliyoruz :

c++ memory leak

Haydi bir de ekrana yazdıralım dersek, şu yolu izleyebiliriz :

for (int i = 0; i < n; ++i) { cout << arr[i] << ' '; }



Önceki Konu : C++ ile çok boyutlu diziler ve kullanımı

Sonraki Konu :  C++ std::vector ile dinamik diziler


C++ Dersleri | C++ 2 Boyutlu Diziler

     C++ ile iki boyutlu eleman sayısı önceden belirli 'sabit' diziler de oluşturmak mümkündür, yapı tek boyutlu dizi tanımlamasıyla mantıksal olarak benzer yapıda. Neyin ne olduğunu anlamak için dizi elaman sayılarını sabitlere atayarak şöyle tanımlamış olalım :

int const n_satir = 3;
int const n_sutun = 7;
int const m[n_satir][n_sutun] = 
{
    { 1, 2, 3, 4, 5, 6, 7 },
    { 8, 9, 10, 11, 12, 13, 14 },
    { 15, 16, 17, 18, 19, 20, 21 }
};

    Sabit kelimesine dikkat edelim, bu değer sabit olmak zorunda. Hazıfazada ne kadar yer ayıracağını bilmek istiyor sevgili derleyicimiz. 3 satırlı, 7 sütunlu ve 2 boyutlu dizi tanımlamış ve değerlerini yukarıdaki şekilde belirlemiş olduk, bu yapıyı matematikteki matriks yapısına benzetebiliriz. Yapı karmaşık görünse de aslında çok basit bit mantığa dayanır, int tipinde bir dizinin dizisidir demek tam anlamını karşılayabilir. Örnek olsun diye değeri 10 olan elemana ulaşmak istediğimizde m[1][2] yazabiliriz. Nerden geldik -> sıfırıncı satırda 10 yok, birinci satırda var, birinci satırın sıfırıncı elemanında ve birinci elemanında yok ikinci elemanında var.


For döngüsü ile 1 'den 20 'ye kadar bunları yazdıralım dersek kullanmamız gereken kod :

for (int y = 0; y < n_rows; ++y)
{
    for (int x = 0; x < n_cols; ++x)
    {
	cout << setw(4) << m[y][x];
    }
    cout << '\n';
}

Çıktımız :   

   1   2   3   4   5   6   7

   8   9  10  11  12  13  14

  15  16  17  18  19  20  21

    İç içe for kullanırken dikat edeceğimiz şeylerden biri, hangisinin daha hızlı döndüğüdür. Hızlı dönmekten kastımız nedir? y 'yi itarete eden for 1 artar, bu bir defa y artışı içerisinde x tam bir döngü tamamlar, yani x iterasyonu daha hızlıdır. Bu bize dizide neyi hızlı döndüreceğimizi belirlemekte faydalı olur, Şunu demeye çalışıyorum: önce satır seç, sonra sutün seç demiş oluyoruz, bu durumda sutün elemanları daha hızlı dönmüş oluyor. Bu sebeple m[x][y] yerine m[y][x] yazıyoruz.

    Kod içerisindeki setw fonksiyonuna takılmayın, çıktı için girilen her elemanın ne kadar karakter alanında yazdırılabileceğini ayarlayan özel bir fonksiyon, aksi halde hepsini bitişik yazardı, yine de merak edenler için söylemiş olalım kullanmak için :

#include <iomanip>

kütüphanesini koda dahil etmeniz yeterlidir. Bir de söylemek de fayda gördüğüm başka nokta m[x,y] gibi birşey yazmıyoruz :) m[x][y], söz dizimi önemli!

Önceki konu : C++ Diziler

Sonraki konu : C++ Dinamik Diziler tanımlanması ve kullanılması

C++ Dersleri | Diziler - Dizilerin Başlatılması ( Array Initialization )

    C++ 'da bir dizi, yalnızca belirli bir değişken türü için sıralı şekilde bellekte yer almasını sağlayan veri bloğudur. C++ 'da bir değişkeni tanımlarken geçerli olan tüm kurallar geçerlidir. Ek olarak bir diziden bahsettiğimiz için, bu veri tipinden bellekte kaç adet saklayacağımızı belirtmemiz gerekir. Bunun için değişken ismine köşeli parantez [] içerisine adedi yazarız.
    Aşağıda int değişken tipi için adı arrInts olan ve 3 elemana sahip olduğu söylenen bir tanımlama görüyoruz :
int arrInts[3];
    Bir dizi tanımlanırken eleman değerleri de verilebilir, buna literatürde initialization deniyor, başlatma olarak çevrilmiş, bunun sebebi bir değişkeni sadece tanımlarsanız sadece tanımlamış olursunuz, değerini vermezseniz başlatmış olmazsınız :) ya compiler kafasına göre bir değer verir ya da vermez sadece adresi ve sığasını biliyor olur ve o anda bellekte o adreste ne veri varsa onun veri tipindeki karşılığını görüyor olursunuz, kararsız bir yapıdan bahsediyoruz yani. Tanımlamayı yaparken verileri gireceksek eşittir deyip süslü parantez içerisine elemanların arasına virgül koyarak yapabiliyoruz :

int arrInts[3] = { 1,256,14153 };

Eğer verileri bu şekilde giriyorsak dizi boyutunu belirtmek zorunlu değil, derleyicimiz 3 değer girildiğine göre boyutu da 3 olmalıdır inisiyatifini kullanabiliyor :

int arrInts[] = { 1,256,14153 };


Boyut belirttim ancak eksik veriler girdim :

int arrInts[5] = { 1,256,14153 };
boyutum beş olur, ilk üç elemanım bellidir diğer ikisi muallak, sıfır diyelim mi.
    Dizilerin içindeki elemana erişmek için index değerini kullanırız: bu değer için pozitif tam sayılardır diyebiliriz, 0 dan başlar birer birer artar. Beş elemanlı bir dizinin ilk elemanı sıfırıncı elemandır, son elemanı dördüncü elemandır. Yukarıdaki dizinin sıfır bir ve ikinci elemanlarına değer verilmiş, üçüncü elemanına değer verilmemiştir. Şu şekilde tekil olarak verebiliyoruz :

arrInts[3] = 15;

Dizideki herhangi bir elemana erişmek için değişken adının yanına erişmek istediğimiz elemanın index numarasını bir köşeli paranteze yazmak yeterlidir, Tüm elemanlarını ekrana yazdıralım dersek for ile şunu yazmak yeterli olacaktır :

for (int i = 0; i < 5; i++)
	cout << arrInts[i] << endl;

1
256
14153
15
0

Önceki Konu : C++ Diziler
Sonraki Konu : C++ 2 Boyutlu Diziler

C++ Dersleri | C++ Diziler [ Array ]

    C++ 'da diziler, aynı veri tipine sahip adetli verilerin tek bir değişken ismiyle erişilebilir hale gelmesine olanak tanır. Ne diyebiliriz; ADC 'den veri okuyoruz, saniyede 100 örnek alacağız, her biri için adcVal1, adcVal2 .. adcVal100 diye yüz adet değişken tanımlayıp her birine verimizi kaydedebiliriz, çok pratik olmayacak gibi geldi bana ve de örnekleme sayımız parametrik ise bu yolu kullanmak zaten imkansız oluyor. Bu noktada dizilerden faydalanıyoruz. AdcVals diye bir dizi oluşturup, boyutunu belirtip hafızada bizim için o veri tipinin yüz adedinin sığabileceği bir bellek alanı ayırmasını söylüyoruz, verilerimizi onun içinde saklayıp yine oradan erişebiliyoruz.

  C++ da bir diziyi her değişkende olduğu gibi önce tanımlamak "declare" sonrasında da dilersek başlatmak "initialize" gerekiyor. Sabit değerli diziler için dizi boyutunu da belirtmek gerekiyor ki hafıza organizasyonu işlevi düzgün görevini yerine getirebilsin. Sabit değerli diye bahsettiğimize göre boyutu sonradan belirlenebilen dinamik dizilerin kullanımı da mümkün. Dizilerin ve göstericilerin "pointer" bir araya geldiği aslında her göstericinin aynı zamanda bir dizi olabildiği falan gibi konuları da yazıyor olacağız.


Önceki Konu : Bit Alanları - Gömülü Sistemler Bellek Organizasyonu

Sonraki Konu : C++ Dizilerin Tanımlanması ve Kullanılması

C++ Dersleri | Bit Alanları - Gömülü Sistemler Bellek Organizasyonu

    Gömülü sistemlerde hepimizin bildiği ya da şuanda öğreneceği üzere hafıza alanlarımız (flash - eprom - ram) oldukça kısıtlıdır. Atmega 328p için 2kb ram alanı var desek ve bunun da ancak 2048 tane harfi ram de barındırabileceği anlamına geldiğini söylesek, belki de şu okumakta olduğunuz metini bile ram de saklayamıyor olacağımızı kolayca tahmin edebiliriz. Bazı durumlarda herhangi bir parametrenin sadece açık ya da kapalı olduğunu tutmak istediğimiz bir değişkene ihtiyacımız olur. Ancak en küçük hafıza birimimiz 8 bit (1byte) olduğundan, 1 byte harcamadan 1 bitlik veriyi bir değişken içerisinde saklayabilmek mümkün değildir. Ancak bu bir byte 'ın geri kalan 7 bitini farklı değişkenler için kullanmamıza olanak tanıyan bit fields dediğimiz bir yapı vardır. Tanımlarken hangi değişken için kaç bitlik alan ayırmak istediğimizi belirtmemiz yeterli, bit ayırma işlemini compiler halleder.

    

C++ bit fields

    Bir projede parametreleri kaydetmek isteyelim, hatta daha net olarak örneklendirelim, bir televizyon için olsun bu. Parametrelerimiz limitleriyle birlikte şöyle olsun :

  • Mevcut kanal : 1-16 (toplam 16 kanal) 4 bit
  • Ses seviyesi  : 0-15 (toplam 16 seviye) 4 bit
  • Otomatik parlaklık : true / false (toplam 2 durum) 1 bit
  • Dil seçeneği 1-8 (enum 8 dil) 3 bit
  • Kaynak 1-4 (enum AV-SCART-TV) 2 bit
parametreler çoğaltılabilir.


Kodumuz şöyle olacak

enum languages
{
    Turkish,
    English,
    French,
    Dutch,
    Spanish,
    Arabic,
    Farsi
};
enum videoSources
{
    Vga,
    Tv,
    Scart
};
struct params
{
    // 2 byte yer kaplaması beklenir
    // 4 bit: kanal verisi 0-15 arasında
    // 4 bit: ses seviyesi verisi 0-15 arasında
    // 1 bit: Otomaik parlaklık açık / kapalı
    // 3 bit: Dil seçimi enum maksimum 8 seçenek 
    // 2 bit: Video kaynağı seçimi
    // 2 bit: boş
    unsigned char channel :4, volume :4, autoBrightness :1, language :3, source :2, :2;
};
 
int main()
{
    params TvParams;
    TvParams.channel = 11;
    TvParams.volume = 5;
    TvParams.autoBrightness = false;
    TvParams.language = Turkish;
    TvParams.source = Vga;
    cout << sizeof(TvParams);
}

Her bir türü için örnek vermeye çalıştım, sonraki parametreye dikkat ederseniz isim vermedik, kullanmıyoruz ama sen bunun 2 bit olduğunu bil ve bize toplamda 16 bit 2 bytelık bellek ayır demiş olduk.
    Uygulama bize 2 çıktısını verdi, beklediğimiz gibi. Ancak sizeof kullanırken şunu yapamıyoruz :

sizeof(TvParams.autoBrightness);

    Herkese kolay gelsin

Önceki konu : Bit kopyalama
Sonraki konu: C++ Diziler

C++ Dersleri | Bit işlemleri, Bit Clear ve Bit Set

 C++ dersleri bit işlemlerinde belki de en çok kullandığımız bit işlemlerinden biri bit set diğeri de bit clear dir desek yanılmış olayız herhalde, bitwise OR konusunda örneğini vermiştik burda da kullanalım:

int indexOfBitToSet = 5;
PORTB |= 1LL << indexOfBitToSet;

5. indexteki bit 'i set eder. portB 'nin 5 numaralı pini Set edilmiş (HIGH) olur. Burada diğer pin konfigürasyonları bu durumdan etkilenmezler.

PORTB 'nin 0000 0000b olduğunu düşünelim,

1 << 5 bize 0010 0000b değerini verir, bu değerle 0000 0000b değeri orlanırsa, gayet basitçe 5. indexin 1 olduğunu görebiliyoruz.

Aynı şekilde bir bit dizesindeki belirli bir biti CLEAR (0) yapmak için bitwise and kullanıyoruz:

  int indexOfBitToClear = 5;
  PORTB &= ~(1LL << indexOfBitToClear);

şimdide PORTB 'nin tümünün HIGH olduğunu varsayalım, 1111 1111b, 1 << 5 'den 0010 0000b değeri gelir, ifadenin başında yer alan ~ işaretiyle bit dizisindeki tüm değerler inverse oldu, yani tüm 1 ler 0, tm sıfırlar 1 oldu -> 1101 1111, son olarak da PORTB nin değeri olan 1111 1111 ü 1101 1111 ile and işlemine tabi tuttuğumuz vakit, diğer hiçbir bit eklilenmeden sadece 5. intexteki bitin Clear olduğunu görebiliyoruz.

Herkese kolay gelsin!

Önceki konu : Set Bitleri sayma

Sonraki konu : Bit Kopyalama

C++ Dersleri | Bit İşlemleri - Set Bitleri sayma

 C++ bit işlemlerinde bir bit dizesi içerisindeki SET (1) olmuş bitlerin sayısını elde etmek için bir kaç yol izleyebiliriz, basitçe programlama kafasıyla for kullanarak yapılabilir :

int main()
{
	unsigned int a = 1234;     // 0100 1101 0010
	int bitCount = 0;
	for (bitCount = 0; a; a >>= 1)
		bitCount += a & 1LL;
	
	cout << "result=" << bitCount << endl;
}

 result=5 

ne yapmış olduk açıklamaya çalışamadan önce for ne yapıyor onu anlatalım : for 'un ilk ifadesi bir kez çalıştırılır, ikinci ifadesi kontrol edilecek durumu belirler; burada yalnızca a var, bu ne anlama geliyor, bu ifade boolean bir ifade olmalıdır, 0 olmamışsa durumun sağlandığını kabul eder yani 3 5 7 vs diğer tüm sayılar true kabul edilir, yani for 'un bitme şartı a nın sıfır olması durumudur, en son ifadesi de her dönüşte yürütülecek kod ifadesidir, for'u yazmadan for'u da anlatmış olduk kısaca, yazarız ilerde detaylı bir şekilde.

  • bitCount = 0    a = 1234 : 0100 1101 0010b    a & 1LL -> 0100 1101 0010 & 1 den +0 oldu
  • a >>= 1 -> 0010 0110 1001   a & 1LL den bu sefer 1 geldi bitCount +1 oldu,
yaani her defasında a bir bit sağa kaydırılarak değeri düştü en sondaki biti 1 ise bitCount 1 arttı sıfırsa değişmedi, adımlar tamamlandığında a sıfır oldu ve for çalışmayı durdurdu, bu arada bitCount 5 değerine ulaşmış oldu, dileyenler for 'un içerisinde bitCount 'a değer verdiğimiz satıra bir breakpoint atarak adım adım değerleri izleyebilirler.


Daha basitçe yine for kullanarak; en sağda set edilmiş biti kaldır formuna dayanan şu algoritma da kullanılabilir :

int main()
{
	unsigned int a = 1234;     // 0100 1101 0010
	int bitCount = 0;
	for (; a; ++bitCount)
		a &= (a - 1);
	
	cout << "result=" << bitCount << endl;
}

 result=5 

Burada for için başlangıç koşulu verilmemiş, yine a sıfır değilse devam ediyor, preincrement kullanılmış, bu da önce değer ver sonra aksiyona geç demekti, for içerisinde de en sağdaki biti resetle demiş olduk, bu sayede kaç resetlenecek bit varsa o kadar bitCount++ olmuş olacak.

Son olarak Hamming weight (üzerine tıklayarak detaylarına ulaşabilirsiniz) algoritmasıyla geliştirilen bir fonksiyonla şu şekilde de yapılabiliyor, armut piş durumu :)

unsigned popcount(std::uint64_t x)
{
	const std::uint64_t m1 = 0x5555555555555555; // binary: 0101...
	const std::uint64_t m2 = 0x3333333333333333; // binary: 00110011..
	const std::uint64_t m4 = 0x0f0f0f0f0f0f0f0f; // binary: 0000111100001111
	const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
	x -= (x >> 1) & m1; // put count of each 2 bits into those 2 bits
	x = (x & m2) + ((x >> 2) & m2); // put count of each 4 bits into those 4 bits
	x = (x + (x >> 4)) & m4; // put count of each 8 bits into those 8 bits
	return (x * h01) >> 56; // left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
}
 
int main()
{
	unsigned int a = 1235;     // 0100 1101 0010
	int bitCount = popcount(a);
	
	cout << "result=" << bitCount << endl;
}


Herkese kolay gelsin!

Önceki konu : Bit Kontrol

Sonraki konu  : Bir Tamsayının 2'nin Kuvveti Olup Olmadığının Kontrol Edilmesi

C++ Dersleri | Bit işlemleri - Bit Kontrol

 C++ bit işlemlerinde bir bit dizesindeki belirli bir bitin durumunu kontrol etmek için değeri elde etmek istediğimiz bitin indeks değeri kadar right shift yapıp üzerinde and işlemi uygulayarak yapılabilir. Cümle şeklinde ifade edince bana bile anlaşılabilir gelmedi :) kodla bakalım :

int main()
{
	int a = 170;     // 10101010
	int result = (a >> 5) & 1LL;
	cout << "result=" << result << endl;  
}

 result = 5 

5. numaralı indexte yer alan bitin değerini sorguluyoruz, bu indexle kastettiğim sayma sayılarıyla değil, en sağdaki bit için 0 'dan başlayarak sayıyoruz anlamını ifade ediyor. Adım Adım şöyle gidiyor işlem :

a = 10101010 değerini   a >> 5 : 00000101 : yaptığımız zaman zaten istediğimiz bit en sağda yerini almış oluyor, bu değeri de 1 ile & işlemine tabi tutunca 1 ise 1, 0 ise döndürüyor result değişkenine. LL kullanmamızın sebebi Long Long deyip, değişkenin boyutundan bağımsız tüm veri tipleri için yapılacak işlemi garanti altına almaktır.

Şayet bitin değerine yerinde ihtiyacımız varsa; yani diğer tüm bitler 0 olacak, istediğimiz bitin değeri neyse yerinde o değer olacak, 5 için 00X00000 şeklinde

int main()
{
	int a = 170;     // 10101010
	int bitValueinPlace = a & (1LL << 5);
	cout << "result=" << bitValueinPlace << endl;
}

 result = 32 

5. biti 0 olan 218 gibi bir sayı kullansaydık; result=0 çıktısını elde etmiş olacaktık.

Kafanıza takılan herhangi birşey olursa lütfen yorumlarda sormaktan çekinmeyiniz.

Önceki konu : Bit toggle

Sonraki konu : Set Bitleri Sayma

C++ Dersleri | Bit İşlemleri - Bit Toggle

 C++ Dersleri | Bit İşlemleri - Bit Toggle; kısaca açıklamak gerekirse bir bit dizesinin istenen bitini toggle etmek, mevcut değerini ters çevirmek anlamına gelir, yani 0 ise 1, 1 ise 0 a çevirir.

int main()
{
	int a = 255;     // 11111111
	a ^= 1LL << 7;	  // 01111111	127
	cout << "a=" << a << endl;  
}

a değişkeninin 7 bitini toggle yap demiş olduk, işlemi adım adım yazmamız gerekirse

a 255 değerindeyken 8 bit, hepsi 1 şeklinde değer buluyor ikili sistemde -> 11111111 bu değeri (1 << 7) ile -> 10000000 xor işlemine tabii tutarsak 01111111 elde etmiş oluyoruz.

Önceki konu : Tüm Bitleri Set Etme

Sonraki konu : Bit Kontrol

C++ Dersleri | Bit İşlemleri - Tüm Bitleri Set Etme

 C++ ve gömülü sistemlerde bir değişkene ya da yazmaca ait tüm bitlerin set edilmesi çokça kolay bir mantığa dayanır. Eğer değişkenin ya da yazmacın boyutunu biliyorsak o kadar bit sayısına eşit olan en büyük sayıya eşitleyerek işin içinden sıyrılabiliriz: 8 bitlik bir yazmaç için 0xFF 'e eşitlemek bir çözüm olmakla beraber eğer bilmiyorsak bir fonksiyon içerisine template ile geliyorsa mesela daha basit bir yolu da söz konusu: değeri -1 e eşitlemek. 

uint8_t a = 0xFF;

    Yazının birinde bahsetmiştik, işaretli sayıların MSB biti (en solda) işaret biti olup 0 ise sayının pozitif 1 ise negatif olduğu anlamına geliyordu ve negatif tarafta anlamlı bitler 1 'ler değil 0'lardı. Ne demeye çalışıyorum ? 8 bit için konuşursak : -1 sayısı 2 lik sistemde 11111111b olarak ifade edilir, bence tüm bitleri set etmek için güzel yöntem :)

  PORTB = -1;

Tüm bitleri resetlemek istersek? Bilmem söylemeye gerek var mı ama yazmış olalım : a=0; işinizi çözecektir.

Herkese kolay gelsin!

Önceki konu : En Sağdaki Set Edilmiş Biti Resetleme

Sonraki konu : Bit Toggle

C++ Dersleri | Bitwise Operatörleri | Right Shift Operatör

 C++ bitwise operatörlerden right shift operatörünü konu alıyoruz >> . Right shift operatörü,  C++ Dersleri | Bitwise Operatörleri | Left Shift Operatör konusunda bahsettiğimiz tüm özellikleri taşıyor, tek farkla : bit dizisini sağa doğru kaydırıyor. Bir örnekle right shift operatörünün nasıl kullanıldığına bakalım:

int main()
{
	int a = 2;	// 0010b
	int b = a >> 1;	// 0001b
	cout << "a=" << a << ", b=" << b;
}

çıktımız şu şekilde :  a=2, b=1 

Kolayca anlayabileceğimiz şekilde a değişkeni için oluşan binary sistem diziliminde indexlemeye göre 1. bit hanesinde yer alan operatöre gönderdiğimiz sayı :1 adedince sağ tarafa kaydırılmış. Left Shift operatörü için sayıyı 2 'nin kuvvetleriyle çarpmakla aynı şey demiştik, burada olan da sayıyı 2 'nin kuvvetleriyle bölmekle aynı şeydir. a değişkeninin değeri olan 2 'yi 2^1 'e (bu 1 operatöre gönderilen 1) bölerek 1 elde etmiş olduk:

Farklı sayılarla denememiz gerekirse :

int main()
{
	int a = 44;		
	int b = a >> 2;
	cout << "a=" << a << ", b=" << b; // 44/2^2 -> 44/4 -> b=11 çıktısını üretir.
	a = 128;
	b = a >> 5;
	cout << "a=" << a << ", b=" << b; //128/2^5 ->128/32 -> b = 4 çıktısını üretir.
}

Yine, left shift operatöründe olduğu gibi kaydırma operatörüne gönderdiğimiz kaç bit kaydırılacağı değeri, negatif olamaz Önemli bir nokta daha işaretli sayılarla çalışıyorsak şayet, bit kaydırması yapılacak operandın yani a değişkeninin de pozitif olması gerekir, negatif sayılardaki davranışı da işlemi yapacağını garanti etmez ve undefined behavior olarak tanımlanır.

Son olarak bu operatörün operandlar üzerinde değer değiştirmediğini unutmayın diyelim :

int main()
{
	int a = 2;
	a >> 1;
	cout << "a=" << a << endl;  // a=2
	a >>= 1;
	cout << "a=" << a << endl;  // a=1
}

yani a >> 1 yaparak a 'nın değerini değiştiremeyiz, eşittir operatörünü kullanmak durumundayız :)

Herkese kolay gelsin.



Önceki konu:  C++ Left Shift Operatörü

Sonraki Konu: C++ ile Bit Manipülasyonları


Türksat Saat Kanalı ve IRIG-B Time Code

Türksat Saat Kanalından Saat Bilgisi Nasıl Alınır? Uyduda kanalları dolaşırken, şu Türksat Saat kanalı hep dikkatimi çekmiştir. Özellikle  S...