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ı)
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.
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
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.
Sağolun cevaplar için, ekipmanlar iş yerinde yarın ilk iş deneyip yazarım sonucu. "packed" olayını bilmiyordum ne yalan söyleyeyim.
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.
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 :)
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.
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 :)
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.
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.
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.
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?
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 ?
Siz Anltın ben Öğrneym Hcam Yntemi mmknse.
baktım hocam Sağolun.
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?
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.
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.
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.
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);
@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.
@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
)
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.
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.
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.
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/)
@mufitsozen hocam gerçekten güzel algoritmaymış teşekkürler. Birde buna CRC ekledik mi tadından yenmeyecek :)
@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?
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
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 ?
sevgili @gerbay arkadas 14 bytelik structure basinca 15 eleman basmis. aslinda sonundaki 01 extra yoksa struct duzgun
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ı.
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?
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.
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.
@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.
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. ;)
@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
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 ?
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.