Picproje Elektronik Sitesi

BİLGİSAYAR => Donanım ve Yazılım => Konuyu başlatan: yamak - 24 Ekim 2014, 13:43:57

Başlık: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 13:43:57
Aşağıdakine benzer bi kodum var.

typedef struct
{
  unsigned char NoError:1;
  unsigned char LowEnergy:1;
  unsigned char LowVoltage:1;
  unsigned char LowCurrent1:1;
  unsigned char LowCurrent2:1;
  unsigned char HighCurrent1:1;
  unsigned char HighCurrent2:1;
}BatteryError;

BatteryError* error;

int main(void)
{
     ControlBattery(error);
     while(1)
    {
    }

}
void ControlBattery(BatteryError* error)
{
  unsigned char voltageLevel,currentLevel1,currentLevel2;
  float voltage,current1,current2;
  *(unsigned char*)error=0;
  voltageLevel=ReadVoltageLevel();
  currentLevel1=ReadCurrent1Level();
  currentLevel2=ReadCurrent2Level();
  if(ChargeState<=CHARGE_LEVEL_1)
    error->LowEnergy=1;
  if(voltageLevel<=LOW_VOLTAGE_LEVEL)       
    error->LowVoltage=1;                   
  if(currentLevel1<=LOW_CURRENT_LEVEL)
    error->LowCurrent1=1;
  else if(currentLevel1>=HIGH_CURRENT_LEVEL)
    error->HighCurrent1=1;
  if(currentLevel2<=LOW_CURRENT_LEVEL)
    error->LowCurrent2=1;
  else if(currentLevel2>=HIGH_CURRENT_LEVEL)
    error->HighCurrent2=1;
  voltage=((0.6/0xFFFFFF)*((float)Voltage)+VOLTAGE_OFFSET)*VOLT_COEFF;
  current1=(((0.6/0xFFFFFF)*((float)Current))*SHUNT)/16.0;
  current2=(((0.6/0xFFFFFF)*((float)Current))*SHUNT)/16.0;
  energyCounter+=((voltage*(current1+current2))*DELTATIME)/3600.0;
}


Bu durumda hiç bir şekilde LowCurrent1 ve LowEnergy bit leri set edemiyorum.Ama structure ı mı aşağıdaki gibi değiştirince her şey gayet güzel çalışıyo.
typedef struct
{
  unsigned char LowEnergy:1;
  unsigned char LowVoltage:1;
  unsigned char NoError:1;
  unsigned char LowCurrent1:1;
  unsigned char LowCurrent2:1;
  unsigned char HighCurrent1:1;
  unsigned char HighCurrent2:1;
  unsigned char No:1;
}BatteryError;


Bu problemin mantıklı bi açıklaması var mı?Kullanıdığım ortam IAR mcu msp430. Biraz forumlarda falan araştırınca millet bit field kullanmayaın falan diyo.Yani önermiyolar.Ama bu zamana kadar bir çok kez kullandım ve hiç bir sorunla karşılaşmadım.Var mı bu sorunun bi cevabı?Yoksa compiler problemi mi?
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: CLR - 24 Ekim 2014, 14:01:42
Hatanın sebebini asm'li çıktısından bulabilirsin ama hatanın sebebi MSP430 16bitlik işlemci olduğundan structları 16bit tanımlamalıydın, bit field'leri 16bit tanımlarsan compiler hatası yoksa sorun düzelecektir. Veya illa 8bit kullanmak istiyorum diyorsan bu struct 'ın olduğu alanı pack(1) yaparakta çözebilirsin.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mir_as82 - 24 Ekim 2014, 14:02:10
hocam if içindeki tür uyumsuzluğu olabilir mi?
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 14:07:05
Alıntı yapılan: CLR - 24 Ekim 2014, 14:01:42
Hatanın sebebini asm'li çıktısından bulabilirsin ama hatanın sebebi MSP430 16bitlik işlemci olduğundan structları 16bit tanımlamalıydın, bit field'leri 16bit tanımlarsan compiler hatası yoksa sorun düzelecektir. Veya illa 8bit kullanmak istiyorum diyorsan bu struct 'ın olduğu alanı pack(1) yaparakta çözebilirsin.
Neden?Böyle bi kural mı var?MSP430 16 bitlik olabilir ama byte erişim için instruction'lara sahip.Hem başka bi yerde 8 bitlik field kullanıyorum.

mesaj birleştirme:: 24 Ekim 2014, 14:07:42

Alıntı yapılan: mir_as82 - 24 Ekim 2014, 14:02:10
hocam if içindeki tür uyumsuzluğu olabilir mi?
Hocam onu da denedim unsigned char a type cast yaptım yine de olmadı.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: AsHeS - 24 Ekim 2014, 14:08:12
typedef struct
{
  volatile unsigned char NoError:1;
  volatile unsigned char LowEnergy:1;
  volatile unsigned char LowVoltage:1;
  volatile unsigned char LowCurrent1:1;
  volatile unsigned char LowCurrent2:1;
  volatile unsigned char HighCurrent1:1;
  volatile unsigned char HighCurrent2:1;
}BatteryError;


Bunu bir deneyebilir misin ? Benzer bir problem benimde STM32'de başıma gelmişti volatile yapınca çözülmüştü.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mir_as82 - 24 Ekim 2014, 14:14:20
  if(currentLevel1<=LOW_CURRENT_LEVEL) bu kodda LOW_CURREN_LEVEL in türü ne hocam? Eğer türü int ise sıkıntı olabilir.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 14:16:59
Alıntı yapılan: AsHeS - 24 Ekim 2014, 14:08:12
typedef struct
{
  volatile unsigned char NoError:1;
  volatile unsigned char LowEnergy:1;
  volatile unsigned char LowVoltage:1;
  volatile unsigned char LowCurrent1:1;
  volatile unsigned char LowCurrent2:1;
  volatile unsigned char HighCurrent1:1;
  volatile unsigned char HighCurrent2:1;
}BatteryError;


Bunu bir deneyebilir misin ? Benzer bir problem benimde STM32'de başıma gelmişti volatile yapınca çözülmüştü.
Hocam olmadı yaw.
Alıntı yapılan: mir_as82 - 24 Ekim 2014, 14:14:20
  if(currentLevel1<=LOW_CURRENT_LEVEL) bu kodda LOW_CURREN_LEVEL in türü ne hocam? Eğer türü int ise sıkıntı olabilir.
Hocam onlar define edilmiş sabitler.Yani türleri int.Fakat şöyle bi sıkıntı debug modda o satırın çalıştığını görüyorum.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: CLR - 24 Ekim 2014, 14:27:39
Alıntı yapılan: yamak - 24 Ekim 2014, 14:07:05
Neden?Böyle bi kural mı var?MSP430 16 bitlik olabilir ama byte erişim için instruction'lara sahip.Hem başka bi yerde 8 bitlik field kullanıyorum.

IAR'da çok kez bi field kullandım cortem3'lerde ama ya hep u32 yaptım yada packed alanda u8/u16 kullandım  o nedenle senin sorununla karşılaşmadım diye söylüyorum.
Mesela senin bakış açınla cortem m3'te de u8 erişimi var ama u8 olarak belirtmezsen u32'lik alana yerleştiriyor, demekki senin compilerda u8'lik değil u16'lık alana yerleştirebilir ve bit kayması oluşabilir.
Benimkisi sadece öneri u8'leri u16 yapıp test edeceksin sadece.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mir_as82 - 24 Ekim 2014, 14:28:00
Eğer define edilmiş sembolik sabit negatif bir değer değilse sıkıntı olmaz.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: justice_for_all - 24 Ekim 2014, 14:33:58
C18 de bit tanımlaması yaparken unsigned diye yapılıyor bide oyle dene istersen.

unsigned NoError:1;

şeklinde

Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: hasankara - 24 Ekim 2014, 14:37:07
tam ben yazacaktım evet bende böyle kullanıyorum
unsigned NoError:1;
hatta 1 bit olduğunu belirtmeye de gerek kalmıyor.
unsigned NoError;

edit sebebi: yanlış bilgi paylaşımı.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 14:45:28
Alıntı yapılan: CLR - 24 Ekim 2014, 14:27:39
IAR'da çok kez bi field kullandım cortem3'lerde ama ya hep u32 yaptım yada packed alanda u8/u16 kullandım  o nedenle senin sorununla karşılaşmadım diye söylüyorum.
Mesela senin bakış açınla cortem m3'te de u8 erişimi var ama u8 olarak belirtmezsen u32'lik alana yerleştiriyor, demekki senin compilerda u8'lik değil u16'lık alana yerleştirebilir ve bit kayması oluşabilir.
Benimkisi sadece öneri u8'leri u16 yapıp test edeceksin.
Yapıp test ettim olmadı."Mesela senin bakış açınla cortem m3'te de u8 erişimi var ama u8 olarak belirtmezsen u32'lik alana yerleştiriyor" bu cümle ile de ne demek istediğini anlamadım.Bir de alligment ı compiler ın değişkenleri belleğin 4 katı ya da 16 bitlik sistemlerde 2 nin katı olan bölgelere yerleştirmesini istemediğimiz durumlarda kullanırız.Benim sorunumun alligment ile olan bağlantısını anlayamadım.Ayıca sen dedikten sonra cortex m4 te hiç alligment yapmadan unsigned char türünde bit field tanımladım ve bütün bitlere güzel güzel eriştim.

mesaj birleştirme:: 24 Ekim 2014, 14:48:20

Alıntı yapılan: justice_for_all - 24 Ekim 2014, 14:33:58
C18 de bit tanımlaması yaparken unsigned diye yapılıyor bide oyle dene istersen.

unsigned NoError:1;

şeklinde
Hocam unsigned dersem unsigned int olarak kabul eder.
Alıntı yapılan: hasankara - 24 Ekim 2014, 14:37:07
hatta 1 bit olduğunu belirtmeye de gerek kalmıyor.
unsigned NoError;
Nasıl yani 1 bit olduğunuz belirtmeye gerek kalmıyor.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mir_as82 - 24 Ekim 2014, 14:54:14
siz global alanda bir pointer tanımlamışsınız(statik) ve hiç bir nesne adresi vermeden, o pointeri main içinde fonksiyonunuza parametre olarak geçmişsiniz. Yani NULL pointeri parametre olarak geçmişsiniz. Sorun buradan kaynaklanabilir mi?
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: CLR - 24 Ekim 2014, 15:03:14
İşlemcide 16 bit ama 8 biti destekleyen asm komutları var dedin diye söyledim. Aynı durum cortex m3'te de var çünkü. Byte/HWord alligment bahsetmiyorum bit alligment bazında bahsediyorum. Belki 16bit tanımlamadığın için yanlış yerleştiriyor olabilir dedim. 16bit tanımladıktan sonra hala set/reset etmemişse muhtemelen compiler sorunu görünüyor.

8 bitlik registeri 16/32bitlik işlemcide Packed etmezsen her defasında doğru çalışcağını garanti edemezsin. 
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 15:15:59
Alıntı yapılan: mir_as82 - 24 Ekim 2014, 14:54:14
siz global alanda bir pointer tanımlamışsınız(statik) ve hiç bir nesne adresi vermeden, o pointeri main içinde fonksiyonunuza parametre olarak geçmişsiniz. Yani NULL pointeri parametre olarak geçmişsiniz. Sorun buradan kaynaklanabilir mi?
Hocam normalde bu dediğiniz doğru ama benim asıl kodumda o değişken global değil.Ama bu gözümden kaçmış.Normalde pointer local de olsa global de olsa initialize etmek gerekir.Bir de ben bu soruyu sorarken asıl sormak istediğim kod normalde çalışmazken struct içindeki değişkenlerin yerini değiştirdiğimde neden çalışıyor olması.

Edit:Hatta şu an denedim sorun ortadan kalktı.
Ama en azından bu saçma hatayı görememem sayesinde şunu öğrendim:Msp430 forumlarındaki guru'lara göre bit field hiç önerilen bir şey değilmiş.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: JKramer - 24 Ekim 2014, 15:47:09
Değişkenlerin yerlerinin değişmesinin yanında sekize de tamamlamışsınız, ilk structure'da yedi adet değişken var.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 15:51:44
Hocam onlar buraya yazarken oldu.Normalde 7 değişken var.Hocam sebebi kesinlikle pointer ı initialize etmemiş olmam.Yerlerini değiştirdiğimde çalışıyor olması bence tesadüf.Mesela şöyle bişey olabilir.İlk durumda initialize etmediğim için belleğin güvenli olmayan bi yerini değiştiriyorum.Yerlerini değiştirdikten sonra compiler tesadüfi olarak pointerın gösterdiği adres güvenli biyer olmuş bu durumda da hiç bir sorun olmamış olabilir.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mir_as82 - 24 Ekim 2014, 16:12:19
Ben olayı anlamadım :). Sorun sizin derleyicinizde mi? Sorun runtime hatası olacak şekilde kod yazılmasında mı? Kodunuzda runtime hatası varsa bazen doğru çalışır bazen doğru çalışmaz. Yani istediğiniz sonucu almanız kodunuzun doğru olduğu manasına gelmez hocam. Aman dikkat.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: CLR - 24 Ekim 2014, 16:21:26
Compiler derlerken pointer point etmiyor diye uyarmıştır sizi ama açıkçası ben çalıştığınız proje üzerinden yazdığınızı düşünmüştüm.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 17:05:19
Alıntı yapılan: mir_as82 - 24 Ekim 2014, 16:12:19
Ben olayı anlamadım :). Sorun sizin derleyicinizde mi? Sorun runtime hatası olacak şekilde kod yazılmasında mı? Kodunuzda runtime hatası varsa bazen doğru çalışır bazen doğru çalışmaz. Yani istediğiniz sonucu almanız kodunuzun doğru olduğu manasına gelmez hocam. Aman dikkat.
Hocam derleyicide falan sorun yok.Bahsettiğim problem derleme esnasında ortaya çıkacak bi problem değil.Olay şu pointer ı tanımladım ama initialize etmedim.Yani local pointer tanımladığım için nereyi gösteriği belli değildi.Bu durumdada run time esnasında ne olacağı belli değildi.Tesadüfi olarak değişkenlerin yerini değiştirdiğimde kod çalıştı
Alıntı yapılan: CLR - 24 Ekim 2014, 16:21:26
Compiler derlerken pointer point etmiyor diye uyarmıştır sizi ama açıkçası ben çalıştığınız proje üzerinden yazdığınızı düşünmüştüm.
Tamam çalıştığım proje üzerinden yazdım ama tamamını kopyalayıp yapıştırmadım.Bi de öyle bi uyarı vermedi çünkü pointer gösterdiği bir yer vardı ama güvenli bi yer değildi.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: CLR - 24 Ekim 2014, 17:30:07
Tamda bundan bahsediyordum önceki mesajımda, şimdi aslında uygulamalı oldu, Kendisi bir adres gösterdiyse, neden 8bitide aynı yere atmadı. 6 tanesi doğru değişirken 2 tanesi yanlış değişiyor, muhtemelen onlar 16bit içinde bir yerde. Pointer aynı anda iki adres göstemiyeceğine göre.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 17:55:10
Alıntı yapılan: CLR - 24 Ekim 2014, 17:30:07
Tamda bundan bahsediyordum önceki mesajımda, şimdi aslında uygulamalı oldu, Kendisi bir adres gösterdiyse, neden 8bitide aynı yere atmadı. 6 tanesi doğru değişirken 2 tanesi yanlış değişiyor, muhtemelen onlar 16bit içinde bir yerde. Pointer aynı anda iki adres göstemiyeceğine göre.
"muhtemelen onlar 16bit içinde bir yerde" bu cümle ile ne demek istediğini anlamadım.Bellek zaten 16 bitlik.
Pointer ı initialize edince her şey gayet güzel çalıştı.Ayrıca ben bu şekilde defalarca kullandım hem pc de hem embedded da (8 16 32 bitlik sistemlerin hepsinde) hiç birinde sorun olmadı.İstersen aşağıdaki kodu gcc'de bi derleyip çalıştır.
#include <stdio.h>
typedef union
{
    unsigned char all;
    struct
    {
    unsigned char bit1:1;
    unsigned char bit2:1;
    unsigned char bit3:1;
    unsigned char bit4:1;
    unsigned char bit5:1;
    unsigned char bit6:1;
    unsigned char bit7:1;
    unsigned char bit8:1;
    }bit;
}Byte;

int main(void)
{
    Byte byte1;
    byte1.bit.bit1=1;
    byte1.bit.bit5=1;
    byte1.bit.bit8=1;
    printf("%d\n",byte1.all);
}

Bi ara gerbay MMIO'da belleğe byte byte erişilemez gibi bişey söylemişti ama konuyu bi türlü bulamıyorum.Eğer bu tarz bi olayı kastediyosan bilmiyorum.Ama o bahsedilen şey tam olarak bu değildi galiba çünkü o şekilde erişmeye çalışacan arkadaş sorun yaşadığı için öyle bi konu açmıştı.Dediğim gibi ben bunu allignment etmeden bi çok kez kullandım hiç bi sorun olmadı.Zaten burda alligment a gerek olduğunu düşünmüyorum.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: hasankara - 24 Ekim 2014, 18:48:54
bayağı gerek yok. stuct dışında da bit tipinde değişken tanımlayabilirsin (unsigned deneme;)bu şekilde. alt alta bit tanımladığında derleyici onları aynı bytedan ayarlıyor zaten. yani struct içinde bit tanımlarken de sonuna :1 diyerek bir bit olduğunu ekstradan belirtmene gerek kalmıyor.

edit sebebi: yanlış bilgi paylaşımı.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 20:28:22
Alıntı yapılan: hasankara - 24 Ekim 2014, 18:48:54
bayağı gerek yok. stuct dışında da bit tipinde değişken tanımlayabilirsin (unsigned deneme;)bu şekilde. alt alta bit tanımladığında derleyici onları aynı bytedan ayarlıyor zaten. yani struct içinde bit tanımlarken de sonuna :1 diyerek bir bit olduğunu ekstradan belirtmene gerek kalmıyor.
Bi örnek verir misin?Mesela benim yaptığım gibi 7 adet 1 bitlik değişken tanımlar mısın?
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: hasankara - 24 Ekim 2014, 20:38:56
union {
    unsigned char byte;
    struct {
        unsigned bit0;
        unsigned bit1;
        unsigned bit2;
        unsigned bit3;
        unsigned bit4;
        unsigned bit5;
        unsigned bit6;
        unsigned bit7;
    } bitler;
} deneme;
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: mufitsozen - 24 Ekim 2014, 20:53:49
Alıntı yapılan: hasankara - 24 Ekim 2014, 20:38:56
union {
    unsigned char byte;
    struct {
        unsigned bit0;
        unsigned bit1;
        unsigned bit2;
        unsigned bit3;
        unsigned bit4;
        unsigned bit5;
        unsigned bit6;
        unsigned bit7;
    } bitler;
} deneme;


Alıntı Yap#include <stdio.h>

union {
    unsigned char byte;
    struct {
        unsigned bit0;
        unsigned bit1;
        unsigned bit2;
        unsigned bit3;
        unsigned bit4;
        unsigned bit5;
        unsigned bit6;
        unsigned bit7;
    } bitler;
} deneme;

int main(){

    printf("size %d", sizeof(deneme));

    return 0;

}

sonucunu bizimle paylasirmisiniz?
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: yamak - 24 Ekim 2014, 20:55:52
Bu union'ın kaç byte kapladığını biliyo musun?
Edit:Ben yazarken mufitsozen benim soracağım soruyu sormuş.
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: Tagli - 24 Ekim 2014, 20:59:21
Ben bir tahminde bulunayım: 2 (yani 16 bit).
Başlık: Ynt: C hakkında ilginç bir problem
Gönderen: hasankara - 24 Ekim 2014, 21:22:38
(http://s14.postimg.cc/odbsoi6ql/unsigned_deneme1.jpg) (http://postimg.cc/image/odbsoi6ql/)(http://s14.postimg.cc/eequ20xb1/unsigned_deneme1_2.jpg) (http://postimg.cc/image/eequ20xb1/)(http://s14.postimg.cc/cphqtyhlp/unsigned_deneme2.jpg) (http://postimg.cc/image/cphqtyhlp/)

:( hatalıysam lütfen bu şekilde uyarın.