C sorularım

Başlatan xoom, 08 Ekim 2024, 19:42:35

xoom

void HC595writePin(uint8_t pin, uint8_t value)
{
      if (value == 0)
      {
          currentVal &= ~(1 << pin);
      }
      else
      {
          currentVal |= (1 << pin);
      }
      HC595write();


HC595writePin(5, 1); //fonksiyona bu değerleri yazdığımda..
CurrentVal değerinin 5.Pinini 1 ile SET edecek buraya kadar tamam
Peki
currentVal &= ~(1 << pin);
Bu kod bu işlemi nasıl yapıyor onu anlayamadım.
ilgili pin değeri kadar sola kaydırıyor ardından bit bazında AND işlemi mi yapıyor ?
Kodu hazır bir yerden aldım fakat kafamda oturmadan ilerlemek istemedim.


serkan

Tüm bitleri ters çeviriyor.

xoom

Alıntı yapılan: serkan - 08 Ekim 2024, 21:35:07Tüm bitleri ters çeviriyor.
~ bu işaretle mi? biraz parça parça açıklar mısın?

elektronik kassabı

x&=y bunun kısaltmasıdır: x=x&y

~x değişkeni bit bit tersler. Atıyorum mesela x 8 bitlik bir değişken olsun, x=0b10101010 ise ~x==0b01010101'dir.

Sonuç olarak önce kaydırma işlemini yapar, bunu tersler, currentVal ile bunu VE işleminden geçirir. Böylece currentVal'ın pin ile seçilmiş biti sıfırlanmış olur.

fide

#4
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

sedronjames

C dilinde bit operatörleri olarak araştırırsan muhakkak kaynak bulursun. Kütüphane oluştururken register ayarlamada çoğunlukla bit operatörler kullanılır. ne işe yaradıklarını anladıktan sonra muhakkak birkaç pratik yapmalısın.

yine bu bit operatörleri çarpma bölme gibi işlemlerin hızlıca yapılmasını da sağlıyor.

örneğin bir gerilimin ortalama değerini ölçmek için bir periyot boyunca 10 örnek alabilirsin. ama 2nin kuvvetleri şeklinde örnek alırsan (mesela 16) ortalama değerini bulurken 10'a bölme işlemi yapmazsın, (2^4 = 16) toplamda elde ettiğin sayıyı 4 bit sağa kaydırarak aslında 16ya bölmüş olursun. bu da sana zaman kazandırır.

istinaf duvarı

#6
currentVal |= (1 << pin)
Bu ifadeyi çoğunlukla atmelciler kullanıyor gördüğüm kadarıyla. Genelde bir pini çıkış ya da giriş yapmak için kullanıyorlar. Ama olayın mantığını çözebilmiş değilim.
portb0 değerini 1 bit sola kaydırınca nasıl output oluyor,
0 bit sola kaydırınca nasıl input oluyor hiç anlamış değilim.

Tagli

Alıntı yapılan: istinaf duvarı - 09 Ekim 2024, 14:39:54Bu ifadeyi çoğunlukla atmelciler kullanıyor gördüğüm kadarıyla.
Gömülü yazılım ile uğraşan herkes tarafından sıklıkla kullanılır bu ve benzeri ifadeler.

(1u << pin) türündeki ifadeler
00000001
00000010
00000100
gibi sonuçlar verir.

Benzer şekilde ~(1u << pin) ifadeleri ise
11111110
11111101
11111011
gibi sonuçlar verirler.

Bunlar | ve & işlemleri ile kullanılarak işlemcinin ilgili register'ındaki bir bitin değiştirilmesini sağlarlar.

Bu arada genelde çok sorun olmasa da doğru kullanım 1 değil 1u üzerinde kaydırma yapmaktır. Çünkü C'de tek başına bir tam sayı int türünden algılanır, yani işaretlidir. İşaretli sayılar üzerinde kaydırma yapmak tanımsız davranışa sebep olabilir ve bu yüzden tehlikeli kabul edilir.
Gökçe Tağlıoğlu

mehmet

#8
Alıntı yapılan: istinaf duvarı - 09 Ekim 2024, 14:39:54
currentVal |= (1 << pin)
Bu ifadeyi çoğunlukla atmelciler kullanıyor gördüğüm kadarıyla. Genelde bir pini çıkış ya da giriş yapmak için kullanıyorlar. Ama olayın mantığını çözebilmiş değilim.
portb0 değerini 1 bit sola kaydırınca nasıl output oluyor,
0 bit sola kaydırınca nasıl input oluyor hiç anlamış değilim.

İlgili mcu kataloglarını inceleyiniz. Atmel mcularda; I/O için bir kaç fazladan register(DDR, PIN, vs.) bulunmakta. I/O yapılandırması, MC PIC yapılandırmasından farklı. Bunları inceleyip karşılaştırabilirsiniz.

Ayrıca; bit işlem kısmını, sadece gömülü yazılım veya C ile uğraşanlar değil, tüm yazılım işleriyle uğraşanların bilmesi gerekli.
Özellikle endüstriyel işleri yapanlar. Pin sayısı az olan yerlerde bu işlemlerin kullanılması neredeyse mecburi. Donanımcı bilse bile, PC yazılımı ile ilgilenler bilmezse bu olay işe yaramayacaktır.

Alttaki makroları, her hangi bir mcu kodunun başına eklerim. Çok yardımcı olur. Benzerlerini internette bulmanız mümkün.
/*_BV, sbi, rbi Arduino da tanımlı*/
#define _BV(bt)                (1 << (bt))
#define sbi(port, bt)          (port) |= _BV(bt)    /* Set bit number n in byte b  */
#define cbi(port, bt)          (port) &= ~_BV(bt)  /* Clear bit number n in byte b */

#define rbi(port, bt)          (port) & _BV(bt)    /* Read bit number n in byte b  */
#define fbi(port, bt)          (port) ^= _BV(bt)    /* Flip bit number n in byte b  */
#define bit_is_set(port, bt)    (port) & _BV(bt)    /* Test if bit number n in byte b is set  */
#define bit_is_clear(port, bt)  (!port) & _BV(bt)    /* Test if bit number n in byte b is clear */

#define pinToggle(port, bt)    (port ^= 1 << bt)
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

sedronjames

Alıntı yapılan: Tagli - 09 Ekim 2024, 18:03:38Gömülü yazılım ile uğraşan herkes tarafından sıklıkla kullanılır bu ve benzeri ifadeler.

(1u << pin) türündeki ifadeler
00000001
00000010
00000100
gibi sonuçlar verir.

Benzer şekilde ~(1u << pin) ifadeleri ise
11111110
11111101
11111011
gibi sonuçlar verirler.

Bunlar | ve & işlemleri ile kullanılarak işlemcinin ilgili register'ındaki bir bitin değiştirilmesini sağlarlar.

Bu arada genelde çok sorun olmasa da doğru kullanım 1 değil 1u üzerinde kaydırma yapmaktır. Çünkü C'de tek başına bir tam sayı int türünden algılanır, yani işaretlidir. İşaretli sayılar üzerinde kaydırma yapmak tanımsız davranışa sebep olabilir ve bu yüzden tehlikeli kabul edilir.


kesinlikle katılıyorum. bir kere başıma buna benzer bir problem geldi. sabit bir ondalıklı sayıyı makro olarak tanımlamıştım. yanında türünü belirtmedim. meğerse kullandığım compiler double türünde tutuyormuş bu değişkeni. 20 mikrosaniye içerisinde motor kontrol işlemleri yapmam gerekiyordu. kod düzgün çalışmayınca benden daha tecrübeli bir ağabeyime danıştım ve bahsettiğim hatamı o görmüştü. makro bile tanımlasanız değişken türünü muhakkak girmelisiniz.

xoom

#10
a= 0b0000100010000000
b= 0b0000100001000000
c= 0b1000000010000000

    d= 0b1000100011000000

sonucun d'yi vermesi için nasıl bir kod yazmalıyım?
Ek:  amacım a,b,c değişkenlerinde hangi bit 1 olursa d sonucunda görmek istiyorum.


power20

d = a|b|c;

xoom

#12

Arkadaşlar yukaridaki yapı kurulu bir devrem var.
Bu ledleri kontrol etmekte bazı sıkıntılar yaşıyorum. 14 adet ledim var.
ledleri aşağıdaki kodlar ile kontrol ettiğimde 8-9 lede kadar ledlerde titreme olmasada
14 ledin tamamını yakmak istediğimde sanırım tarama frekansından dolayı ledler titremeye başlıyor.
bu sorunu nasıl aşmalıyım?
uint16_t Status[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void HC4094write()
{
    for(int i=0; i<16; i++)
    {
        if(currentVal & (1<<i))
        {
            HAL_GPIO_WritePin(SER_PORT, SER_PIN, GPIO_PIN_SET);
        }
        else
        {
            HAL_GPIO_WritePin(SER_PORT, SER_PIN, GPIO_PIN_RESET);
        }
        HAL_GPIO_WritePin(SRCLK_PORT, SRCLK_PIN, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(SRCLK_PORT, SRCLK_PIN, GPIO_PIN_SET);
    }
    HAL_GPIO_WritePin(RCLK_PORT, RCLK_PIN, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(RCLK_PORT, RCLK_PIN, GPIO_PIN_SET);
}
74hc4094 Shift Register yazma blogum.
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6)==0) 
	{
	Status[0]=0b0000100001000000;
	}

	else
	{
	Status[0]=0b0000000000000000;
	}
Yukaridaki gibi 14 adet giriş pinim var.
  for(int i=0;i<14;i++)
        {
            currentVal=Status[i];
            HC4094write();
            HAL_Delay(1);
            currentVal=0;
            HC4094write();
        }
Girişleri taramak için kullanıyorum

mehmet

#13
Bir timer modülü içine kodları gömerseniz daha iyi olacaktır.
Matriks yerine papatya zinciri şeklinde yapabilirdiniz. Pwm yoksa daha kolay olur.
Sanki dizi içinden değer okumaktansa, iki byte değer içinden bir okumak daha hızlı olacaktır.


12F675, 20MHz kristal ile iki HC595 ile 16 kanal pwm yapmıştım. Ama sadece test için. Bir uygulamadan kullanılmamalı...
https://etepic.com/index.php/topic,4852.0.html
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

xoom

Alıntı yapılan: mehmet - 21 Ekim 2024, 17:32:45Bir timer modülü içine kodları gömerseniz daha iyi olacaktır.
Matriks yerine papatya zinciri şeklinde yapabilirdiniz. Pwm yoksa daha kolay olur.
Sanki dizi içinden değer okumaktansa, iki byte değer içinden bir okumak daha hızlı olacaktır.


12F675, 20MHz kristal ile iki HC595 ile 16 kanal pwm yapmıştım. Ama sadece test için. Bir uygulamadan kullanılmamalı...
https://etepic.com/index.php/topic,4852.0.html
Devreyi değiştirme şansım yok.
1ms timer oluşturup Tarama blogunu oraya yerleştirdim ama sonuç değişmedi.
Sanırım mantığımı değiştmem gerekiyor ama kafam öyle karıştı ki farklı nasıl yazılır düşünemediğim için buraya yazdım.