C’de bitler üzerinde işlemler yapabilmek için birçok operatör tanımlanmıştır ancak ben iki özel operatör üzerinde duracağım. Bunlar iki küçüktür “<<” ve iki büyüktür “>>” işaretleri ile gösterilen bit kaydırma operatörleri.
Bunlardan iki küçüktür ile gösterilen “<<” (Sola Kaydır) operatörü solunda verilen sayıyı sağında verilen sayı kadar sola kaydırır. İki büyüktür ile gösterilen işaret “<<” ile gösterilen (Sağa Kaydır) operatörü ise solunda verilen sayıyı sağında verilen sayı kadar sağa kaydırır. Aşağıdaki tabloda konunun daha net anlaşılması açısından birkaç örnek yer almakta.
Hex Formatında Bit Kaydırma | İşlemin Sonucu |
0x01 << 1 | 0x02 |
0x02 << 1 | 0x04 |
0x04 << 1 | 0x08 |
0x01 << 2 | 0x04 |
0x01 << 3 | 0x08 |
0x0F << 1 | 0x10 |
İkili Formatta Bit Kaydırma | İşlemin Sonucu |
00000001 << 1 | 00000010 |
00000001 << 2 | 00000100 |
00001111 << 1 | 00011110 |
00001111 << 2 | 00111100 |
Burada vereceğim örnekleri Atmel AVR üzerinden anlatmaya çalışacağım. Örneğin PORTA’nın üzerindeki en düşük değerlikli biti HIGH yapmak istediğinizde bunu en basit haliyle
|
PORTA = 1;
|
şekilnde bir atama ile yapabiliyoruz. Biz aslında bu atamayı yapmakla PORTA’ya 00000001 değerini atamış oluyoruz.
Bununla birlikte PORTA üzerindeki en düşük değerli ikinci biti HIGH yapmak istediğimizde ise bunu bit kaydırma operatörü ile kolayca yapabiliriz.
|
PORTA = (0x01 << 1);
|
İfadesi ile 0x01 değerini bir kez sola kaydırmış olduk. Böylece PORTA’nın yeni değeri 0x02 olacaktır.
Eğer PORTA’nın en yüksek değerli bitini (yani 7. biti) HIGH yapmak istersek bu sefer de
|
PORTA = (0x01 << 7);
|
İfadesini kullanırız. Bu ifade ile 0x01 değerini yedi kez sola kaydırarak 0x80 (Yani 10000000) değerini PORTA’ya atamış oluyoruz.
BİRDEN FAZLA DEĞERİ OR’LAMAK
Bazen birden fazla biti HIGH yapmamız gerekebilir. Böyle durumlarda her bir değeri birbiriyle OR’layarak (VEYA işlemine tabi tutarak) istediğimiz bitleri (diğer bitlerin değerleriyle oynamadan) HIGH yapabiliriz. C ve C++’ta OR (VEYA) işleminin karşılığı “|” (Boru) işaretidir.
|
PORTA = (1<<0) | (1<<7);
|
Şunu unutmamak gerekir ki yazdığınız kodlar derleyiciye verilmeden önce bit kaydırma işlemleri ön derleyici tarafından hesaplanır ve böylece yazdığınız kodlar mikrodenetleyici veya işlemci içinde fazladan yer kaplamaz ve işlem gücü tüketmez.
AVR’de Özel Bir Makro: _BV
WinAVR kullananlar _BV makrosunun bit düzeyinde işlemler yaparken ne denli kullanıldığını bilirler. Makronun ne işe yaradığını anlamak için ne yaptığını bilmek gerekir. _BV makrosunun aşağıda verilen tanımı nasıl çalıştığını anlamanızı sağlayacaktır.
|
#DEFINE _BV(bit) (1 << bit);
|
Aslında makro oldukça basit değil mi. Kendisine verilen parametreyi alarak “1” değerini bu parametre kadar sola kaydırıyor. Yukarıda yaptığımız işlemleri bir de bu makroyu kullanarak yapalım.
|
PORTA = _BV(0) | _BV(7);
|
Bu makro sadece AVR kütüphanesine özel olduğundan diğer C veya C++ implementasyonlarında bulamayabilirsiniz. Eğer illa ki kullanacağım derseniz de makro tanımını kodunuzun tepesinde bir yerlere yazarak makroyu kullanabilirsiniz.
PORT DEĞERİNİN TEK SEFERDE YALNIZCA BİR BİTİNİ HIGH (1) YAPMAK
Eğer port değerinin yalnızca bir bitini güncellemek istersek bunu da tek satırda kolayca halledebiliriz. Mesela portun 3. bitini HIGH yapmak ve diğer bit değerlerini olduğu gibi bırakmak için
|
PORTA = PORTA | _BV(3);
|
İfadesini kullanabiliriz. Bu satırda derleyiciye PORTA yazmacının durumunu okumasını ve buradan gelen değerle _BV(3) makrosundan gelen değeri (1 << 3 bit işlemi ile aynı) OR işlemine tabi tutarak sonucu yine PORTA’ya yazmasını söylüyoruz. Sonuç olarak PORTA’nın yalnızca 3. biti HIGH olacak diğer bitleri ise olduğu gibi kalacaktır.
Bu ifadeyi aynı zamanda şöyle de yazabilirdik.
|
PORTA |= _BV(3);
|
Bu durumda da yine PORTA’nın içeriği okunarak _BV(3) ile OR’lanacak ve sonuç yine PORTA’ya yüklenecek. |= operatörü ile tek adımda hem OR işlemini hem de atama işlemini yapabiliyoruz.
PORT DEĞERİNİN TEK SEFERDE YALNIZCA BİR BİTİNİ LOW (0) YAPMAK
Bit değerlerini LOW yapmak, HIGH yapmaya benzer. Bir biti LOW yapmak için yeni değerin tersini (tümleyenini) alıp değiştirmek istediğiniz değerle AND’lemeniz (VE) yeterlidir. Cve C++’ta bir değerin tersini (tümleyenini) almak için değerin soluna “~” (tilda) işareti koyarız.
Mesela PORTA’nın birinci bitini LOW (0) yapmak istersek
|
PORTA &= ~_BV(0);
|
ifadesini kullanırız. Bu ifadenin ne yaptığına gelecek olursak, diyelim ki PORTA’nın değeri halihazırda 0x55 (yani 01010101) olsun. Eğer bu değerin en düşük değerlikli bitini LOW yapmak istersek PORTA’nın değerini 00000001 değerinin tersi (ya da tümleyeni) olan 11111110 değeri ile AND işlemine tabi tutmamız gerekir.
PORTA | 01010101 |
MASKE | 11111110 |
Mantıksal VE İşlemi | 01010100 |
VE işleminin, LOW yapmak istediğimiz bit hariç diğer bitlerin değerini nasıl koruduğuna dikkat edin. Aşağıdaki satırlarda bu işlemi farklı birkaç yoldan nasıl yapacağımızı görebiliriz.
|
PORTA &= ~_BV(0x01);
PORTA &= ~(1<<0);
PORTA = PORTA & ~_BV(0x01);
PORTA = PORTA & ~(1<<0);
|
Bit düzeyinde işlemler geniş ve önemli bir konu. Özellikle kısıtlı hafızaya sahip mikro denetleyiciler söz konusu olduğunda hayati öneme sahip olabiliyorlar. Burada sadece sola kaydırma, sağa kaydırma, ve, veya gibi birkaç bit düzeyinde işlemden bahsettik. Konu hakkındaki daha detaylı bilgileri Google’dan öğrenebilirsiniz..