Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: HellMaster 11. 04. 2013, 16:33:49

Název: Monitor sběrnice LIN - dekódování v C
Přispěvatel: HellMaster 11. 04. 2013, 16:33:49
Zdravim vsechny,

pomoci karty od National Instruments jsem schopen monitorovat data po sbernici LIN. NI ma API v C, kterym lze data z karty vycist a zapsat do struktury nasledujiciho typu:

Kód: [Vybrat]
typedef struct
{
timestamp;
ID;
data_length;
data[8]
} LIN_DATA

Vypsat tyto data neni problem, ale zde prichazi hacek. Frame zpravy daneho ID reprezentuje nejakou konkretni zpravu.
Napriklad:
zprava s ID 10 bude GetStatus, bude mit 32 bitu:
bit 0 - 5 vyska
bit 6 - 11 sirka
bit 12 - 17 delka
.
.
.

Informace o techto framech mam ulozene v externim souboru. Jakym zpusobem dekodovat detaily techto zprav? Napriklad z karty vyctu zpravu s ID 10. Vypisu ji a k tomu potrebuju vypsat/rozklicovat jednotlive podzpravy, protoze tato informace je pro uzivatele prinosnejsi, nez 8 byte v hexa. Problem je, ze soubor s definici ramcu zprav je projekt od projektu odlisny, cili nelze nadefinovat hlavickovy soubor, ten inkludovat a toto cele zkompilovat.

Pro lepsi predstavu pro monitorovani LIN/CAN sbernice slouzi napr. HW CANoe nebo CANalyzer od spolecnosti VECTOR. Bohuzel je velmi drahy a licencovany, proto jsem si chtel udelat vlastni, jednodussi variantu. :-)

Diky za jakekoli napady! :-)
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: gamer 11. 04. 2013, 17:53:19
Nehledáš tohle?
http://www.elmomc.com/support/manuals/MAN-CAN301IG.pdf
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 11. 04. 2013, 20:11:02
Cau, diky za link. Prolitnul jsem to zbezne, ale zatim jsem z toho nevykoukal nic moudreho nebo pouzitelneho.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: xcvcdvsd 11. 04. 2013, 20:23:26
v externim souboru mas definice, ze napr. pro ID 4 mas bajty interpretovat treba jako 3 inty za sebou.
nebo pro ID 7, ze to jsou treba 2 floaty za sebou. apod.

i kdyz maji ruzne projekty ruzne definice v externim souboru,  furt tam bude definice neco jako:
ID1 vyska 2bajty = 2bajtove_cele_cislo, sirka 2bajty = 2bajtove_cele_cislo
ID2 teplota 4 bajty = 4_bajtovy_float.

pokud budes mit v kodu programu nadefinovany vsecky vystupni formaty 2_bajtove_cele_cislo, 3_bajtove_cele_cislo, 4_bajtovy_float, 10_bajtovy_string a v externim souboru budou jenom tyto, tak nemas problem.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 12. 04. 2013, 06:31:17
At jsme konkretni, tak v externim souboru mam nasledujici:

Frames {
   BCM_LIN5_A : 48, BCM_Gp, 4   {
      UserSetMinute, 0;
      UserSetSecond, 8;
      UserSetHour, 16;
      CarModeL5, 24;
   }
   BCM_LIN5_B : 32, BCM_Gp, 2   {
      MonitoringRestartReqBCML5, 9;
   }
   BCM_LIN5_C : 55, BCM_Gp, 8   {
      RHSBLSlewRateRequest, 0;
      RHFrontSMRequest, 4;
      LHFrontSMRequest, 6;
      RHSBLPWMDutyRequest, 8;
      RHDRLPosSlewRateRequest, 16;
      LHSBLSlewRateRequest, 20;
      RHDRLPosPWMDutyReq, 24;
      LHDRLPosSlewRateReq, 32;
      LHDRLPosPWMDutyReq, 40;
      LHSBLPWMDutyRequest, 48;
   }
   CLOCK_A : 49, CLOCK, 4   {
      CLKHWPartNo, 0;
      CLKFaultStatus, 16;
.
.
.
.
}

Nazev zpravy, jeho ID, pocet bytu a pak nasleduje vnitrni struktura, kde jsou nadefinovane offsety jednotlivych parametru v bitech. Jak je videt, tak kazda podzprava ma jine vnitrni usporadana. Nektere podzpravy jsou 8 bitu dlouhe, jindy 6 atp...
Cili ja za behu programu neznam tuto strukturu a nemuzu si ji teda nikde predem nadefinovat a zakomponovat ji do applikace. Toto musi nejak probehnout za behu programu.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: sdrgtdasgf 12. 04. 2013, 06:51:27
UserSetMinute, 0;
UserSetSecond, 8;
UserSetHour, 16;
CarModeL5, 24;

ale z tech offsetu vidim, ze UserSetMinute ma delku osm bitu viz. offsety 0-8, tak bych to reprezentoval jako cislo 0-255 v ulozene v charu.

RHSBLSlewRateRequest, 0;
RHFrontSMRequest, 4;
LHFrontSMRequest, 6;

RHSBLSlewRateRequest ma delku 4 bity takze zase jako cislo 0-127 ulozene v char.

takze jedina vec je predem si urcit jak ruzne delky v bitech budu reprezentovat jako typy.
napr.

4 bity = char
8 bitu = char
16 bitu = int nebo float, tady uz by bylo asi treba rozhodnout i podle nazvu promene.
nebo pokud vim, ze pracuju jen s inty.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 12. 04. 2013, 07:07:19
To vidis ted, ale co kdyz ti hodim jiny file kde toto bude nadefinovane jinak? :-)

A i nazvy parametru budou jine. Takze nejake preddefinovani nemuzu pouzit.

Krom toho ja potom budu potrebovat z tech 8 bytu vykrojit tu 6bitovou cast a vypsat ji. Coz by se dalo udelat najkym maskovanim a posunem bitu.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: adfgsdfgsdfgdsg 12. 04. 2013, 08:53:41
To vidis ted, ale co kdyz ti hodim jiny file kde toto bude nadefinovane jinak? :-)

A i nazvy parametru budou jine. Takze nejake preddefinovani nemuzu pouzit.

Krom toho ja potom budu potrebovat z tech 8 bytu vykrojit tu 6bitovou cast a vypsat ji. Coz by se dalo udelat najkym maskovanim a posunem bitu.

na nejakem standardu se ale musis zastavit.

UserSetMinute, 0;
UserSetSecond, 8;
UserSetHour, 16;
CarModeL5, 24;
napriklad CarModeL5 zacina na 24 bitu a konci na 48 bitu, takze to podle me bude stringovy identifikator, ale treba by to mohl
by i nejaky vicebajtovy integer. to z konfiguraku nevyctes, to si holt musis preddefinovat predem.

kdyz mam nekde 4bity tak to muze byt cislo, nebo znak, dokonce i nejaky float s pevnou desetinou teckou.
Kdyz nekde v nazvu vidim minute, second, hour tak predpokladam integer cislo.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 12. 04. 2013, 10:21:40
CarModeL5 zacina na bitu 24 a je az do konde, coz je v tomto pripade bit 32. To neni ale podstatne. Ve vysledku to jsou vsechno jen cisla. Neni to string a podle me ani float. Vsechno to jsou cisla typu int.
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: Mirek Prýmek 12. 04. 2013, 10:30:56
Asi mně nějak nedochází, co řešíš. Máš jakýsi definiční soubor v jakémsi formátu a máš data, která jsou formátovaná podle té definice.

No tak si musíš napsat parser toho definičního souboru, zparsovat ho, uložit výsledek do nějaké rozumné struktury v paměti a potom data dekódovat na základě té struktury. V čem je teda problém? Nechceš to přeformulovat na trochu jinou otázku než "jak to udělám"?
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: adfgsdfgsdfgdsg 12. 04. 2013, 11:08:25
CarModeL5 zacina na bitu 24 a je az do konde, coz je v tomto pripade bit 32. To neni ale podstatne. Ve vysledku to jsou vsechno jen cisla. Neni to string a podle me ani float. Vsechno to jsou cisla typu int.

tak kdyz jsou to vsecko inty s ruznou bitovou velikosti, tak nemas problem. na vtupu mas char[ruzna_delka]
a ty pak jenom nasypes tolik bitu kolik chces pomoci bitovych operaci treba do vystupniho long longu.
klidne muzes pouzivat typ long long dlouhy 64 bitu, a do toho vleze vsecko :-)
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 12. 04. 2013, 11:18:50
Asi mně nějak nedochází, co řešíš. Máš jakýsi definiční soubor v jakémsi formátu a máš data, která jsou formátovaná podle té definice.

No tak si musíš napsat parser toho definičního souboru, zparsovat ho, uložit výsledek do nějaké rozumné struktury v paměti a potom data dekódovat na základě té struktury. V čem je teda problém? Nechceš to přeformulovat na trochu jinou otázku než "jak to udělám"?

Diky za poznamku, asi jsem to vysvetlil spatne. Jelikoz neocekavam nejake kusy kodu apod. jen rady, jakym zpusobem toto implementovat, tak jsem to psal obecneji. Takze:

Po sbernici prijimam a vysilam data, kde ramec vypada zjendodusene nasledovne:

ID (1byte), Data (2 - 4 - 8 bytes delka se lisi)

Karta od National Instrument umi pres jejich C API vycist tyto data do struktury, ktera vypada nasledovne:

Kód: [Vybrat]
typedef struct
{
     ID;
     timestamp;
     data_length;
     UINT8 data[8];
} NITYPE_LIN_STRUCT

Priklad: ID = 48; timestamp = 5000; data_length = 4; data = 0A 25 3C 10 (hex) => data[8] = {10, 37, 60, 10, 0, 0, 0, 0}

Mam externi soubor ldf (LIN description file) ktery mi popisuje vnitrni strukturu prijatych dat podle ID zpravy (tento soubor je nezavisly na NI karte a je dodavan od treti strany):

Kus vypisu z toho souboru vypada nasledovne:

Kód: [Vybrat]
Frames {
BCM_LIN5_A : 48, BCM_Gp, 4 { (nazev zpravy, ID zpravy, nepodstatne, delka zpravy v bytech)
UserSetMinute, 0;       (sub-informace, bit offset - tento parametr zacina na bitu 0)
UserSetSecond, 8;      (sub-informace, bit offset - tento parametr zacina na bitu 8)
UserSetHour, 16;
CarModeL5, 24;
}
BCM_LIN5_C : 55, BCM_Gp, 8 {
RHSBLSlewRateRequest, 0;
RHFrontSMRequest, 4;
LHFrontSMRequest, 6;
RHSBLPWMDutyRequest, 8;
RHDRLPosSlewRateRequest, 16;
LHSBLSlewRateRequest, 20;
RHDRLPosPWMDutyReq, 24;
LHDRLPosSlewRateReq, 32;
LHDRLPosPWMDutyReq, 40;
LHSBLPWMDutyRequest, 48;
}
CLOCK_A : 49, CLOCK, 4 {
CLKHWPartNo, 0;
CLKFaultStatus, 16;
.
.
.
} // End of Frame description

Takze pro nas prikald,
UserSetMinute = 16 (0x10)
UserSetSecond = 60 (0x3C)
UserSetHour = 37 (0x25)
CarModeL5 = 10 (0x0A)

Problem je, ze ten definicni soubor se meni projekt od projektu. Takze priste muze byt na ID 48 zprava GetParam, delka 2 byte a muze v sobe mit zakodovanych 8 informaci, kazda po dvou bitech.

Otazka zni, jaky zpusob zvolit pro predzpracovani teto informace pro nasledny vypis na obrazovku?

priklad:
Kód: [Vybrat]



NITYPE_LIN_STRUCT data[256]; // mam nactenych 256 zprav

ReadData(&data);

for(i = 0; i < pocet_zprav; i++)
{
     printf("ID: %d,  Time: %d,   Data Length: %d, Byte1: %d, Byte2: %d, Byte3: %d Byte4: %d, Byte5: %d....\n", data[i].ID, data[i].timestamp, ....)
     for(j = 0; j < pocet_sub_informaci; j++)
           printf("%sz: %d\n", [b]data[/b], [b]hodnota[/b]);
}

Jakym zpusobem udelat predzpracovani dat z externiho souboru (jak je manageovat), abych k nim potom pri vypisu mohl pristoupit a pomoci nich dekodoval onech 2-4-8 prijatych bytu?

Cili, otevru soubor -> predzpracovani dat a ulozeni nekam -> mozno spustit monitorovani sbernice (data uz jsou predpripravena a vim, podle jakeho klice dekodovat)


Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: Logik 12. 04. 2013, 12:02:50
No tak si z toho popisu zprávy udělej deskriptor zprávy přesně v tom stylu: seznam
polozek ve tvaru

char[] nazev
int start
int length

ukladej si presne co ti vraci ta knihovna a pomoci tohodle deskriptoru tahej data primo z toho uintu, ne

Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: Mirek Prýmek 12. 04. 2013, 12:10:39
To jenom podrobneji popisujes porad to stejny. Kde mas presne problem? Na co presne se ptas? Jak parsovat ten definicni soubor, v jakem meziformatu si ho ulozit? Nebo jak ten meziformat pouzit na dekodovani dat?

Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: slonik 12. 04. 2013, 12:11:50
to BCM_Gp neviem co je.
Kód: [Vybrat]
struct subor {
  struct idcko *pole_id;
  size_t pole_id_len;
}

struct idcko {
 char * popisok;
 size_t pocet_chlievikov;
 struct chlievik *pole_ch;
}

struct chlievik {
char * popisok;
off_t offset;
size_t typ;
}

teraz to tychto struktur naloadujes ten subor.

a nasledne vypisujes
Kód: [Vybrat]
NITYPE_LIN_STRUCT sprava;

struct subor *s;
struct idcko *muid = s->pole_id[sprava.ID];

fprintf(stdout, "Id spravy je %u %s \n", sprava.ID, muid->popisok);

int i;
for (i = 0; i < muid->pocet_chlievikov; i++){
 struct chlievik * chliev = &muid->pole_ch[i];
 char * num = &sprava.data[chliev->offset];

   fprintf(stdout, "V chlieviku %u %s je cislo %s \n", i, chliev->popisok, muid->popisok, num);


}
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: HellMaster 12. 04. 2013, 12:32:16
to Mirek P.

V podstate jsem hledal meziformat toho, jak to ulozit, skladovat a k tomu potom pristupovat. Asi jsme se na to koukal moc ze siroka nebo co a pritom to je primo prede mnou.

To co pisou kluci je (prozatim) jasne reseni. Ale do budoucna, pokud budu potrebovat informaci o tech framech atp. pouzit jinde, tak budu moct pouzit tohle pole.... zatim to vypada jako cesta nejmensiho odporu. Jen nevim, jak z hlediska budoucnosti, kdyz budeme pridavat dalsi funkcionality.

Diky za otevreni oci. Pokud jsou ale jine navrhy, jak toto spravovat, sem s nimi. Kazde reseni ma neco do sebe. :-)


Jinak co se parsovani tyce... je neco, na co byste me odkazali nebo mam se drzet klasickych C funkci a tema to nejak zpytlikovat?

Diky vsem za snahu a pomoc! :-)
Název: Re:Monitor sbernice LIN - dekodovani zprav v C
Přispěvatel: Mirek Prýmek 12. 04. 2013, 13:48:57
Jen nevim, jak z hlediska budoucnosti, kdyz budeme pridavat dalsi funkcionality.
Ja v tom zadnej problem nevidim. Resil bych to taky tak jak slonik, akorat mozna jednoduseji - kazda polozka ma nazev (string) a typ (enum), offset neni potreba, protoze delky jsou dane typem a pozice je dana poradim v paketu (predpokladam, ze "diry" tam byt nemuzou). Takze podle me by jako popis paketu stacilo pole dvojic (string popis, enum typ) ukoncene NULLem a paket postupne prochazet pomoci ukazatele a vypisovat vzdycky popis a hodnotu. Akorat trochu drbacka s tim, ze hodnoty, pokud jsem se neprehlidl, nejsou zarovnane na byty.


Diky za otevreni oci. Pokud jsou ale jine navrhy, jak toto spravovat, sem s nimi. Kazde reseni ma neco do sebe. :-)

Jinak co se parsovani tyce... je neco, na co byste me odkazali nebo mam se drzet klasickych C funkci a tema to nejak zpytlikovat?
Nejjednodussi je pouzit nejakej parser generator typu yacc apod.
Název: Re:Monitor sběrnice LIN - dekódování v C
Přispěvatel: HellMaster 12. 04. 2013, 15:19:05
Ja to budu resit jako slonik, jen misto chlieviku bude spojovy seznam a subor nadefinuju natvrdo jako pole o delce 64.

Ale zajimala by me implementace pres enumerator. Nemam s tim vubec zkusenost, muzes nadhodit myslenku, pripade sample code? Diky :-)
Název: Re:Monitor sběrnice LIN - dekódování v C
Přispěvatel: Mirek Prýmek 12. 04. 2013, 15:20:29
Ne enumerator, ale enum = výčet.
Název: Re:Monitor sběrnice LIN - dekódování v C
Přispěvatel: HellMaster 12. 04. 2013, 15:27:13
Ziju v domeni, ze enum = enumeration  coz je onen vycet. Jen jsem to spatne pouzil a napsal enumerator. Coz mela byt asi enumerace. :-) Ale kod by me zajimal, jestli mas chvilku. Pokud ne, hod na to bobek. :-)