Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => ARM => Konuyu başlatan: kimlenbu - 04 Haziran 2014, 17:06:18

Başlık: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 04 Haziran 2014, 17:06:18
Selamlar,

İki adet STM32F407 arasında seri olarak veri alışverişi olması gerekiyor. Veriler iki işlemcide de struct tipinde.

typedef struct MyTestStruct
{
uint8_t  a;
uint16_t b;
uint32_t c
}MyTestStruct;

MyTestStruct TestStruct[] = {
{0xAA,0xBBBB,0xCCCCCCCC},
{0x2A,0x2BBB,0x2CCCCCCC},
};


USART veri gönderme fonksiyonum şu şekilde :

void USART_puts(USART_TypeDef* USARTx, volatile char *s){

while(*s){
// wait until data register is empty
while( !(USARTx->SR & 0x00000040) );
USART_SendData(USARTx, *s);
*s++;
}
}


Bu struct'ı tek seferde gönderme şansım var mı ? Araştırdığımda "Type Casting" önermişler, aşağıdaki şekilde denedim çalışmadı.

Struct içinden bir değişken göndermeyi denedim olmadı :

USART_puts(USART6, (uint8_t *) TestStruct[0].a );

Struct'ı göndermeyi denedim olmadı :

USART_puts(USART6, (uint8_t *) TestStruct );


Bu struct'ı usart üzerinden tek seferde nasıl göndeririz ? (iki tarftaki işlemci de aynı, derleyici de aynı)

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 04 Haziran 2014, 17:36:51
C pointer ile çalışırken biraz tutucudur.  işaretinin gösterdiği büyüklük aynı bile olsa  , birebir tip uyumu ister. Bu sebeple casting yaparız. 
eğer USART_Puts(..) fonksiyonu 
veri işaretçisi olarak "*char " parametre alıyorsa,  casting şu şekilde olmalı   "(char *) mystruct"
eğer *uint8_t   şeklinde parametre alıyorsa yaptığınız casting doğru. Hata vermemelidir.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 04 Haziran 2014, 17:45:13
Hata vermiyor, derleniyor ama veriler hatalı gönderiliyor (PC'de kontrol ediyorum)

Bu şekilde gönderiyorum :

USART_puts(USART6, (volatile char *) TestStruct );

Karşı tarafa şu şekilde ulaşıyor :

47 6F 6E 64 65 72 69 79 6F 6D AA


Düzeltme : Pardon verilerde hata var, veri göndermeden önce "Gonderiyom" mesaji gidiyordu, onun hex değerleriymiş :)

aslında AA gönderiyormuş sadece

G47 o6F n6E d64 e65 r72 i69 y79 o6F m6D  AA 

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 04 Haziran 2014, 18:33:49

typedef volatile struct  __attribute__ ((__packed__))
{
struct{
TBroadCastRegisters BroadCastRegisters; // 10
TSTSRegisters StsRegisters; // 6
Alarmflags_TypeDef ActiveAlarms; // 2
Alarmflags_TypeDef AlarmHistory; // 2
uint16_t Reserve[2];
Param_TypeDef Params;// 78
TFunctions Function; //2
int16_t Anin[4];//16
int16_t AdcRaw[4];//16
int16_t Adc[4];//16

};
}IOMap_Typedef; // 120



Paketleme  GCC'de böyle. Keil kullanıyorsan farklı olabilir. 
Ayrıca  structların boyunu mümkün olduğunca 32 bitin katlarına denk getirirsen iyi olur.

Neden paketlemen gerekiyor?
CPU 32 bit.  Eğer struct paketlenmemişse derleyici  değişkenleri yerleştirirken  adresleri 32 bitin katları olacak şeklide yerleştirir.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 04 Haziran 2014, 18:53:48
Sağolun cevaplar için, ekipmanlar iş yerinde yarın ilk iş deneyip yazarım sonucu. "packed" olayını bilmiyordum ne yalan söyleyeyim.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: CLR - 04 Haziran 2014, 19:50:08
Keil'de struct için __packed keywordu yeterli.

Blok olarak packed yapacaksan

#pragma pack(push, x)  ve #pragma pack(pop) kullanabilirsin. Burada x byte sayısıdır mesela 1 ise __packed ile aynı.



typedef __packed struct{
u8 LcdCmdFlag;
u16 LcdCmd;
u32 LcdCmdTimeout;
}LcdCmdRegs_Typedef;

#pragma pack(push, 1) 

typedef struct...

typedef struct...

typedef struct...

#pragma pack(pop)



Ayrıca yerinde olsam bu şekilde interface yapmazdım. Struct'ları packed tanımladıktan sonra , usart RX ve TX DMA'ya ilgili structların'ın start adreslerini girerdim hem herşeyi dma yapardı hemde gelen veya giden struct registerlerin otomatik update olur. Mesela peryodik flag tanımlayabilirsin, flag set olunca dma gönderir, diğeride alır gibi.

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 05 Haziran 2014, 10:09:08
Struct'ı "packed" yapınca düzeldi :) ekstra bytelar'da gönderiyor ve byte sıralamalarına dikkat etmem gerekiyor ama usart kodlarımı düzenlerim ona göre.

AA BB BB CC CC CC CC 2A BB 2B CC CC CC 2C


@CLR hocam, öneriniz için teşekkür ederim. "kara düzen" bi çalıştırayım, DMA'yı süsleme kısmında hallederim :)
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 05 Haziran 2014, 12:11:46
Konunun biraz dışında ama böyle bir struct'u gönderirken paket başı sonunu nasıl tespit ediyorsunuz, bu sorun olmuyor mu?
Paket içinde null dahil 0...255 aralığındaki tüm değerlerin olma ihtimali var.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 05 Haziran 2014, 12:27:45
Alıntı yapılan: Elektroemre - 05 Haziran 2014, 12:11:46
Konunun biraz dışında ama böyle bir struct'u gönderirken paket başı sonunu nasıl tespit ediyorsunuz, bu sorun olmuyor mu?
Paket içinde null dahil 0...255 aralığındaki tüm değerlerin olma ihtimali var.

"$Gonderiyom" ile baslayip "$Bitti" ile sonlandiriyorum :) eger bu kadar karakterin arka arka gelecegi tutarsa da gidip bi sayisal oynarim :)
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 05 Haziran 2014, 12:33:59
Haha  :D Yinede benim içime sinmiyor hocam. Profesyonel uygulamlarda da bu şekilde mi?
Kendi uygulamalarımda '$' karakteri ile başlayıp sonra tün dataları ascii'ye dönüştürüp gönderiyorum. Haliyle özellik sayılarda baya bir hız kaybı yaşanıyor.
Sayıları hexdecimal gönderince normalin 2 katı (1byte için 2 ascii karakter) band genişliği harcıyorum. en sonda \n ile bitiriyorum.
Uygulamayı terminalden elle test etmekte kolaylaşıyor ama dediğim gibi fazla band genişliği harcıyorum.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 05 Haziran 2014, 12:54:15
Paket sonunda 1-2Byte  boşluk verirseniz, karşı taraf bunun paket sonu olduğunu anlar. Binary haberleşen bir  çok ( hatta benim gördüklerimin tamamı) ve kendi kullandığım yöntem bu.
Modbus RTu böyle çalışır. 3Byte boşluk paket sonu kabul ediir.

Eğer paket içeriğinde kaç byte veri göndereceğinizi belirttiyseniz ve de CRC ,LRC benzeri bir kontrol mekanizmanız varsa , sonlandırma olmadan da paketi işleyebilirsiniz. Ancak tek başına önermem.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 05 Haziran 2014, 13:50:32
Alıntı yapılan: gerbay - 05 Haziran 2014, 13:29:52
bu işler için uygulanması gereken yöntem structure göndermek. structure içine gerekli senkronizasyon alanlarını ve ortamına göre gerekiyorsa checksum ı vs. koyup göndermek.

ben normal tam sayılar dışında float, double da gönderdim. çok gönderenini de gördüm. çok gönderen derken Türkiye anlamında değil.

LN270 - INS,  bu zımbırtının protocol struct ında tam sayı da var, float da var, double da var.

stucture gönderin/alın.. doğru yöntem bu..
Türkiye'de neden olmasın hocam. Yıllardır struct gönderirim.  Modbus çalışırken de , Kendi protokolümle de. Bence çok kişi vardır bu şekilde çalışan.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 05 Haziran 2014, 13:53:24
Hocam UART ile 3.5 byte süresini tespit edip frameleri ayrıştırma olayı açıkçası sıkıntılı olur.

Bu bahsettiğiniz senkronizasyon byte'ları ve sonrasında gelen 0 değerleri, gönderdiğiniz içerikle tesadüf olarak denk gelince ne yapılıyor?

Sistem gelen data buffer'ında senkronizasyon byte'larını arıyor,
daha sonra senkronizasyon byte'ından sonraki diğer parametrelere bakıp değerler tutarlıysa "tamam abi burası paketin başı" kararı veriyor,
yok tutarlı değilse "paketin başı zannettik ama değilmiş normal data galiba" deyip diğer senkronizasyon byte'larını aramaya devam ediyor.

Durum bu mudur hocam?
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: muhittin_kaplan - 05 Haziran 2014, 14:28:06
Konu Güzel. yeni bir öğrenme Kaynağı,
Hocam Kullandığım Yöntemden bahsedeyim
bilgileri sprintf ile bir katar yapıp usart tan yolluyorum. tabiki ardına CR LF ekliyorum.

bu struct göndermek arasında ne gibi bir iyilik/kötülük oluşturur ? Sonuçta usart ByteByte Göndermeyecek mi ?
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: muhittin_kaplan - 05 Haziran 2014, 14:41:06
Siz Anltın ben Öğrneym Hcam Yntemi mmknse.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: muhittin_kaplan - 05 Haziran 2014, 14:50:09
baktım hocam  Sağolun.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kantirici - 05 Haziran 2014, 15:25:10
Alıntı yapılan: gerbay - 05 Haziran 2014, 14:33:21
hocam onu float ve double için yazdım, eğer struct a float, double da koyup gönderdiyseniz size ancak "bravo!" diyebilirim.

Hocam şimdi kafam karıştı. Struct içinde float tanımlayıp uarttan gönderelim mi göndermeyelim mi?


Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 05 Haziran 2014, 15:29:43
O zaman kendimizce uart için basit bir paket yapısı oluşturalım:

typedef struct
{
    /**  Header  **/
    uint32_t Sync;         // Mesela 0x55AA0000 olabilir
    uint16_t PayloadLen;   // 0..65535
    uint16_t HeaderCrc16;  // Header icin Crc
   
    /** Esas Data **/
    uint8_t* Payload;      // Esas Data
    uint16_t PayloadCrc16; // Esas Data icin Crc
   
}UartPack_t;


Bu struct konunun başında konuşulan esas data struct'ı değil. Esas göndermek istediğimiz data katarı ya da struct'ı bu struct içersindeki payload pointer'ına type cast yapıp bildireceğiz.

Sonra Packet gönderme ve alma rutinleri yukarıdaki bu struct ile çalışacak ve payload'ın doğru şelkilde paket senkronizasyonu yapılarak gönderilip alındığını garanti edecek. Payloadın içeriği herhangi bir şey olabilir 'şu karaketeri kullanmak yasak' gibi bir şey söz konusu değil. Senaryo böyle olsun.

Bizde "Alt katmanda neler oluyor?" , "Paketin başını sonunu doğru kestirdik mi?" gibi sıkıntılar yaşamadan üst katmanlarda uygulamamızı yazalım.

Mesela CAN'de ya da USB HID'de paket gönderip paket alıyoruz. Gerisi bizi hiç mi hiç ilgilendirmiyor. UART'tada benzer rahatlığı yaşayabileceğimiz hale getirmemiz çok güzel olur.

Vaktim oldukça yazmaya çalışacağım.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Tagli - 05 Haziran 2014, 18:04:31
Bence olayı 9 bitlik veri paketleri ile çözmek daha rahat olur. Böylece paket başları net bir şekilde belirlenir. ARM'ı bilmiyorum ama seri port modülü olan tüm PIC'lerde 9 bit ve "address detect" özelliği var. Etkinleştirildiğinde, 9. biti 1 olmayan tüm veriler yok sayılıyor. Bus üzerinde birden fazla slave cihaz olan uygulamalarda çok mantıklı.

9. bitte bozulma olursa işler karışır gerçi, onun da önlemini almak lazım.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: AsHeS - 05 Haziran 2014, 19:31:55
Konuşulanlara ek olarak şöyle bir yöntemde olabilir paketin başına STX , sonuna EOT karakteri koyacağımızı varsayalım. Sorun şu paketin içinde bunlar varsa ne olacak onu da şöyle aşalım ESC karakterini remap karakteri olarak belirleyelim ve mesajın içindekileri yenileri ile remap edelim.
Diyelim
struct __packed msg_packet_s
{
      uint32_t  mp_fly_me;
      uint16_t  mp_fly_high;
      uint8_t    mp_fly_more;
};

struct msg_packet_s msg_packet;

msg_packet.mp_fly_me = STX;
msg_packet.mp_fly_high = EOT;
msg_packet.mp_fly_more = ESC;


mesajlarını taşısın gönderilecek mesajın başı sonu şöyle olacaktır.
STX (0x00 0x00 0x00 ESC 0x01)  (0x00 ESC 0x02) (ESC 0x03)  EOT
Tabi hem verici hem alıcı tarafta mesaj çıkışından ve alışından önce pre_process mekanizması olmalıdır.
Ayrıca worst case durumu olan bütün mesajın bu karakterlerden oluşması durumu için çıkış bufferının boyutunu struct'ın 2 katı seçmekte yarar var.  uint8_t out_buff[2*sizeof(struct msg_packet_s) +2]

Edit: Mesajın içine checksum da konulabilir ama dikkat çekmek istediğim nokta paket içeriği değil dışarıya çıkış şeklidir.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 05 Haziran 2014, 19:40:49
Alıntı yapılan: Elektroemre - 05 Haziran 2014, 13:53:24
Hocam UART ile 3.5 byte süresini tespit edip frameleri ayrıştırma olayı açıkçası sıkıntılı olur.

Bu bahsettiğiniz senkronizasyon byte'ları ve sonrasında gelen 0 değerleri, gönderdiğiniz içerikle tesadüf olarak denk gelince ne yapılıyor?

Sistem gelen data buffer'ında senkronizasyon byte'larını arıyor,
daha sonra senkronizasyon byte'ından sonraki diğer parametrelere bakıp değerler tutarlıysa "tamam abi burası paketin başı" kararı veriyor,
yok tutarlı değilse "paketin başı zannettik ama değilmiş normal data galiba" deyip diğer senkronizasyon byte'larını aramaya devam ediyor.

Durum bu mudur hocam?
Yok tam öyle değil.  3.5 byte  senkronizasyon baytı değil.  sadece bekleme.  eğer 3 byte boynca veri gelmiyorsa, paket alınmıştır. bu kadar.  Eğer 3.5 byte beklemeden sonra veri alınmışsa bu yeni paketin verisidir. 
Ama bu yöntem Master-Slave çalışmaya daha uygun bir yöntem.   
Modbus-RTU kullanan Her yeni cihazımda bir kaç gün süren haberleşme testi yaparım. Haberleşme testi yapılırken cihazın diğer fonksiyonları da çalışır durumda olur. Menülere girer çıkarım, input output fonksiyonlarını test ederim.
Test şartları genellikle şöyledir.
Baud 256000
Data bit 8
parite yok
stop bit 1
master 10 byte paket gönderip slave cihazdan 250 byte uzunluğında bir paket ister.
Slave paketi gönerir. Paket içeriğinde her türden  canlı veri ve sabit veri bulunur. 
Eğer  paket doğru alınmışsa   başarı sayacı bir artar,  CRC hatası, paket boyu  hatası , zaman aşımı hatası  ve benzeri hata durumlarında  hata sayıcısı bir artar.
cevap paketinden sonra 10ms beklerim ve yeni sorguyu gönderirim. 

Bu şekilde  bir kaç gün test ederim.  Eğer  şebeke gürültüsü konusunda cihazı  zorlamazsam ,  hata sayıcısının arttığını hiç görmedim. 
Eğer çok vahşi gürültü testleri yaparsam ,  40-50 bin pakette bir hatalı paket aldığım olur. Bunu normal sayarım.
Ama bu vahşi test bazen işlemciyi uçurmaya  kadar gider. Hatta bilgisayarın USB, Bluetooth gibi aygıtları bile uçar.

Ama uygulama , bu şartlar altında bile bu hatayı kaldıramayacak bir hata olursa o zaman bu yöntemin sıkıntılı olduğundan bahsedebiliriz.
Belki de bu hata bile yöntemden değil , benim donanımda veya yazılımda yaptığım hatalardan kaynaklanıyordur.


mesaj birleştirme:: 05 Haziran 2014, 20:11:39

Alıntı yapılan: muhittin_kaplan - 05 Haziran 2014, 14:28:06
Konu Güzel. yeni bir öğrenme Kaynağı,
Hocam Kullandığım Yöntemden bahsedeyim
bilgileri sprintf ile bir katar yapıp usart tan yolluyorum. tabiki ardına CR LF ekliyorum.

bu struct göndermek arasında ne gibi bir iyilik/kötülük oluşturur ? Sonuçta usart ByteByte Göndermeyecek mi ?
Evet sonuta byte byte gönderecek. ama Structların esas gücü faklı veri tiplerini kullanabiliyor olmanda  yatıyor.
diyelim ki
Standart bir tx arrayın var.   göndermen ve alman gereken bir çok tipte    verin var.
örneğin

float offset;
float span;
unsigned long int  counter;
char name[16];
float  AnalogValue;
unsigned int DeviceCount;
unsigned int aaaaaaaaaa;


şimdi sana bunları  seri porttan gönder ve karşı tarafta da birleştir desem, struct kullanmadan nasıl yaparsın?

Ben sana struct ile nasıl yapılacağını göstereyim , sen bana struct kullanmadan nasıl yapılacağını.


typedef struct
{
      float offset;
      float span;
      unsigned long int  counter;
      char name[16];
      float  AnalogValue;
      unsigned int DeviceCount;
      unsigned int aaaaaaaaaa;
}TValues;

TValues  values;
/* gönderme */
Gönder( (char *) values, sizeof(values));

/* alma */
char *rxbuffer = values;
al( rxbuffer);


Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 05 Haziran 2014, 22:19:04
@gerbay hocam,

O struct data struct'ı değil, bizim paket gönderme alma alt fonksiyonları ile çalışmak için tanımladığımız struct.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: muhittin_kaplan - 05 Haziran 2014, 22:22:55
@Klein
Hocam


sprintf(str,"GX%dGY%dGZ%dAX%dAY%dAZ%dS\r\n",GyrX,GyrY,GyrZ,AccX,AccY,AccZ);
USART_puts(USART2,str);


ile PC ye gönderir
Oradada STRING MANIPULATION la ayırırım.
(GX ile GY arasına Al Şuraya At
GY ile GZ arasını al Buraya At gibi
)

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 05 Haziran 2014, 22:24:04
Hocam basit örnek olsun diye hiç bir şey koymadım. Farklı veri türleri olması yeterliydi.
Genellikle  Modbus-RTU kullanıyorum.  İlla ki özel bir protokol kullanmam gerekirse ( ki çook nadir) ,  Teslimat bilgileri, paket içeriğine ilişkin bilgiler  ve paket sıra numarası gibi alanlar bulunuyor. Çok nadiren de zaman senkronizasyonu yaptığım oluyor. 
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 05 Haziran 2014, 22:54:00
Alıntı yapılan: muhittin_kaplan - 05 Haziran 2014, 22:22:55
@Klein
Hocam


sprintf(str,"GX%dGY%dGZ%dAX%dAY%dAZ%dS\r\n",GyrX,GyrY,GyrZ,AccX,AccY,AccZ);
USART_puts(USART2,str);


ile PC ye gönderir
Oradada STRING MANIPULATION la ayırırım.
(GX ile GY arasına Al Şuraya At
GY ile GZ arasını al Buraya At gibi
)



:) Bir ayır bakalım.
Zaten olamayacağını iddia ettiğm için değil , ortaya çıkan kodla , Struct kullanılan kod arasındaki farka bakıp ,  neden Struct kullanmalıyız sorusunun cevabını görmen için istedim.
Ha bu işin daha başlangıcı. bazen 250 baytlık  paket gönderdiğim oluyor. Bunu işini zorlaştırmak için söylemiyorum.

Tabi yapıları  sadece haberleşmeyle sınırlandırma.  Kodunu daha okunaklu yapması , değişkenleri guruplandırabilme, aynı tip yapıyı bir çok kere kullanabilme , casting ile her türlü diziye atabilme gibi bir çok avantajı var.
Hatta mümkün olduğunca global değişkenlerinin tümünü eşitli yapılar içerisinde guruplandır.
Hatta yapıyı buradaki gibi diziye çevirip bir yere transfer etmeyeceksen,  bazı durumda fonksiyon işaretçileri kullanarak , structuna özel fonksiyon çağrısı yapabilirsin. Velhasıl Pointer ve Struct olmadan C nin tadı ıkmaz.

İşin  başka bir ayrıntısı da  yapı (Struct) ile sınıfların (Class)  benzerliği. Eğer Yapıları iyi anlar ve iyi kullanabilirsen , C++ için çok iyi bir başlangıç yapmış olursun.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: muhittin_kaplan - 05 Haziran 2014, 23:41:06
Hocam, PC de ufak değerlerde pek fark yaratmıyor. Yoğun Veri trafiğinde tek seferde parse edilebilecekken yoğun bir String ayırma işlemiyle uğraşılır. Haliyle PC yi yorar, MCU yu düşenemiyorum bile.

mesaj birleştirme:: 05 Haziran 2014, 23:46:03

Alıntı yapılan: gerbay - 05 Haziran 2014, 22:44:09
muhittin hocam,

sen de kızılderililer gibi duman  ile haberleşiyormuşsun ;)

Daha Nelerle Haberleştiğimi Görseniz.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: mufitsozen - 06 Haziran 2014, 10:59:36
Arkadaslar dayanamadim araya girecegim,  kusura bakmayin.

Desturrr!!!!.... Yine okumaniz icin bir referans verecegim. ;D kufur yok, kotu soz yok... :P

UART uzerinden frame olarak bilgi gondermek icin sultan palamut devrinden beri byte stuffing kullanilir(di, 7E ve 2D xor filan falan) ama bununda bazi dezavantajlari vardi. Yakin zamanda gelistirilen bir algorithma ile bu sorunlar cozuldu.

Sayin @klein, @muhittin_arslan ve sevgili @gerbay bazilari akil yasta degil bastadir dersede bazen akil hem yasta hemde bastadir cunki yasli olanlar ayni zamanda baslida olabilir  :P

bu konuya caktirmadan okuyup ne oldugunu anlamaya calisan arkadaslar C bilginiz yeteri kadar iyi ise sizde sayin @klein, @muhittin_arslan ve sevgili @gerbay gibi cok bilgili ve tecrubeli arkadaslara birseyler  soyleme/gosterme firsatiniz var fekaaattt elinizi cabuk tutun bu @gerbay denilen canavar simdi hemen bu konuyu arastirip 8 mcuda 4 degisik compiler ile derleyip, assemblerli cross listingi uzerinden performans analizi bile yapar! demedi demeyin.. ;)

Alıntı YapFraming packets transmitted on a UART serial link (such as RS-232 or RS-485) is a common problem in embedded programming. The typical approach is to put framing characters at the beginning and end of the packet. If a framing character occurs in the packet, it is escaped using a technique called byte stuffing. This sucks for a few reasons, but there's a better way. The recently developed algorithm called (cikartim, bu makaleyi okuyun hazira konmayin  :P ) is a great solution that should be in every embedded software engineer's toolbox.

First, a bit of background. I'm working on a project where I have to transmit data between two microcontrollers using RS-422. RS-422 is a differential signalling standard that is often used in place of RS-232 to connect two UARTs when electrical isolation and/or noise immunity are required.

The question came up, how do we assemble packets on the transmitter and detect packet boundaries on he receiver? (devami asagidaki linkte, tabii googledan bulabileceginiz yaklasik 20,000 referansida okuyabilirisiniz. wikipediayi soylemiyorum bile...)

Yani uzun sozun kisasi COBS diyorum!

http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing/ (http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing/)


Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Elektroemre - 06 Haziran 2014, 11:27:09
@mufitsozen hocam gerçekten güzel algoritmaymış teşekkürler. Birde buna CRC ekledik mi tadından yenmeyecek :)
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kantirici - 06 Haziran 2014, 16:35:20
@mufitsozen hocam teşekkürler.


Algoritma ile ilgli http://stuartcheshire.org/papers/COBSforSIGCOMM/ (http://stuartcheshire.org/papers/COBSforSIGCOMM/) buradaki sayfanın en sonunda verilen kodları şunlar;

Source Code Listings

/*
* StuffData byte stuffs "length" bytes of
* data at the location pointed to by "ptr",
* writing the output to the location pointed
* to by "dst".
*/

#define FinishBlock(X) \
    (*code_ptr = (X),  \
    code_ptr = dst++,  \
    code = 0x01)

void StuffData(const unsigned char *ptr,
unsigned long length, unsigned char *dst)
    {
    const unsigned char *end = ptr + length;
    unsigned char *code_ptr = dst++;
    unsigned char code = 0x01;

    while (ptr < end)
        {
if (*ptr == 0) FinishBlock(code);
else
    {
    *dst++ = *ptr;
    code++;
    if (code == 0xFF) FinishBlock(code);
    }
ptr++;
}
    FinishBlock(code);
    }
Listing 1. COBS Encoding in C

/*
* UnStuffData decodes "length" bytes of
* data at the location pointed to by "ptr",
* writing the output to the location pointed
* to by "dst".
*/

void UnStuffData(const unsigned char *ptr,
unsigned long length, unsigned char *dst)
    {
    const unsigned char *end = ptr + length;
    while (ptr < end)
{
int i, code = *ptr++;
for (i=1; i<code; i++) *dst++ = *ptr++;
if (code < 0xFF) *dst++ = 0;
}
    }


Burada veri olarak  char hamveri[10]={10,9,8,7,6,5,1,2,3,4}; giriyorum ve çıkışta

0B-0A-9-8-7-6-5-1-2-3 bilgisini alıyorum. 

Yularıdaki kod paket yapısını tam olarak oluşturmuyor mu?

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: mufitsozen - 06 Haziran 2014, 17:25:39
Alıntı yapılan: gerbay - 06 Haziran 2014, 13:43:49
Müfit Bey,

her zaman söylüyorum; "sizden hepimizin öğreneceği çok şey" var diye.. 

keşke kitap(lar) yazsanız hem teknik hem teknik olmayan..

Vayt canavar gelmis!   ;D

sevgili @gerbay once sen Picproje Hangout'a cik, sonra teknik kitap yazma konusunu ciddi olarak konusalim(ornek kodlari kim yazacak acaba?)   
Subram bunu sende duy, not al hemen! :P


<kisiye ozel mesaj>gerbay bu mesaj icin onceden konustugumuz gibi 100TL hesabina bugun yatar. Sen beni ovmeye devam et. :P

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 06 Haziran 2014, 17:30:34
selamlar tekrar,

Konu baya dallanmış budaklanmış :) Yeni başlık açmadan bir şey sorayım hemen.

uint8_t TestVerim[14];

typedef __packed struct MyTestStruct
{
uint8_t  a; //1Byte
uint16_t b; //2Byte
uint32_t c; //4Byte
}MyTestStruct;

MyTestStruct TestStruct[] = {
{0xAA,0xBBBB,0xCCCCCCCC},
{0x2A,0x2BBB,0x2CCCCCCC},
};


Gelen verinin işime yarayan kısmını TestVerim dizisine atıyorum, bu diziyi usart üzerinden geri gönderdiğimde içeriğinin doğru olduğunu görüyorum. Aynı şekilde TestStruct'ın içeriğine baktığımda da aşağıdaki şekilde doğru görünüyor.

AA BB BB CC CC CC CC 2A BB 2B CC CC CC 2C

TestVerim dizisinin içeriğini memcpy ile struct'a atmaya çalıştığımda ise structa ekstra bir byte ekleniyor :

memcpy(TestStruct,TestVerim,sizeof(TestVerim));


AA BB BB CC CC CC CC 2A BB 2B CC CC CC 2C 01

0x01 (SOH:Start of Heading) anlamına gelen bir byte ekleniyor. sizeof yerine direkt 14 yazmayı denedim gene olmadı. bu ekstra byte niye ekleniyor ? Nasıl engellerim ?

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: mufitsozen - 06 Haziran 2014, 17:49:33
sevgili @gerbay arkadas 14 bytelik structure basinca 15 eleman basmis. aslinda sonundaki  01 extra yoksa struct duzgun

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: kimlenbu - 06 Haziran 2014, 17:53:20
kendi
Alıntı yapılan: gerbay - 06 Haziran 2014, 17:42:47
kodlarınızın tümünü görmeden birşey söylenemez, struct a öyle byte falan eklenemez..

kendi kendine düzeldi, ne olduğunu anlamadım bile. tek harf eklemeden doğru çalışmaya başladı.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: yldzelektronik - 07 Haziran 2014, 13:25:58
Selamlar.

Simdi usart uzerinden struct olarak paket veri gonderimi olayi cok guzel gozukuyor. Ancak olayi tam olarak kavrayabilms degilim. Bunun tercih sebebi verilerin istifli duzenli gitmesi midir? Baska bir sebebi var midir? Bir de float nasil gonderilecek? Bu konusuldu ama yarim kaldi. Sevgili gerbay bu konuda hakli olarak bize cok kzdi fakat yontem gosterilmedi veya bn kacirdm. Sonucta noktali bir sayi ve usart uzerinden her seyi byte byte gonderebiliyoruz. Ancak ornegin 1.23456789 sayisini baska nasil gonderebiliriz? Struct icinde olur denms olmaz dnms. Nedir isin asli?
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Tagli - 07 Haziran 2014, 13:45:57
Aslında struct içinde olup olmamasının bir önemi de yok. Düzenli olsun, efendi gibi gitsin diye öyle yapıyoruz.

Şu da yapılabilirdi:
float gidici = 1.234;
char *baslangic = (char*)(&gidici);
gonderenFonksiyon(baslangic, sizeof(gidici));

Bu en temel hali tabi. Kodun adam gibi gözükmesi için bu işin bir düzeni olmalı. Alıcı taraf ne olup bittiğini bilmeli, yani arada bir protokol olmalı. Ayrıca tabi endian türü uyumlu olmalı.

Not: char'ın 1 byte olduğunu varsaydım. Çoğu platformda bu böyle ama istisnaları var.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: berat23 - 07 Haziran 2014, 14:57:21
altyazı gürmek gerekiyor galiba. bilmeyen biri gibi bakınca epey karışık gözüküyor.

aslında sorulan struct'ı byte byte yollamak, buna muhtelif cevaplar var.
gerbay 'ın dediği gönerilecek verileri bir struct ile paketleyip yollamak.
mufitsozen'in anlattığı ise paketlerin doğru alınabilmesi için bir metod.

bu sıra ile üst seviyeye doğru gidiyor. bu yönden bakarsanız konu daha anlaşılır olur.
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 07 Haziran 2014, 19:47:53
@berat23
Yok müfit hocamın cevabı Struct'a alternatif ya da onun karşısında bir yöntem değil. Binary alışırken , paket başı sonu vs.. sorunlarına  değişik bir yaklaşım getiren bir algoritma ( en azından kısa bir göz atma sonucunda böyle anladım). Sonuta o algoritmayla kodlanacak ve kodu çözülecek bir veri  dizisi var. Struct kullanmak, veri göndermeyi kolaylaştıran bir yöntem değil. Daha doğrusu haberleşme ile ilgili bir mesele değil. Farklı tipte bir çok veriyi, hiç ekstra kod kullanmadan dizi haline getirip paketlememizi sağlıyor.   

@Tagli
Evet elimizde tek bir veri ya da tek tip veriden oluşan bir dizimiz varken  struct içerisinde olup olmamasının bir önemi yok. Dediğin gibi de göndeririz. Karşıdan da alırız.  Ama veri miktarı artınca ve veri tipleri çeşitlenince , bahsettiğin yöntem efektif olmaktan çıkıyor.  Her çeşit tipten 100 tane değişkenin içeriğini bu şekilde gönderip aldığını bir düşünsene...

@yildizelektronik.

elimizde şöyle basit bir struct olsun.
struct{
int a;  // = 0xA01C
float b; //  =  168.967  farzedelim ki bunun hex karşılığı da  0x3CA00BD2 olsun.
char c; // = 'A'  0x41
char d; // = 'B'  0x42
}

bu yapının hafızadaki görünümü şöyle olacaktır.

adres  0x00  0x01  0x02  0x03  0x04  0x05  0x06  0x07
           ------  ------  ------  ------  -------  ------  ------  -------
           0xA0  0x1C  0x3C  0xA0  0x0B  0xD2 0x41  0x42

biz  bu veriyi göndermek iin , 0x00 adresinden başla 0x07 adresine kadar gönder deiğimizde  karşı tarafın tamponunda da aynı veriyi göreceğiz.
Eğer bu adres aynı yipte bir struct başlangı adresi ise,  b değişkenini okuduğumuzda  aynı değeri elde edeceğiz.

@mufitsozen
Hocam! elektronik okumak yerine,  ben bu parite, kur, hisse , borsa gibi şeylerden niye alamıyorum deyip gider ekonomi okursanız, ancak bu kadar programcı olabiliyorsunuz. :) idare edin artık.
Algoritmayı derinlemesine analiz edemedim henüz.  Ama sarsılmaz bildiğiniz bazı şeyleri sarmış olması açısından güzel bir örnek. 
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: mufitsozen - 07 Haziran 2014, 23:34:33
 
Alıntı yapılan: Klein - 07 Haziran 2014, 19:47:53

@mufitsozen
Hocam! elektronik okumak yerine,  ben bu parite, kur, hisse , borsa gibi şeylerden niye alamıyorum deyip gider ekonomi okursanız, ancak bu kadar programcı olabiliyorsunuz. :) idare edin artık.
Algoritmayı derinlemesine analiz edemedim henüz.  Ama sarsılmaz bildiğiniz bazı şeyleri sarmış olması açısından güzel bir örnek. 


sayin @klein, aramizda kalsin ama 4 ay once async framing nasil olur diye bir arkadasa byte stuffing frame start=7E, escape 2D xor filan falan diye uzun uzun anlatmis hatta birde kucuk fsm yapmistim. Ama durmadan okuyup arastirdigim icin 2 ay once bu COBS denilen algoritmayi buldum sans eseri. Gecen gun bu basligi okuyunca "yasasin dedim, simdi herkese bak ben ne kadar bilgiliyim diye gostermek icin firsat cikti!  :P

@gerbay canavardir ama cok iyi niyetli ve sazan familyasindan turemis canavardir. Oda hemen oltaya geldi "mufit bey sizden ogrenecegimiz cok sey var diye!" (tabii hesabina 100TL hemen o an yatti! :D)

Yani demem o ki, ogrenmek, bilmek ve uygulamak yeterli değil, her gun  yeni birseyler ortaya cikiyor. surekli olarak daha da iyisi olabilirmi diye arastirmak gerekiyor.

Bu arada hem size birazcik teselli olacaksa bende borsada oldukca hatiri sayilir meblaglar kaybettim, su meshur pazarin gorunmez eli ne demek yahu diye rosa luxemburg'un "accumulation of capital"inden john kay"in "culture and prosperity"sine kadar ekonomi okudum bir faydasi olmadi. Yani bendende anca o kadar ekonomist oluyor :) sonucta yasama "isci emeklisi" olarak devam ediyorum. ;)

Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: berat23 - 12 Haziran 2014, 17:20:04
@Klein

tam anladığınız gibi değil aslında. yaşadım, örnek vereyim. mesela bir sensörden hex data geliyor. adamlar frame sonu bildirmek için cr kullanmış ama bu veri aynı zamanda gelen veride olabiliyor. bu durumda frame sonunu anlamak için 0x0d ararsan hata yaparsın. veriyi struct ile paketleyip yollamak bu tip bir haberleşmenin doğruluğunu garantilemiyor. mufitsozen'in anlattığı algoritmalar veriden bağımsız, unique bir soh ile veri yollamanıza yarıyor, bu sayede paket başı,sonu daha kesin belirlenebiliyor. yani farklı tipte verileri paketlemeye bir çözümü yok(o işi struct ile yapabilirsiniz), paketlerin doğru alınmasına yarıyor. bilmem anlatabildim mi
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: ilhan_mkp - 15 Haziran 2014, 00:00:10
bu haberleşme konularını öğrenmek için bir süredir okuyorum iki işlemcili bir yapıyı haberleştirmek için nasıl bir protokol kullanmak gerekir bunu öğrenmek için yola çıktım okudukça dallandı budaklandı.
ilk önce modbus ascii gözüme hoş göründü başlangıç  ";" karakteri  ile bitiç "cr\lf" ile yapılması ama "123" göndericem "1""2""3" olarak parçalamak pekte hoşuma gitmedi.

çerçeve olarak neler kullanılabilir bu konuda standart bir yapı varmı modbus protokolleri haricinde yeni nesil neleri araştırmak lazım.
müfit hocam haberleşme konusunda önerebilceğiniz çok kaynak olduğuna eminim.
struct göndermek hoş bir resim bu resmi düzgün bir çerçeveye koymak gerekmezmi ?
Başlık: Ynt: USART Üzerinden Struct Göndermek
Gönderen: Klein - 11 Ocak 2015, 05:21:26
Alıntı yapılan: berat23 - 12 Haziran 2014, 17:20:04
@Klein

tam anladığınız gibi değil aslında. yaşadım, örnek vereyim. mesela bir sensörden hex data geliyor. adamlar frame sonu bildirmek için cr kullanmış ama bu veri aynı zamanda gelen veride olabiliyor. bu durumda frame sonunu anlamak için 0x0d ararsan hata yaparsın. veriyi struct ile paketleyip yollamak bu tip bir haberleşmenin doğruluğunu garantilemiyor. mufitsozen'in anlattığı algoritmalar veriden bağımsız, unique bir soh ile veri yollamanıza yarıyor, bu sayede paket başı,sonu daha kesin belirlenebiliyor. yani farklı tipte verileri paketlemeye bir çözümü yok(o işi struct ile yapabilirsiniz), paketlerin doğru alınmasına yarıyor. bilmem anlatabildim mi
Evet anlatabildin. Ama benim anladığımdan ve yukarıda anlattığımdan farklı olan nedir onu anlamadım?

Alıntı yapılan: Klein - 07 Haziran 2014, 19:47:53
Yok müfit hocamın cevabı Struct'a alternatif ya da onun karşısında bir yöntem değil. Binary alışırken , paket başı sonu vs.. sorunlarına  değişik bir yaklaşım getiren bir algoritma ( en azından kısa bir göz atma sonucunda böyle anladım). Sonuta o algoritmayla kodlanacak ve kodu çözülecek bir veri  dizisi var. Struct kullanmak, veri göndermeyi kolaylaştıran bir yöntem değil. Daha doğrusu haberleşme ile ilgili bir mesele değil. Farklı tipte bir çok veriyi, hiç ekstra kod kullanmadan dizi haline getirip paketlememizi sağlıyor.