struct array uart ile gönderip alma işlemi nasıl yapılır ?

Başlatan ilhan_mkp, 23 Ocak 2018, 11:12:12

ilhan_mkp

struct deneme {
char a;
int b;
long c;
};
struct deneme bir[8];

main() {
......
........
}


deneme bir[4] uarttan göndermek istiyorum.
başı sonu nasıl belirlenir?
pointerler sizeof kafam karıştı.
deneme bir[x]
x ne alırsa tamamını peşpeşe uarttan göndermek istiyorum ama bir türlü beceremedim.

controller

Dizinin sadece belirli bir elemanını göndermek için,


gonder(&bir[4], sizeof(deneme));

Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

ilhan_mkp

hocam ben örnekten hiçbirşey anlamadım.
bir
  • dizisinin tamamını peş peşe göndermek istiyorum.

controller

Anladığım kadarıyla şunu arıyorsun;


struct deneme {
char a;
int b;
long c;
};

#define N 8

struct deneme bir[N];

main()
{
int i;

for (i=0; i<N; i++)
{
gonder(&bir[i], sizeof(deneme));
}
}
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

ilhan_mkp

gönder kısmını biraz açabilirmisiniz sizeof(deneme) virgül sonrası niye var.
anlayamadım.
mantığı anladım gönder kısmının açık cahile anlatır gibi anlatsanız süper olucak.

controller

gonder kısmı size kalmış. Hangi kanaldan göndermek istiyorsanız uart, spi, i2c, tcp socket vs. genelde write yada send gibi foksiyonları olur. Bu fonksiyona gönderilecek datanın pointerini ve datanın uzunluğunu verirsiniz. Virgülden sonraki sizeof(deneme) dizideki bir elemanın uzunluğu.
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

OptimusPrime

uart tan gondermeden once isaretci atadigin yapiyi bos bir baska yapiya kopyala. sonra tekar oku. en azindan kopyalama islemin veya isaretci yapin calisiyormu onu anlamis olursun. zaten bu iki yapiyi alici ve verici tarafta kullanacaksin. arada uart olmadan bir deneyip kontrol et. sonra sac bas yolarsin.
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

foseydon

sturct'ta aslında bir array'dir. Hatta, sıralı yapıların hepsi birer array olarak düşünülebilir. Struct, array vs. bunlar bizim(yani insanlar) içindir, kodu daha kolay takip edebilelim diye. işlemci için böyle birşey yoktur, onun için veriler belleğindeki kutucuklardaki sıralı 1 ve 0'lardan ibarettir. Ayrıca bunlar pointer'dır. Array dediğimiz yapı aslında yan yana dizili bellek kutucuklarından ilkinin adresini ve bu veri katarının uzunluğunu tutan bir veri yapısından başka birşey değildir. O yüzden bunları pointer olarak düşünüp ona göre işlem yapabilirsin. Bu sayede struct elemanlarını açıkça(explicit) belirtmeden sadece adres artırımı yaparak dolaylı(imlicit) olarak kullanabilirsin.

Yalnız struct için array'den farklı bir durum var. O da şu, array için içerdiği verileri yan yana koymak zorunda. yani birinci eleman 0x01 adresinde ise, ikinci eleman 0x02 adresinde olmak zorunda. Derleyici bu şekilde yerleştirir. Struct için bu zorunluluk yok bildiğim kadarı ile, yani derleyici sturct elemanlarını yerleştirirken arada atlamalar olabilir. o yüzden adresi artırarak sıradan gidersen hatalı sonuç alabilirsin. Bunun için çoğu derleyicide "packed" gibi bir directive bulunur. sturct'ını bu şekilde tanımlarsan, yan yana dizer. o zaman array gibi kullanmanda bir sorun olmaz.

ilhan_mkp

cevaplar çok açıklayıcı ve doyurucu oldu çok teşekkür edrim.
ben yazılım işi yapmadığım için konuya süper hakim değilim.
iş yerinde arkadaş konu üzerine çalışıyor ona yardımcı olmak için konu açtım.
daha önce gerbay bu konuyla ilgili bir örnek paylaşmıştı eski hartdikte o örneği stm8 için uyguladığım yarım yamalak bir kod buldum.
gerbay forumla bir sorunmu yaşadı ben ailevi sorunlar nedeniyle forumlara pek zaman ayıramadım.
ordan burdan kopyala yapıştır usulü bir denemeydi.

#include <iostm8s003k3.h>
#include <intrinsics.h>
#include <stdio.h>


#define ARRAY_SIZE(x)     (sizeof(x)/sizeof(*x))
short crc16;
unsigned char ReceiveByte;
//crc16------------------------------------------------------
unsigned short
slow_crc16(unsigned short sum, unsigned char *p, unsigned int len)
  {
    while (len--)
      {
        int i;
        unsigned char byte = *p++;


        for (i = 0; i < 8; ++i)
          {
            unsigned long osum = sum;
            sum <<= 1;
            if (byte & 0x80)
              sum |= 1 ;
            if (osum & 0x8000)
              sum ^= 0x1021;
            byte <<= 1;
          }
      }
    return sum;
  }
//bir byte gönder---------------------------------------------
void SendByte(char i)
{
  while(UART1_SR_TXE!=1);
 UART1_DR = i;
}
//string gönder----------------------------------------------
void SendString(const char *s)
{
   while(*s)
      SendByte(*s++);
}
//struct tanımla---------------------------------------------
typedef struct MyTestStruct
{
    char  a;
    char b;
    char c;
} MyTestStruct;
//struct ilk değer ver----------------------------------------
//MyTestStruct TestStruct[] = {
 //  {0x41,0x42,0x43},
  //  {0x44,0x45,0x46},
//};
MyTestStruct TestStruct[4];






//paketi uarta gönder---------------------------------------
void USART_puts( volatile char *s, int length) {
    for ( ;length > 0; length--,s++) {
     SendByte(*s);          
    }
    
}
//structın tamamını gönderme----------------------------------------
void birinciYol()
{
  char *pc = (char*) TestStruct;
  USART_puts(pc, sizeof(TestStruct)); 
}
//structı tek tek gönderme----------------------------------------
void ikinciYolStructGonder(MyTestStruct * pMyStruct)
{
  char *pc = (char*) pMyStruct;
  USART_puts( pc, sizeof(*pMyStruct)); 
}




void InitClock(void)
{
   CLK_ICKR_HSIEN = 1;
   while(!CLK_ICKR_HSIRDY);
   CLK_CKDIVR = 0x00;
}
 
void InitUART(void)
{
  UART1_BRR2  = 0x0A;
  UART1_BRR1  = 0x08;
  UART1_CR2_REN  = 1;
  UART1_CR2_TEN  = 1;
  UART1_CR2_RIEN = 1;
}
 


 
void main(void)
{
TestStruct[0].a=0x41;
TestStruct[0].b=0x42;
TestStruct[0].c=0x43;
TestStruct[1].a=0x44;
TestStruct[1].b=0x45;
TestStruct[1].c=0x46;
TestStruct[2].a=0x47;
TestStruct[2].b=0x48;
TestStruct[2].c=0x49;
TestStruct[3].a=0x50;
TestStruct[3].b=0x51;
TestStruct[3].c=0x52;




  InitClock();
  InitUART();
    int i;
    SendString("******************************");
    SendByte(13);
     SendByte(10);
     
    birinciYol(); 
     SendByte(13);
     SendByte(10);
    SendString("----------------------------");
     SendByte(13);
     SendByte(10);
    ikinciYolStructGonder(&TestStruct[0]);
     SendByte(13);
     SendByte(10);
    ikinciYolStructGonder(&TestStruct[1]);
     SendByte(13);
     SendByte(10);
     ikinciYolStructGonder(&TestStruct[2]);
     SendByte(13);
     SendByte(10);
     ikinciYolStructGonder(&TestStruct[3]);
     SendByte(13);
     SendByte(10);
    SendString("----------------------------");
     SendByte(13);
     SendByte(10);
    for (i = 0; i < ARRAY_SIZE(TestStruct); i++)
    {
      ikinciYolStructGonder(&TestStruct[i]);
   
     SendString("-- for ici --");
     SendByte(13);
     SendByte(10);
    }


    for(;;
    
    
}
 
#pragma vector=UART1_R_RXNE_vector
__interrupt void uart1_RX_ISR(void)
{
 //  ReceiveByte = UART1_DR;
  // SendByte(ReceiveByte);  
}
   

fide

Merhaba.
Struct yapısını uarttan göndermenin diğer veri tiplerini göndermekten farkı yok. Uart gönderimi için
fprintf(uart1, "%c" bir.a);


fprintf(uart1, "%u" bir.b);

fprintf(uart1, "%lu" bir.c);
Mikroişlemcide ccs c ile ben bu şekilde kullanıyorum.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

yldzelektronik

@foseydon


Alıntı yapılan: foseydon - 23 Ocak 2018, 17:51:41
...Yalnız struct için array'den farklı bir durum var. O da şu, array için içerdiği verileri yan yana koymak zorunda. yani birinci eleman 0x01 adresinde ise, ikinci eleman 0x02 adresinde olmak zorunda. Derleyici bu şekilde yerleştirir. Struct için bu zorunluluk yok bildiğim kadarı ile, yani derleyici sturct elemanlarını yerleştirirken arada atlamalar olabilir. o yüzden adresi artırarak sıradan gidersen hatalı sonuç alabilirsin. Bunun için çoğu derleyicide "packed" gibi bir directive bulunur. sturct'ını bu şekilde tanımlarsan, yan yana dizer. o zaman array gibi kullanmanda bir sorun olmaz.


Struct için de aynı zorunluluk var. Aslında o konu öyle değil. Derleyici, değişkenlerin kesin adreslerini bilmez. Yalnızca offset adresleri ile bir yere yazar ve linker adres işini halleder. Değişkenler ramde saklanacağından hepsi sıralı gider.global değişkenlerin yerleşimine baktığınızda da bunu görürsünüz.
Gelelim kırmızı kısıma. Burada bahsettiğiniz konu padding ile ilgili.Eğer struct içinde sıralı yerleşim yapılmazsa, derleyici bunları sıralı okuma şeklinde optimize eder. Bu da duruma göre değişir.Yani eğer sizin kullandığınız çip unaligne access destekliyorsa ve tek byte okuyabiliyorsa farklı davranır, desteklemiyorsa farklı davranır.Ayrıca padding yapılırken kullandığınız çipin bus witdh değeri de önemlidir. 16 bit sistem için int değeri 16 bittir. 32 bit sistem için 32 bittir.Paddingin faydası bellekten daha hızlı okuma yapmaktır. Eğer derleyicinin padding yapmasını istemezseniz sizin de bahsettiğiniz gibi packet direktifi kullanılabilir. Bu direktif derleyiciye padding yapmamasını söyler.
Yeşil kısımda bahsettiğiniz konu her zaman geçerli olmayabilir. Mesela eğer haberleşmenin her iki ucunda da aynı çip kullanılırsa ve structure aynı şekilde inşa edilirse sorun olmayacaktır. Ancak bir tarafta 32bit bir tarafta 16 bit bir sistem kullanılsa ve padding yapılması gereken bir structure oluşturulsa ve farklı boylarda padding yapılsa bu haberleşmede zaafiyet doğurabilir.


Aslında aşağıdaki sözüm hepimiz için geçerli.
Structure inşa edilirken kullanılan çipe uygun yerleşim yaptığınıza emin olunuz.Örneğin;
struct mystruct_t
{
   uint8_t a;
   uint16_t b;
   uint32_t c;
   char d;
   float e;
   uint8_t f;
   double g;
};
[\code]


Bu şekilde bir struct oluşturup bellek yerleşimini inceleyiniz.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

ilhan_mkp

int yerine rem üzerinde tam ne kadar byte yer ayıracağını bildiğimiz işlemci veri yolunun genişliğine bağlı değişen int yerine u16 gibi tercih etmek doğru olucak.