Struct & Union kullanımı

Başlatan yldzelektronik, 10 Temmuz 2013, 17:53:13

yldzelektronik

Selamlar.

Struct ve union kullanımını anlayamadım.Ccs de registerleri oluşturmak için kullanmak istedim.Sanki pişman olacak gibiyim.

typedef enum {
  I2C_ERROR_NONE = 0,
  I2C_BUS_ERROR = 1,
} I2C_ERROR;

typedef struct SSP1_STAT_reg{

   int1 SMP;       //Standart hız modu için çevrim hızı kontrolü pasif/aktif (1/0)
   int1 CKE;       //SmBus aktif etme biti.
   int1 D_A;         //Data veya Adres biti.
   int1 P;           //Stop biti.
   int1 S;           //Start biti.
   int1 R_W;         //I2C modunda okuma/yazma yapıldığının bilgisini tutar.
// Master Modda                        Slave Modda
// 1==> Veri iletimi yapılıyor.        1==>Oku
// 0==> Veri iletimi durdu.            0==>Yaz
   int1 UA;        //10bitlik I2C modunda adres güncelleme bitidir.
   int1 BF;          //Bufferın doluluk durumu hakkında bilgi tutar.
//Veri Gönderme Modunda                               Veri Alma Modunda
//1==>Veri alımı tamamlandı ve SSPBUF dolu.           1==>Gönderme yapılıyor ve SSPBUF dolu.
//0==>Veri alımı tamamlanmadı ve SSPBUF boş.          0==>Gönderme tamamlanmadı ve SSPBUF boş.
}SSP1_STAT;

struct SSP1_CON1{

   int1  WCOL;        //Yazım çakışması bitidir.Bir nevi hata kontrolü yapar.
/* Master Modunda                                                       Slave Modunda
   1==>I2C hattı iletişim için uygun olmadığı halde                     1==>Önceki paket gönderilmeden SSPBUF kaydedicisine 
   SSPxBUF kaydedicisine yazılmaya çalışılırsa çakışma                  veri yazılmaya çalışılırsa çakışma ortaya çıkar.
   ortaya çıkar.Yazılımda temizlenmelidir.                              Yazılımda temizlenmelidir.
   
   0==>Herhangi bir çakışma yoktur.                                     0==>Herhangi bir çakışma yoktur.
*/
   
   int1 SSPOV;       //Mssp modülünde alma işleminde taşmaları düzenler.
/* Alma Modunda                                    Gönderme Modunda
   1==>SSPBUF kaydedicisinde önceki veri henüz     
   işlenmemişken, yeni veri gelirse set olur.      Gönderme modunda kullanılmaz.
   Yazılımla temizlenmelidir.
   
   0==>Taşma yoktur.
*/

   int1 SSPEN;       //Mssp modülü için kontrol bitidir. 1 ise modül aktif, 0 ise pinler I/O dur.
   int1 CKP;         //SCK kontrol biti.Slave modda 1 iken serbest clock,0 iken clock low da tutulur.Master modda kullanılmaz.
   
/******Senkron Seri Port için mod seçim bitleri********/
   int1 SSPM3;    //Bit3
   int1 SSPM2;    //Bit2
   int1 SSPM1;    //Bit1
   int1 SSPM0;    //Bit0  
/*
   1111: I2C slave modu, 10 bit adres ile START ve STOP bit kesmeleri etkin.
   1110: I2C slave modu, 7 bit adres ile START ve STOP bit kesmeleri etkin.
   1011: I2C firmware kontrollü master modu.
   1000: I2C master modu, clock= Fosc/(4x(SSPADD+1))
   0111: I2C slave modu, 10 bit adres.
   0110: I2C slave modu, 7 bit adres.
Not: Belirtilmeyen bit kombinasyonları SPI iletişim için ayrılmıştır.
*/
}SSP1_CON1;

struct SSP1_CON2{

   int1 GCEN;        //Genel çağırma aktif biti.Slave modda kullanılır.
/*
   1==>SSPSR'den gelen çağırma adresi (0000h) alındığında kesme enkinleştirir.
   0==>Genel çağırma adresi pasif.
*/

   int1 ACKSTAT;     //Acknowledge (bilgi kabul edildi) durum biti.(Yalnız master gönderme modda kullanılır)
/*
   1==>Slave'den ack gelmedi.
   0==>Slave'den ack geldi.
*/
   int1 ACKEN;       //Ard arda veri almayı aktif etme biti.(Sadece master alma modda kullanılır).
/*
   1==>SDA ve SCL pinlerinden senkronizeli ard arda veri iletimi başlatılır ve ACKDT veri biti iletilir.Bu bit donanım tarafından otomatik temizlenir.
   0==>Acknowledge boşta.
*/
   int1 RCEN;        //Veri almayı aktif etme biti (Sadece master modda).
/*
   1==>I2C için veri alma biti aktif.
   0==>I2C için veri alma boşta.
*/
   int1 PEN;         //STOP durumunu aktif etme biti (Sadece master modda).
/*
   1==>SDA ve SCL pinleri STOP durumunu başlatır.STOP biti gönderildiğinde donanım tarafından otomatik olarak temizlenir.
   0==>STOP durumu boşta.
*/
   int1 RSEN;        //I2C modda START durumunu tekrarlama bitidir (Sadece master modda).
/*
   1==>SDA ve SCL pinleri START durumunu tekrarlar.Donanım tarafından otomatik olarak sıfırlanır.
   0==>START durumu pasif.
*/
   int1 SEN;         //I2C START durum biti.
/* Master Modda                                       Slave Modda
   1==>SDA ve SCL pinleri STOP durumunu başlatır.     1==>Slave gönderme ve slave alma modlarında,
   START biti gönderildiğinde donanım tarafından      clock uzatılması etkinleştirilir.
   otomatik sıfırlanır.
   0==>START durumu boşta.                            0==>Yanlızca slave gönderme modunda clock uzatılması etkinleştirilir.
*/
}SSP1_CON2;

struct SSP1CON3{

   int1 ACKTIM;

}SSP1CON3;

#define SSP1_STAT  0x214
#define SSP1_CON1  0x215
#define SSP1_CON2  0x216


Şeklinde header dosyamda tanımlamaları yaptım. .c dosyamda bu yapılardan birini kullanmak istediğimde hata alıyorum.

1^SSP1_STAT SSP1_STATt ;

void i2c_init(){

   SSP1_STATt=0;
   
   SSP1_STATt.SMP=1;
   
   

}


1^satırında expecting declaration hatası alıyorum.

Bu yapıların kullanımını açıklayabilir misiniz?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

yldzelektronik

Yapı ile daha önce çalışan olmadı mı?Konuyla ilgili kimsenin yorumu yok mu?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

Klein

#2
1^ ? nedir?
CCS'da bazı tanımlamalar biraz farklı. O yüzden CCS için bir şey diyemem.
Genel C typedef tanımı  aşağıda. İşini görürse böyle bir dene.   

typedef struct {

   int1 SMP;       //Standart hız modu için çevrim hızı kontrolü pasif/aktif (1/0)
   int1 CKE;       //SmBus aktif etme biti.
   int1 D_A;         //Data veya Adres biti.
   int1 P;           //Stop biti.
   int1 S;           //Start biti.
   int1 R_W;         //I2C modunda okuma/yazma yapıldığının bilgisini tutar.
// Master Modda                        Slave Modda
// 1==> Veri iletimi yapılıyor.        1==>Oku
// 0==> Veri iletimi durdu.            0==>Yaz
   int1 UA;        //10bitlik I2C modunda adres güncelleme bitidir.
   int1 BF;          //Bufferın doluluk durumu hakkında bilgi tutar.
//Veri Gönderme Modunda                               Veri Alma Modunda
//1==>Veri alımı tamamlandı ve SSPBUF dolu.           1==>Gönderme yapılıyor ve SSPBUF dolu.
//0==>Veri alımı tamamlanmadı ve SSPBUF boş.          0==>Gönderme tamamlanmadı ve SSPBUF boş.
}SSP1_STAT;


SSP1_STAT SSP1_STATt ;

yldzelektronik

Alıntı yapılan: Klein - 11 Temmuz 2013, 00:17:44
1^ ? nedir?


O kısımı sadece o satırı kastettiğimi göstermek için ekledim kodda yok yani.Bir sürü kitabı ve notları inceledim.Ccs nin helpine de baktım.Gösterdiği şekilde kullanıyorum ama olmuyor.Yapılardan biraz bahsedebilir misiniz?Tanımladığım bir yapıya başka bir fonksiyon içinde değer veremez miyim?Tek seferde yapının bütün elemanlarına değer veremez miyim?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

Klein

typedef struct SSP1_STAT_reg{

Eğer typedef kullanmadan doğrudan struct değişken yaraıyorsanız bu şekilde kullanılır ve değişkeninizin adı bu olur.
Eğer typedef ile yeni bir tip tanımlıyorsanız tipin adı  tip tanımının sonunda olur. Bazı derleyiciler belki bu şekilde bir tanımlamaya müsade ediyordur. ama yaygın ullanım anlattığım gibi.

SSP1_STATt=0;
Bir yapıya bu şekilde değer veremezsiniz. Ancak "SSP1_STATt" bir işaretçi olsaydı o zaman ancak adres değeri verebilirdiniz.

Program içerisinde yapının istediğiniz elemanına değer verebilirsiniz. Ama yapının tüm elemanlarına tek seferde değer vermeyi ancak değişkeni tanımladığınız anda yaparsınız. Yapılabiliyorsa da ben bilmiyorum.

typedef struct
{
   int a;
  int b;
  char *c;
}struct_type;

struct type x ={5, 155, {"Struct ilk deger"}};

hasankara

yazım kolaylığı elde edebilmek için unsigned char şeklinde tanımladığım 8 bit lik değişkenin, hem tümüne birden hükmedebilmek hemde içerisindeki özel bitlerine ayrekten hükmedebilmek için bu yapıyı kullanmak istemiştim. ancak dediğiniz gibi
Alıntı Yapyapının tüm elemanlarına tek seferde değer verme
şeklinde kullanamayınca kullanmaktan vazgeçtim.

örnek olarak
if((buff&0b10000000)>0) db7=1; else db7=0;
dediğim zaman
  0730    1F7D     BTFSS buff, 0x7
  0731    2F34     GOTO 0x734
  0732    170E     BSF PORTC, 0x7
  0733    2F35     GOTO 0x735
  0734    130E     BCF PORTC, 0x7
şeklinde dönüşüm yaptığını gördüm.

yazım kolaylığı açısından bu yapıyı bu şekilde kullanabileceğimiz konusunda fikri olan var mıdır acaba?

Klein

typedef  union
{
      int all;
      struct{
         int b0 :1;
         int b1 :1;
         int b2 :1;
         int b3 :1;
         int b4 :1;
         ..
         ..
         int b15 :1;
      }
}bittype;

bittype  degisken;

degisken.all = 0xf00A;

degisken.b0 = 0;
degisken.b1 = 1;

db7 = degisken.b7;

mufitsozen

Alıntı Yapif((buff&0b10000000)>0) db7=1; else db7=0;

yerine bir conditional operator kullanabilirsiniz.

     db7 = (buff&0b10000000)>0 ? 1 :  0;
     db7 = buff & 0b10000000) ? 1 :  0;
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

hasankara

şimdi bunları deneyeceğim teşekkür ederim ilginiz için.

hasankara

tanımlamayı bu şekilde yaptım;
typedef  union
{
      unsigned char all;
      struct{
        unsigned b0 :1;
		unsigned b1 :1;
		unsigned b2 :1;
		unsigned b3 :1;
		unsigned b4 :1;
		unsigned b5 :1;
		unsigned b6 :1;
		unsigned b7 :1;
      };
}bittype;

değişkeni bu şekilde tanımladım;
bittype buff;


ve  yazdığım komut bu iken;
   db7=buff.b7;


aldığımız assembly dönüşümü;
  0596    0D74     RLF __lldiv@dividend, W
  0597    0D74     RLF __lldiv@dividend, W
  0598    3901     ANDLW 0x1
  0599    00F1     MOVWF disp_yansit@i
  059A    0C71     RRF disp_yansit@i, W
  059B    1C03     BTFSS STATUS, 0
  059C    2DA0     GOTO 0x5a0
  059D    0020     MOVLB 0
  059E    148D     BSF PORTB, 0x1
  059F    2DA2     GOTO 0x5a2
  05A0    0020     MOVLB 0
  05A1    108D     BCF PORTB, 0x1
  şeklinde :D ve çalışıyor.

sanırım hi-tech bu noktada yeteri kadar pratik düşünemiyor. ben bu uygulamada bunu kullanmayacağım ancak bu yazım şekli olabildiğince esnek olduğundan başka bir yerlerde kullanabilirim. en azından böyle bir kullanımının olduğunu öğrendik.

@mufitsozen hocamızın önerisinde ise

db7 = (buff&0b10000000) ? 1 :0;
komutu ile
56:  
  0296    1FD9     BTFSS veri_yolla@buff, 0x7
  0297    2A9B     GOTO 0x29b
  0298    0020     MOVLB 0
  0299    148D     BSF PORTB, 0x1
  029A    2A9D     GOTO 0x29d
  029B    0020     MOVLB 0
  029C    108D     BCF PORTB, 0x1
şeklinde bir dönüşüm aldım. movlb 0 komutu hangi amaçla yerleştirdiğini anlamasamda conditional operator kullanışlı olduğundan dolayı bu şekilde kullanmayı tercih edeceğim.

tekrar teşekkür ederim.

mufitsozen

movlb 0 komutu banked variable erisimi yapilmasindan once compiler tarafindan konulan bir komut. Normalde optimizerin bunun var oldugunu bilip extradan (ikinci, ucunculeri vb) kaldirmasi lazim. Fakat pratikde inline fonksiyonlar gibi durumlarda compilerin kafasi karisiyor ve isi saglama almak icin bu fazlalik komutlari ekliyor.

bu durum birazda compilera bagli yani.

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

M_B

Altaki gibi tanımlama yapamıyormuyuz.

typedef  union
{
      int all;
      struct{
         int b0 :7;
         int b1 :7;
         int b2 :7;
         int b3 :7;
         int b4 :4;
        };
}bittype;

bittype  degisken;


Verdiği hata:
number of bits is out of range
Expecting a; or,
Expecting Declaration

Ama şu şekilde yaparsam hata vermiyor.
Bu seferde o benim işime gelmiyor.
typedef  union
{
      int all;
      struct{
         int b0 :7;
         int b1 :1;
         int b2 :7;
         int b3 :1;
         int b4 :4;
        };
}bittype;


İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

M_B

HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode)  V9.83
                            ve
mikroC Pro for Pic v.6.00 derleyicileri
typedef  union
              {
              int all;
              struct {
                      unsigned  b0 :7;
                      unsigned  b1 :7;
                      unsigned  b2 :7;
                      unsigned  b3 :7;
               	      unsigned  b4 :4;
                      };
             }bittype;

Bu nu normal sekılde derliyor.
Ama  CCS C 5.008 versiyonu derleme yapmıyor. :(
Neden !!!!
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

yamak

Hocam bazı derleyicilerde union ın içindeki struct'a isim vermek gerekiyo bir de isim vererek dener misiniz?

M_B

Alıntı yapılan: yamak - 25 Temmuz 2013, 14:49:36
Hocam bazı derleyicilerde union ın içindeki struct'a isim vermek gerekiyo bir de isim vererek dener misiniz?
malesef o sekılde de olmuyor.
Anladıgım kadarıyla derleyici 16 biti gecmek istemiyor.
şu şekilde yapınca kızmıyor
typedef  union
{
      int all;
      struct{
         int b0 :7;
         int b1 :1;
         int b2 :7;
         int b3 :1;
         int b4 :4;
        };
}bittype;
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet