Postitused: 578
Teemad: 140
Liitus: Dec 2009
Õpin seda ja tekkis tüüpiline algaja küsimus. Neti abiga palju targemaks ei saanud. Küsimus on andmetüüpide konverteerimises.
Saan DS1337-kellalt aja ja tahan moodustada faili nimega yyyy-mm-dd.csv (aasta-kuu-päev).
Hüva, kellalt saadav aasta on WORD tüüpi, muu aga BYTE:
Kood: typedef struct
{
BYTE tm_control;
BYTE tm_status;
BYTE tm_sec;
BYTE tm_min;
BYTE tm_hour;
BYTE tm_wday;
BYTE tm_mday;
// BYTE tm_mon_cent;
WORD tm_year;
BYTE tm_mon;
BYTE tm_yday;
BYTE tm_isdst;
} timetype;
Ilmselt peab ajad muundama stringideks ja siis nad kokku liitma. Proovisin:
Kood: char FailiName[32]; // logifaili nime moodustamiseks
char *pFailiName; // viit faili nimele
char * itoa( int value,char * string );
pFailiName=FailiName; // viitab failinime arrayle
FailiName=(itoa ((DS_Aeg->tm_year,pFailiName);//+"-"+(itoa (DS_Aeg->tm_mon,pFailiName)+(itoa (DS_Aeg->tm_mday,pFailiName));
//esialgu testin vaid aastanumbri konvertimist
....
logFile = FSfopenpgm(FailiName+".csv","w"); // see töötab kui anda ette stringikonstant nt logi.csv
.....
Syntax error reas kus FailiName moodustatakse.
Mida paganat... ???
Postitused: 49
Teemad: 10
Liitus: Aug 2011
Failinime moodustamisel on äkki järgmisest näitest abi:
Kood: #include <string.h>
int main(char** args, int argc) {
char fileName[255];
int year = 2012;
int month = 6;
int day = 7;
sprintf(&fileName, "%4d-%2d-%2d.cvs", year, month, day);
}
See võib mitte kompileeruda, mul pole hetkel C-kompilaatorit käepärast, et seda kontrollida ja ei kasuta C-d väga tihti.
Kui sa pead silmas seda rida, kus sa teed FileName + ".csv", siis üldiselt (kui just Microchip pole mingit erandit teinud) C-s on stringid char-i massiivid, "+"-märgiga neid omaval kokku liita ei saa, selleks on meetod "strcat". Ilmselt kahe konstandi korral "+" siiski töötab.
Postitused: 3
Teemad: 0
Liitus: Nov 2010
FailiName=(itoa ((DS_Aeg->tm_year,pFailiName);
Tundub et sulgusid on puudu.
Postitused: 578
Teemad: 140
Liitus: Dec 2009
07-06-2012, 08:45 PM
(Seda postitust muudeti viimati: 07-06-2012, 08:48 PM ja muutjaks oli felch.)
Tänud nõu andmast, probleem on lahendatud. Osa oli sellest, et ma ei saa ikka C bürokraatiale (minu meelest) pihta ja osa oli C18 erinippides.
Lõplik koodilõik tuli säärane:
Kood: ...
char FailiName[32]; // logifaili nime moodustamiseks
....
rtc_get (DS_Aeg); // vaatame kella, WORD year, BYTE - muud aja muutujad
year=DS_Aeg->tm_year;
month=DS_Aeg->tm_mon;
day=DS_Aeg->tm_mday;
hours=DS_Aeg->tm_hour;
minutes=DS_Aeg->tm_min;
seconds=DS_Aeg->tm_sec;
itoa (year,FailiName);
btoa (month,tmpstr);
strcatpgm2ram (FailiName, "-");
strcat (FailiName, tmpstr);
btoa (day,tmpstr);
strcatpgm2ram (FailiName, "-");
strcat (FailiName, tmpstr);
strcatpgm2ram (FailiName, ".csv");
strcpypgm2ram(fo_mode,"a");
logFile = FSfopen(FailiName, fo_mode); // avame faili appendiks või kui sellise nimega veel pole siis tekitame
btoa (hours,FailiName); // kirjutab: hh:mm:ss power restored, muutuja FailiName taaskasutamine :)
btoa (minutes,tmpstr);
strcatpgm2ram (FailiName, ":");
strcat (FailiName, tmpstr);
strcatpgm2ram (FailiName, ":");
btoa (seconds,tmpstr);
strcat (FailiName, tmpstr);
strcatpgm2ram (FailiName, ",Power restored \r\n");
FSfwrite((const void*)&FailiName[0],1,sizeof(FailiName),logFile);
...
Selgub, et 18-seeria puhul tuleb kasutada *pgm funtsiooni (strcatpgm2rm jne) sest muidu ei suudeta flashist asja RAMi lugeda (ilmselt ei kasutata siis TBLRD*+ asmi käsku. Miks aga see on vajalik info liigutamisel RAMi sees, pole selge. Igatahes nii netis soovitati ja nii toimis ka.
Ma ei saa aru...räägitakse ju, et C-s on kõik lihtne ja eriti mugav...?
Postitused: 137
Teemad: 3
Liitus: Dec 2009
(07-06-2012, 08:45 PM)felch Kirjutas: Selgub, et 18-seeria puhul tuleb kasutada *pgm funtsiooni (strcatpgm2rm jne) sest muidu ei suudeta flashist asja RAMi lugeda (ilmselt ei kasutata siis TBLRD*+ asmi käsku. Miks aga see on vajalik info liigutamisel RAMi sees, pole selge. Igatahes nii netis soovitati ja nii toimis ka. Ma ei ole küll Microchipi C kompilaatori spetsialist, seega järgnev on vaid mingi tõenäosusega paika pidav jutt:
See konkreetne kompilaator paneb tähele, et:
1. strcatpgm2rm teine argument on tüüpi "const char*" - ehk et viitab read-only mälualale.
2. ":" on fikseeritud string, mida kasutatakse ainult strcatpgm2rm teise argumendina.
Pannes kokku 2 pluss 2 (ehk tehes lihtsat konstantide kasutuse analüüsi), leiabk kompilaator, et ":" võib paigutada RAM-i asemel flash'i.
(07-06-2012, 08:45 PM)felch Kirjutas: Ma ei saa aru...räägitakse ju, et C-s on kõik lihtne ja eriti mugav...? Eks igal asjal mõned kitsaskohad, millesse eriti alustades võib kinni jääda või ebaefektiivselt teha. Aga kui ka edaspidi tunned C-s millestki puudust, kriba ikka siia; ma ei ütle, et ma kõike oskan, aga mitme peale ikka hea lahenduse leiab.
Stringitöötlus on ka Basicuga võrreldes suhteliselt algelisemal tasemel. Kui leiad sprintf kasutamise võimaluse üles nagu kasutaja Mtj soovitas, siis saad oma koodijupi märksa lühemaks.
Eraldi muutujaid "year", "month" jt. ei pea ka tegema, võib ka otse kasutada "DS_Aeg->tm_year" jne.
Postitused: 49
Teemad: 10
Liitus: Aug 2011
11-06-2012, 10:17 AM
(Seda postitust muudeti viimati: 03-07-2012, 11:03 AM ja muutjaks oli tvtv.)
Mikronkontrolleri jaoks on sprintf vb. liiga ressursinõudlik, kui sul seda funktsiooni just palju tarvis pole. Selline tähelepanek ka veel, et DS1337 hoiab suuremaid numbreid BCD formaadis. Võrreldes kümnendnendsüsteemiga on neid tunduvalt lihtsam ja odavam stringiks teisendada. Võrdlemiseks ja tehte tegemiseks on samas vaja eraldi funktsioone. Microchip-i teek <math.h> peaks sisaldama ka mingeid funktsioone BCD formaadis numbritega manipuleerimiseks, aga ka nende ise kirjutamine pole eriti keeruline. Sinu juhul vb. mingi järgmine lahendus oleks mõistlikum (eeldusel, et tm_year, tm_month ja tm_day on BCD formaadis):
Kood: // ...
char[15] fileName = "2000-00-00.csv";
// See siin on kahtlane rida. Ma ei tea, kas niivisi saab antud
// C-versioonis stringi algväärtustada. Asja mõte on see, et teed
// kõigepealt tõmmisest koopia mällu ja siis asendad seal vajalikel
// postisioonidel olevad sümbolid, nagu allpool tehakse
char[2] = 0x30 + ((DS_Aeg->tm_year) >> 4);
// "10 Year" -> Ascii char (+ 0x30 ehk '0')
char[3] = 0x30 + ((DS_Aeg->tm_year) & 0xF);
// "Year" -> Ascii char (+ 0x30 ehk '0')
char[5] = 0x30 + ((DS_Aeg->tm_month) >> 4);
// "10 Month" -> Ascii char (+ 0x30 ehk '0')
char[6] = 0x30 + ((DS_Aeg->tm_month) & 0xF);
// "Month" -> Ascii char (+ 0x30 ehk '0')
// ... Edasi jätka siit ise
Loomulikult makrode ja funktsioonide kasutamine on alati lubatud, tulemus oleks igatahes loetavam. Ja mul endiselt pole C-kompilaatorit käepärast, niiet ei tea, kas toodud näida ka copy-paste meetodis toimib.
Postitused: 334
Teemad: 26
Liitus: May 2011
Natuke kogemust sellest PICi sprintf-st.
On C-s kirjutatud PICi programmi üks lõik.
(Kogu C teksti pikkus 837 rida.)
Kood: A=input_buffer[0];
if(A=='T'){
Algseisu();
if(mUSBUSARTIsTxTrfReady()){
sprintf(output_buffer, (const far rom char*)"%c", 'X');
mUSBUSARTTxRam((byte*)output_buffer,strlen(output_buffer));
}
return;
Transleeritud kujul sai sellest programmist 47 kb hex,
mille listingu sama lõik näeb välja nii:
Kood: 203: Algseisu();
1D18 DE47 RCALL 0x19a8
204: if(mUSBUSARTIsTxTrfReady()){
1D1A 0101 MOVLB 0x1
1D1C 5101 MOVF 0x1, W, BANKED
1D1E E12B BNZ 0x1d76
205: sprintf(output_buffer, (const far rom char*)"%c", 'X');
1D20 0E58 MOVLW 0x58
1D22 6EE6 MOVWF 0xfe6, ACCESS
1D24 6AE6 CLRF 0xfe6, ACCESS
1D26 0E36 MOVLW 0x36
1D28 6E14 MOVWF 0x14, ACCESS
1D2A 0E42 MOVLW 0x42
1D2C 6E15 MOVWF 0x15, ACCESS
1D2E 6A16 CLRF 0x16, ACCESS
1D30 C014 MOVFF 0x14, 0xfe6
1D32 FFE6 NOP
1D34 C015 MOVFF 0x15, 0xfe6
1D36 FFE6 NOP
1D38 C016 MOVFF 0x16, 0xfe6
1D3A FFE6 NOP
1D3C 0E5D MOVLW 0x5d
1D3E 6EE6 MOVWF 0xfe6, ACCESS
1D40 0E01 MOVLW 0x1
1D42 6EE6 MOVWF 0xfe6, ACCESS
1D44 EC37 CALL 0x446e, 0
1D46 F022 NOP
1D48 6E17 MOVWF 0x17, ACCESS
1D4A 0E07 MOVLW 0x7
1D4C 5EE1 SUBWF 0xfe1, F, ACCESS
1D4E 5017 MOVF 0x17, W, ACCESS
206: mUSBUSARTTxRam((byte*)output_buffer,strlen(output_buffer));
1D50 0101 MOVLB 0x1
1D52 0E5D MOVLW 0x5d
1D54 6F02 MOVWF 0x2, BANKED
1D56 0E01 MOVLW 0x1
1D58 6F03 MOVWF 0x3, BANKED
1D5A 0E5D MOVLW 0x5d
1D5C 6EE6 MOVWF 0xfe6, ACCESS
1D5E 0E01 MOVLW 0x1
1D60 6EE6 MOVWF 0xfe6, ACCESS
1D62 ECA9 CALL 0x4752, 0
1D64 F023 NOP
1D66 52E5 MOVF 0xfe5, F, ACCESS
1D68 52E5 MOVF 0xfe5, F, ACCESS
1D6A CFF3 MOVFF 0xff3, 0x106
1D6C F106 NOP
1D6E 0101 MOVLB 0x1
1D70 6B07 CLRF 0x7, BANKED
1D72 0E01 MOVLW 0x1
1D74 6F01 MOVWF 0x1, BANKED
207: }
208: return;
1D76 EF19 GOTO 0x2632
1D78 F013 NOP
209: }
See buffer viidi siis üle USB tagasi PC-sse ja töödeldi seal.
(Viidi log faili )
Selle PICi hex faili asm logi pikkus on 12656 rida.
Ruumi kokkuhoiu mõttes ma kõike siia ei toonud.
Postitused: 137
Teemad: 3
Liitus: Dec 2009
sprintf on üks tihedamini taasleiutatud jalgrattaid. Googeldage "minimal sprintf implementation" ja kindlasti leiate midagi enda vajadustele ja lubatud flash'i mahule sobivat. Standardis on ära toodud müriaad formaatimise võimalusi ja sestap on standardne funktsioon kole flashimahukas, aga kui kasutate ainult "%s", "%d" ja "%x"-i, siis võib ka kilobaidi või paariga hakkama saada.
Edu!
Postitused: 334
Teemad: 26
Liitus: May 2011
(11-06-2012, 01:13 PM)andrei Kirjutas: sprintf on üks tihedamini taasleiutatud jalgrattaid.
kui kasutate ainult "%s", "%d" ja "%x"-i, siis võib ka
Vaatasin sinna C18 sisse ja
sprintf kutsub välja vfprrintf.c
Seal see on kõik võimalused kenasti kirjas.
Kui nüüd seal natuke "koristada" siis võib küll ruumi juurde saada.
Tapselt samuti on seal siinuse jaoks sincos funktsioon,
mida annaks vajadusel natuke täiendada.
Aga äkki annaks sinna PICi külge sokutada üks mälupulk,
nii 300 GB ( ) ja sealt võtta kõik vajalik.
Piisaks ju ka 300 MB aga uhkus ei anna ju häbeneda.
Postitused: 578
Teemad: 140
Liitus: Dec 2009
Ma leidsin, et C18 sprintf ei toeta float arve Seda on manuaalis ka otse öeldud.
|