Register level etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Register level etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

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ı


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

 C++ bitwise operatörlerinden left shift << operatörüne gelmiş bulunmaktayız, adından da anlaşılabileceği üzere binary düzendeki bir değişkeni  MSB (most significant bit) tarafından kayıplarla LSB (least significant bit) tarafından yeni eklemelerde düzenleyen bir operatördür, ne demek istiyorum bir örnekle açıklamaya çalışalım:

int main()
{
	int a = 4;		//0100
	int b = a << 1;		//1000
	cout << "a=" << a << ", b=" << b << endl;
}

şöyle bir çıktıya ulaştık :  a=4, b=8 

burada olan; indekse göre konuşacak olursam, a değişkeninin 2. bitinde yer alan 1 değeri, 1 bit sola kaydırılmış oldu. Olayı bu kadar basit olmakla beraber dikkat edilmesi gereken noktalarımız vardır; ilk dikkat etmemiz gereken şey değişkenin boyutu, int yukarıdaki kod için benim sistemimde 4 bytes. Bu da şu anlama gelir 4bytes * 8 bit 'ten 32 bitlik bir değişkenimiz var demektir,  ve bu 32 bitlik değişkenin en soldaki biti işaret bitidir, değişkenimiz int olduğu için negatif sayıları da barındırır, bunu da sistem MSB yani en soldaki en anlamlı en yüksek değerlikli olan bitten alır bu bit 0 ise pozitif 1 ise negatif olarak değerlendirilir, nereye gelmeye çalışıyorum : int a = 1 deyip, 31 defa left shift yaparsanız şayet sayımız: en solda 1 gerisi 0 olarak değişmiş olur, ayrıca bir bilgi : negatif tarafta anlamlı bitler 0 lardır, işler ters yürür yani, dolayısıyla int değişkeni için negatif tarafta alabileceği en son değeri yakalamış oluruz, deneyelim mi? 

int main()
{
	int a = 1;
	int b = a << 31;		
	cout << "a=" << (int)a << ", b=" << (int)b << endl;
}

 a=1, b=-2147483648 

gördüğünüz üzere sayı negatif taraftaki ulaşabileceği maksimum (sayı değeri bakımından en küçük) değere ulaşmış oluyor. Finalde olan şudur: sağdan yeni bir sıfır eklenir en soldaki bit de kaybolur. Merak edenler için söylemiş olalım left shift gibi, right shift operatörümüz de var, kaydırmak istediğimiz bit sayısı pozitif, sola kaydırma operatörü ile negatif bir sayı kullanarak sağa kaydırabilir miyiz acaba davranışı belirsiz bir davranışa yol açar, bu sebeple o maceraya girmeyin :)

Arithmetic overflow: Left shift count is negative or greater than or equal to the operand size which is undefined behavior.

Arithmetic overflow: Left shift count is negative or greater than or equal to the operand size which is undefined behavior.

Buradan anladığımız üzere üst limitimiz de değişken boyutumuz, yani a << 32 diyemiyoruz, 32 bitlik bir int değişkeni için. Bunlar keyifli konular üzerinde oynayarak ve keyif alarak tecrübe edinebilirsiniz. Bir şeyi farketmiş olmanızı ümit ediyorum bu notaya kadar: eğer etmediyseniz, left shift operatörü aslında sayıyı 2 üzeri kaydırdığınız bit sayısı ile çarpar : yaani, 

1 << 1 demişseniz bu -> 1*2^1 demektir, sonuç olarak 2 üretir,

1 << 2 demişseniz bu -> 1*2^2 demektir, sonuç olarak 4 üretir,

1 << 3 demişseniz bu -> 1*2^3 demektir, sonuç olarak 8 üretir.

İlk örneğimizde a değişkenimiz 10 olsaydı ve b = a << 3; yazsaydık, 10*2^3 'ten 80 sonucuna ulaşacaktık. 10 luk sistemde de böyle değil mi bi sayıyı 10 ile çarpmak istediğimizde sağına bir sıfır ekliyoruz bitti gitti.

Gömülü sistemlerde nasıl karşımıza çıkar ona da bir bakış atalım; yine bir register 'e ait özel bit bitin değerini değiştirmek istediğimizde left shift operatörüne rastlamamız mümkün, buraya kadar gördüklerimizi de üst üste koymuş olalım :

  DDRB |= (1 << DDB1);
  PORTB |= (1 << PORTB1);
  PORTB &= ~(1 << PORTB1);

ilk satırı al setup 'ın içine diğer iki satırı da aralarına delay ekleyerek loop 'un içine at, bildiğimiz blink kodu. Şimdi bakalım şair burada ne anlatmak istemiş,

DDRB ; atmega328p için DataDirectionRegisterB den gelmekte, PORTB için giriş çıkış durumlarının belirlendiği register, kendisini |= yaparak eski konfigürasyonunu koruyarak 1 nolu pinini çıkış olarak ayarlamışız, peki neler olmuş burda adım adım bakalım:

DDRB 'nin başlangıç notasında 0000 0000 olduğunu kabul ediyoruz, DDB1 iom328p.h dosyasında 

#define DDB1 1

olarak tanımlanmış, bu yazarken ne yaptığımızı da görelim bilelim diye, o zaman parantez içinde şu olmuş (1 << 1 ) => 0000 0001 miş sola bir bit kaydırmışız 0000 0010 olmuş, sonra bu değerle DDRB yi orlamışız : 0000 0000 | 0000 0010 => 0000 0010 elde etmişiz, aslında basit değil mi? anlattıklarımın aynısı bir alt satır için de geçerli PORTB1 neymiş ona bakalım sadece :

#define PORTB1 1

o da 1 'miş yani tıpatıp aynısı, sadece PORTB yazmacına yazmış olduk.

Son satır biraz karmaşık gibi, ama değil. Şimdiye dek gördüklerimizden tek eksiğimiz ~ lambda işareti, bunun da olayı çok basit; önüne yerleştirilen operandın 1 lerini 0, 0 larını 1 yapar. Parantezin içi aynı: 0000 0010, ~ ile şu hale gelir => 1111 1101 sonra PORTB 'yi bir önceki satırda 0000 0010 yapmıştık, bununla & işlemine tabii tutuyoruz : 0000 0010 & 1111 1101 => 0000 0000, loop un içerisinde B portunun 1 numaralı pini bir HIGH bir LOW oluyor.

Kafanıza takılan bir şey olursa yorumlarda sormaya lütfen çekinmeyin, herkese kolay gelsin!

Bu arada ben bu left shift operatörüyle PORTB içinde çalışan bir kara şimşek kodu yazabilirim diyen cesur arkadaşım, seni yorumlara bekliyoruz,  😉 Bir tüyo lazım olabilir: sağa kaymak için right shift operatörünü kullanacaksın >> Bir sonraki konumuzda onu yazıyor olacağız.



Önceki konu: Bitwise And ~ C++ ve operatörü &

Sonraki konu: C++ Right Shift Operatörü

C++ Dersleri | Bit işlemleri - Bitwise And - C++ ve operatörü &

 C++ bitwise and (ve operatörü) & , dijital elektronikten bildiğimiz ve kapısıyla aynı mantıkla çalışmaktadır, iki operandı bulunup, her iki operand da doğru ise doğru (true) sonucunu üretir, diğer tüm olaslıklarda yanlış (false) sonucunu üretir. C++ ve operatörü için doğruluk tablosunu bir görsel ile paylaşalım :

cpp and operator truth table

kodlarken de aynı isimdeki değişkenleri kullanalım:

int main()
{
	int a = 7;		//0111
	int b = 13;		//1101
	int aANDb = a & b;	//0101
	cout << "a=" << a << ", b=" << b << ", a&b=" << aANDb;
}

programın çıktısı şu şekilde :  a=7, b=13, a&b=5 

Sonuç olarak 5 elde ettik, C++ 'ın bu hesaplamayı nasıl yaptığını alttaki görselde açıklamaya çalıştım:

Adım adım and işlemi

Her sütunu kendi içinde and işlemine tabi tutup aynı haneye cevap olarak döndürüyor. Bu operatörün kendi başına değişkenin değerinde bir değişiklik yapmadığını unutmayın, a değişkenini 5 rakamıyla and işlemine tabi tutup çıkan değeri a ' ya atamak için mutlaka eşittir operatörü kullanmak gerekiyor:

int main()
{
	int a = 7;			//0111
	a & 5;
	cout << "a=" << a << endl;
	a &= 5; // => a = a & 5;
	cout << "a=" << a << endl;
}

ilk satır 7 çıktısını verirken, ikinci satırda 7 & 5 in sonucu olan 5 değerini görebiliriz.

Bitwise operatörlerden bahsettiğimiz ilk bölümde dediğimiz gibi bitwise operatörler çoğunlukla gömülü sistemlerde karşımıza çıkar; and operatörü için register seviyesinde bir atmega328p programladığımızı düşünelim, kodumuzun önceki kısımlarında da PORTB 'nin 3. pinini çıkış olarak ayarladığımızı ve şimdide 2.pinini giriş olarak ayarlamak istediğimizi kabul edelim.

  DDRB =  0b00001000; // 3 pini giriş olarak ayarladık
  DDRB &= 0b11111011; // 3 pini giriş olarak ayarladığımız
                       // konfigurasyona zarar vermeden 2 pini
                       // giriş olarak ayarladık

Bunu yaptığınız zaman hem 2. pinin (en sağdan 0 dan başlayarak sola doğru sayıyoruz-MSB -LSB dizilimi) giriş olarak ayarlanmasını garanti etmiş olursunuz: çünkü eski konfigurasyonu ne olursa olsun biz & ile birlikte o pin için 0 gönderdiğimiz için sonucun 0 üretmesini garanti altına almış oluyoruz, hem de diğer bütün pinleri 1 ile and işlemine tabi tutarak evvelce 1 iseler 1 kalmalarını 0 iseler sıfır kalmalarını garantilemiş oluyoruz. Aynı mantıkla pinin dijital seviyesini de bu şekilde LOW 'a çekmeyi garantileyebilirsiniz.

Kafanıza takılan her şeyi lütfen yorumlarda sormaktan çekinmeyin, Şimdilik herkese kolay gelsin



Önceki konu :  Bitwise XOR, Özel Veya Operatörü

Sonraki konu : Bitwise Operatörleri | Left Shift Operatör

Arduino UNO, Atmel Studio üzerinden programlamak | AVR Programlama - Registers




Arduino üzerinde bazı şeyleri öğrendik, hazır kütüphaneler üzerinde projelerimizi çalıştırdık, ama sanki IDE üzerinde eksik bişey var gibi, mesela bir IntelliSense olaydı ne güzel olmaz mıydı? hani şu değişken adını yazmaya başladığımızda tamamlama önerileri çıkartan, ya da nesne tabanlı programlamada kullandığımız; nesne. yazınca nesnenin tüm özelliklerine ulaşabildiğimiz yardımcı pencere açan.. bunun için Arduino yu bir adım ileriye taşıyan Atmelin kendi kodlayıcısı Atmel Studio (artık yerini MicroChip Studio alıyor) mevcut, Visual Studio kullananların hemen alışacağı (neredeyse aynısı) bir kodlama arayüzü, kod yazmak için biraz datasheet karıştırmak gerekiyor. Ancak kontrolün sizde olduğunu bilmek bir ayrıcalık, Arduino IDE ile yazılmış bir led yakın söndürme kodu :


void setup() {

  // initialize digital pin LED_BUILTIN as an output.

  pinMode(LED_BUILTIN, OUTPUT);

}

// the loop function runs over and over again forever

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

  delay(1000);                       // wait for a second

  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

  delay(1000);                       // wait for a second

}

avrdude: 924 bytes of flash written, 

924 bytes yer kaplarken, aynı işi yapan Atmel Studio ile register seviyesinde yazılmış olan şu kod :


#define F_CPU 16000000UL

#include <avr/io.h>

#include <util/delay.h>


int main(void)

{

DDRB |= (1 << DDB5);

while (1)

{

PORTB |= (1<<PORTB5);

_delay_ms(1000);

PORTB = 0;

_delay_ms(1000);

}

}

avrdude.exe: writing flash (176 bytes):

sadece 176 bytes yer kaplıyor, yaklaşık 5.25 katı, 176 bytes ile yapılabilecek işi 924 bytes ile yapmak, nerden baksak bir mühendisin fiyat/performans tarzına uymuyor. 

Peki konu sadece kodun hafızada kapladığı alan mı acaba? Hıza da bakalım mı ?

void setup() {
pinMode(3,OUTPUT);
}

void loop() {
  digitalWrite(3,HIGH);
  digitalWrite(3,LOW);
}

yukarıda gördüğünüz Arduino ide de yazılmış bir kod sizce hangi frekanslarda 3 pini açıp kapatabiliyordur?


112 Khz mi? Hey dostum tek yapabildiğin bu mu? hadi onu geçtim, 1ms lik aralıklarla yaptığın gecikmeler de neyin nesi ?

Studio 'ya ve register level 'e geçelim :

#include <avr/io.h>

int main(void)

{

DDRD |= (1<<DDD3);

/* Replace with your application code */

while (1)

{

PORTD = 8;

PORTD = 0;

}

}


Evet şimdi konuşmaya başladın : 3.2 Mhz :) 27.8 kat daha hızlı ve alt tarafta görebileceğiniz üzere 1ms lik gecikemeler de artık YOK.

Tamam, kararımızı verdik, kodumuzu yazdık, başka hiçbir ek donanım gereksinimi olmadan kodumuzu nasıl Arduino UNO kartımıza yükleyeceğiz?


Atmel Studio 7 (Version 7.0.1931) için şöyle:
Tools Menusu /  External Tools
açılan pencerede Add
Title kısmı tamamen tercihsel ne isim verirseniz, -boş bırakılamaz!
Command kısmı: C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe
Arguments kısmı: -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -v -patmega328p -carduino -PCOM7 -b115200 -D -Uflash:w:"$(ProjectDir)Debug\$(TargetName).hex":i

PCOM7, benim için geçerli Uno Com7 üzerinden çalışıyor, siz kendi portunuzu yazın.
bir kaçtane kartınız var ve hepsinde farklı com görünüyorsa Prompt for arguments işaretleyip, çalıştırıldığında arguments kısmından seri portunuzu elle değiştirebilirsiniz.

Ok deyip ayrılıyoruz pencereden, artık Tools menusu içinde "tercihsel" olarak belirlediğimiz Tool ismi görünüyor olmalı, projemizi Build/Build project menusunden derliyoruz ki "$(ProjectDir)Debug\$(TargetName).hex":i noktasında hex dosyamız oluşsun, sonrasında Tools/Tercihen verdiğimiz araç ismi ne tıklayarak kodumuzu kartımıza yükleyebiliriz.

Biraz zahmetli gibi? yazdığım kodun 5 kat daha fazla yer kaplaması benim için sorun değil diyorsan Arduino IDE devam, hayır önemli diyorsan aramıza hoşgeldin.

-Kolay gelsin.

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...