GSM_w_elektronice_cz5.pdf

(412 KB) Pobierz
Elektronika Praktyczna
kurs
w elektronice (5)
Open AT – komendy AT, pamięć
Flash
Dodatkowe materiały
na CD i FTP
W  poprzednim odcinku
zajmowaliśmy się między
innymi tworzeniem własnych
komend AT. W  tym pokażemy,
jak stosować do swoich celów
komendy AT oferowane przez
system operacyjny. Pokażemy
również, jak wykorzystać
pamięć nieulotną do trwałego
przechowywania danych.
Listing 1. sprawdzanie stanu zalogowania się modemu do sieci GsM
#include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
#deine GPRS_PINCODE “9172”
s8 sms_handle;
static void poll_creg ( u8 Id );
void Wyslij_SMS (){
adl_smsSend ( sms_handle, “+48xxxxxxxxx”, “TEST SMS”, ADL_SMS_MODE_
TEXT );
}
static bool poll_creg_callback (adl_atResponse_t *Rsp) {
ascii regStateString[3];
s32 regStateInt;
TRACE (( 1, “poll_creg_callback” ));
wm_strGetParameterString (regStateString, Rsp->StrData, 2);
regStateInt = wm_atoi(regStateString);
if ( 1 == regStateInt || 5 ==regStateInt) {
TRACE (( 1, „poll_creg_callback - zalogowany w sieci” ));
Wyslij_SMS();
} else {
/* Nie gotowy - sprawdz ponownie za 1s */
adl_tmrSubscribe ( FALSE, 10, ADL_TMR_TYPE_100MS,
poll_creg);
}
return FALSE;
}
static void poll_creg ( u8 Id ) {
adl_atCmdCreate ( “AT+CREG?”, FALSE, poll_creg_callback, ADL_STR_CREG, NULL);
}
static void SIM_Handler ( u8 event) {
TRACE (( 1, “SIM_Handler” ));
if ( event == ADL_SIM_EVENT_FULL_INIT) {
Na jakość działania i niezawodność pro-
jektu M2M duży wpływ ma to, czy na eta-
pie projektowania będziemy w stanie prze-
widzieć wszystkie okoliczności, które mogą
wystąpić podczas pracy urządzenia. W po-
przednim odcinku, gdy opisywaliśmy serwis
SIM oraz SMS, dla uproszczenia przyjąłem,
że ADL_SIM_EVENT_FULL_INIT oznacza, że
modem jest zalogowany i można już wysyłać
SMS. Tak jednak będzie tylko wtedy, gdy mo-
dem znajduje się w miejscu, w którym jest
dobry sygnał GSM, a sieć działa prawidłowo
i nie jest przeciążona. Aby jednak bez wzglę-
du na okoliczności być pewnym, że modem
jest zalogowany, posłużymy się komendą
AT+CREG. Komenda ta, wydana ze znakiem
zapytania, zwraca status zalogowania się
aparatu do sieci. W aplikacji pokazanej na li-
stingu 1 komenda ta jest wydawana cyklicz-
nie, aż do otrzymania odpowiedzi „1” (zalo-
gowany) lub „5” (zalogowany w roamingu).
Zaprezentowana aplikacja w  większości
przedstawia to, czego już nauczyliśmy się z po-
przednich odcinków kursu z tym, że tu SMS
zostanie wysłany tylko wtedy, kiedy modem
faktycznie zaloguje się do sieci. Dla przykładu,
jeśli odłączymy antenę GSM, to mimo iż zaj-
dzie zdarzenie ADL_SIM_EVENT_FULL_INIT ,
to jednak SMS nie zostanie wysłany. Wszyst-
ko to dzięki kontroli odpowiedzi na komendę
AT+CREG? . Sprawdźmy jak wygląda odpo-
wiedź modemu, jeśli komendę AT+CREG?
wydamy do modemu z terminala (odpowiedź
modemu napisano pogrubioną czcionką):
AT+CREG?
+CREG: 0,1
TRACE (( 1, “SIM Full Init” ));
poll_creg(0);
}
}
bool SMS_handler ( ascii * SmsTel, ascii * SmsTimeOrLength, ascii * SmsText ){
return TRUE;
}
void SMS_Control ( u8 Event, u16 Nb ){
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
adl_simSubscribe ( SIM_Handler, GPRS_PINCODE);
sms_handle = adl_smsSubscribe (SMS_handler, SMS_Control, ADL_SMS_MODE_
TEXT );
TRACE((1,”SMS handle = %d”, sms_handle));
}
OK
pomocą funkcji adl_atCmdCreate() podajemy
funkcję, która będzie otrzymywała odpowiedź
na wskazaną komendę AT, a także iltr odpo-
wiedzi, które chcemy przechwytywać. W na-
Mamy dwie odpowiedzi: jedna to
+CREG: 0,1 ”, natomiast druga to „ OK ”. W na-
szej aplikacji wydając komendę AT+CREG? za
68
ELEKTRONIKA PRAKTYCZNA 7/2010
Technologia GSM
742297930.002.png 742297930.003.png
Open AT – komendy AT, pamięć Flash
Listing 2. Przykład konigurowania portu szeregowego
#include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
void Wylacz ( u8 ID, void * Context){
TRACE((1,”Wylacz UART2”));
adl_atCmdCreate ( “AT+WMFM=0,0,2” ,FALSE , NULL, NULL);
}
bool Conf_Handler (adl_atResponse_t * strc){
TRACE (( 1, “Conf_Handler: response = %d”,strc->RspID ));
if (strc->RspID==ADL_STR_OK) {
adl_atSendResponse ( ADL_AT_PORT_TYPE(ADL_AT_UART2,ADL_AT_RSP),”Hello
World UART2\r\n” );
adl_tmrSubscribe (FALSE,10,ADL_TMR_TYPE_100MS,Wylacz);
}
return TRUE;
}
bool Open_Handler (adl_atResponse_t * strc){
TRACE (( 1, “Open_Handler: response = %d”,strc->RspID ));
if (strc->RspID==ADL_STR_OK || strc->RspID==ADL_STR_CME_ERROR) {
adl_atCmdCreate ( “AT+IPR=9600;+IFC=0,0” ,ADL_AT_PORT_TYPE(ADL_AT_
UART2, FALSE), Conf_Handler , “*” , NULL);
}
return TRUE;
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
adl_atCmdCreate ( “AT+WMFM=0,1,2” ,FALSE , Open_Handler , “*” , NULL);
}
szym przypadku jest to ADL_STR_CREG , czyli
jak w deinicji – string w postaci: „ +CREG: ”.
Jako iltr możemy podać kilka ciągów znako-
wych oddzielonych przecinkiem i zakończo-
nych wartością NULL lub jeśli chcemy prze-
chwytywać wszystkie możliwe odpowiedzi,
to jako argument podajemy „*”. Za pomocą
funkcji wm_strGetParameterString() pobiera-
my drugi parametr odpowiedzi i sprawdzamy
czy jest równy wartości „1” lub „5”. Jeśli tak, to
wykonywana jest funkcja Wyslij_SMS , w prze-
ciwnym razie uruchamiany jest jednorazowy
timer, który po sekundzie ponownie wywoła
funkcję pytającą o stan zalogowania. Funkcja
static void poll_creg(u8 Id) może być bez argu-
mentów, ale wykorzystywana jest również jako
funkcja – handler dla timera, a wtedy już musi
być w określonej postaci. Jeśli chcielibyśmy
zobaczyć przechwyconą odpowiedź w całości,
to najlepiej wewnątrz funkcji poll_creg_call-
back() dodać linijkę:
TRACE((1,Rsp->StrData));
W przedstawiony powyżej sposób moż-
na również odczytywać odbierany poziom
sygnału GSM. Należałoby w takim przypad-
ku skorzystać z komendy AT+CSQ .
Wydawanie komend AT wewnątrz apli-
kacji jest bardzo przydatna, możliwości nie
tylko do celów diagnostycznych, ale również
koniguracyjnych. Na listingu 2 umieszczo-
no przykład konigurujący port szeregowy.
Aplikacja włącza port UART2 komendą
AT+WMFM=0,1,2 i  czeka na odpowiedź.
Wyjątkowo w  tym przypadku, oprócz od-
powiedzi OK za poprawną przyjmowana
jest również odpowiedź CME_ERROR . Za-
stosowano takie uproszczenie, aby pomi-
nąć sprawdzanie czy UART2 jest włączony
przed wydaniem komendy. Próba ponowne-
go włączenia już włączonego portu generuje
właśnie odpowiedź ERROR. Jeśli wiemy, że
tak właśnie jest, to takie rozwiązanie jest do
zaakceptowania. Po wydaniu komendy włą-
czającej port, aplikacja ustawia następujące
parametry transmisji: prędkość 9600  bps
oraz wyłączona kontrola przepływu. Wyda-
nie komendy AT+IPR=9600;+IFC=0,0 jest
równoznaczne z wydaniem dwóch komend
AT+IPR=9600
AT+IFC=0,0
W  odpowiedzi na komendę sklejoną
otrzymamy OK tylko wtedy, jeśli obie komen-
dy zwrócą odpowiedzi OK .
Po ustawieniu żądanych parametrów,
przez UART2 zostaje wysłany komunikat,
a następnie port zostaje wyłączony. Należy
zwrócić uwagę na zastosowane makro ADL_
AT_PORT_TYPE() . W przypadku funkcji, któ-
ra włącza i wyłącza UART2, po komendzie
AT pojawia się wartość FALSE . Oznacza
ona, że odpowiedzi które pomijamy przy
przechwytywaniu również nie pojawią się
w oknie terminala. Komenda AT jest w tym
przypadku wydawana w sposób „anonimo-
wy”. W przypadku ustawiania parametrów
Listing 3. Przykład użycia pamięci lash obiektów do przechowywania jednorazowo
wprowadzonego kodu PIN
#include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024;
/*****************************************************************/
/* Local variables */
/*****************************************************************/
static const ascii * hand_name = “kod pin w pamieci lash”;
/*****************************************************************/
/* Local functions */
/*****************************************************************/
void SimHandler ( u8 Event )
{
TRACE (( 1, “Embedded : SimHandler, Event=%d”,Event ));
switch (Event){
case ADL_SIM_EVENT_FULL_INIT:
adl_atSendResponse ( ADL_AT_UNS, “karta SIM zainicjalizowana\n\r”
);
break ;
case ADL_SIM_EVENT_PIN_OK:
adl_atSendResponse ( ADL_AT_UNS, “SIM PIN ok\n\r” );
break ;
}//end switch
}//end simHandler
void Fun_pin (adl_atCmdPreParser_t * param) {
ascii * pin;
TRACE((1,”W Fun_pin”));
if (param->Type == ADL_CMD_TYPE_PARA){
pin = ADL_GET_PARAM ( param, 0 ); //pobierz parametr komendy PIN
TRACE (( 3,pin));
TRACE((3,”Strlen of pin = %d”, strlen (pin) ));
}
if (pin!=NULL){
adl_lhWrite ( hand_name, 0, wm_strlen(pin)+1, (u8 *) pin ); //zapisz
pin do p.lash
adl_simSubscribe (SimHandler, pin ); //wpisz PIN do karty
}
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
void Fun_del (adl_atCmdPreParser_t * param){
if ( adl_lhExist ( hand_name, 0 )>0){
adl_lhErase ( hand_name, 0 );
}
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
void adl_main ( adl_InitType_e InitType )
ELEKTRONIKA PRAKTYCZNA 7/2010
69
742297930.004.png
kurs
portu musimy jawnie wskazać, którego por-
tu te ustawienia mają dotyczyć. W tym celu
stosujemy właśnie makro ADL_AT_PORT_
TYPE() . Pierwszym argumentem jest port,
a drugim laga o znaczeniu analogicznym,
jak w przypadku wywołania „anonimowe-
go”. To samo makro zostało również wyko-
rzystane w  przypadku funkcji wysyłającej
tekst adl_atSendResponse() .
Więcej szczegółów dotyczących komend
AT wykorzystanych w przykładach znajdzie-
my dokumentacji ( Help –> Help Contents –>
Open AT Firmware Documentation –> Firm-
ware version R7.43 )
W  modułach Air Prime Q26 Pamięć
Flash podzielono na następujące obszary:
pamięć Flash obiektów,
pamięć Application and Data (A&D),
pamięć kodu aplikacji.
Pamięć Flash obiektów jest to pamięć
o  rozmiarze 384  kB (wielkość ta może
być zwiększona kosztem pamięci A&D do
1728 kB za pomocą aplikacji DWLWin) po-
zwalająca na zapisanie ponad 5000 obiek-
tów dowolnego typu, np. tablice, struktury,
zmienne. Maksymalny rozmiar pojedyncze-
go obiektu to 30 kB. W obszarze tym, w spo-
sób niewidoczny dla programisty, pracuje
mechanizm zwany Garbage Collector . Po-
woduje on równomierne wykorzystanie ca-
łego obszaru pamięci w taki sposób, że gdy
zmieniamy wartość pewnego obiektu, to nie
jest on zapisywany w tym samym obszarze
pamięci. Tak dzieje się do momentu, aż ob-
szar będzie całkowicie wykorzystany. Wtedy
zadziała Garbage Collector usuwając zwol-
nione komórki i wykonując defragmentację
pamięci. Mechanizm ten przedłuża czas ży-
cia pamięci Flash.
Obszar A&D jest również przeznaczony
na dane użytkownika, ale oprócz tego może
być wykorzystany do przechowania plików
irmware’u lub aplikacji w przypadku, gdy
korzysta się ze zdalnej aktualizacji. Obszar
ten jest dzielony z obszarem kodu aplikacji,
a jego rozmiar wynosi od 0 do 4864 kB. Za-
pisywanie danych w tym obszarze ogranicza
jedynie dostępna wielkość pamięci. Obszar
kodu aplikacji to miejsce, które jest zajęte
przez obecnie działającą aplikację. Rozmiar
tego obszaru to od 256 do 5120 kB. Propor-
cje pamięci przydzielone dla dwóch ostat-
nich obszarów można zmieniać komendą
AT+WOPEN=6 , np.:
AT+WOPEN=6
+WOPEN: 6,2560,2560
Odpowiedź zawiera ilość pamięci od-
powiednio dla pamięci A&D i  kodu apli-
kacji. Jeśli wydamy komendę: AT+WO-
PEN=6,4864 , to otrzymamy odpowiedź:
+WOPEN: 6,4864,256. Należy pamiętać, że
zmieniając proporcje pamięci powodujemy
formatowanie całego obszaru pamięci A&D
oraz kodu aplikacji. Więcej informacji moż-
na znaleźć w dokumentacji komend AT oraz
Listing 3. c.d.
{
ascii * pin;
TRACE (( 1, “Embedded Application : Main” ));
if ( adl_lhExist ( hand_name, 0 )>0){ //czy PIN zostal zapisany w p.lash
pin = (ascii *) adl_memGet (8);
wm_memset(pin, 0 ,8);
adl_lhRead ( hand_name, 0,8,(ascii *) pin);
adl_simSubscribe (SimHandler, pin ); //WPISZ pin DO KARTY
adl_memRelease (pin);
}
else {
adl_lhSubscribe (hand_name, 1);
}
adl_atCmdSubscribe (“AT+PIN”, Fun_pin, ADL_CMD_TYPE_PARA | 0x0011);
adl_atCmdSubscribe (“AT+DEL”, Fun_del, ADL_CMD_TYPE_ACT );
}
Listing 4. Przykład użycia pamięci Application & Data
#include “adl_global.h”
/*************************************************************/
/* Mandatory variables */
/*-----------------------------------------------------------*/
/* wm_apmCustomStackSize */
/*-----------------------------------------------------------*/
/*************************************************************/
const u16 wm_apmCustomStackSize = 1024*3;
/*************************************************************/
/* Local variables */
/*************************************************************/
ascii response[200]={0};
s32 cell_handle=0;
s32 event_handle=0;
/*************************************************************/
/* Local functions */
/*************************************************************/
void Status (){
adl_adState_t State;
adl_adGetState ( &State );
wm_sprintf(response,”Free memory size %d\r\n Deleted memory size\
t%d\r\n”
“Total memory size\t%d\r\nNumber of deleted items\
t%d\r\n”
“Number of allocated items\t%d\r\n”,
State.freemem,State.deletedmem,State.totalmem,State.
numdeleted,
State.numobjects);
adl_atSendResponse (ADL_AT_RSP, response);
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
void Fun_sub (adl_atCmdPreParser_t * param) {
TRACE((1,”Inside Fun-sub”));
ascii cell_s[12];
s32 cell_size;
wm_strcpy(cell_s, ADL_GET_PARAM ( param, 0 ));
cell_size = wm_atoi(cell_s);
TRACE((1,”size = %d”,cell_size));
cell_handle = adl_adSubscribe ( 1, cell_size );
TRACE((1,”cell_handle = %d”,cell_handle));
if (cell_handle>=0){
Status();
}
else {
switch (cell_handle){
case ADL_RET_ERR_ALREADY_SUBSCRIBED:
adl_atSendResponse (ADL_AT_RSP,”\r\nCell already subscribed\
r\n”);
break ;
case ADL_AD_RET_ERR_OVERFLOW:
adl_atSendResponse (ADL_AT_RSP,”\r\nOverlow\r\n”);
break ;
case ADL_RET_ERR_BAD_STATE:
adl_atSendResponse (ADL_AT_RSP,”\r\nBad State\r\n”);
break ;
}
}
}
void Fun_del (adl_atCmdPreParser_t * param){
s32 resp = adl_adDelete ( cell_handle );
TRACE((1,”Del response= %d”,resp));
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
Status();
}
void Fun_wri (adl_atCmdPreParser_t * param){
TRACE (( 1, “Fun_wri: text length %d”,param->StrLength ));
ascii * tekst;
tekst = ADL_GET_PARAM ( param, 0 );
//tekst[param->StrLength]=0;
TRACE((1,tekst));
70
ELEKTRONIKA PRAKTYCZNA 7/2010
742297930.005.png
Open AT – komendy AT, pamięć Flash
Listing 4. c.d.
if ( adl_adWrite ( cell_handle, wm_strlen(tekst), ( void *) tekst )>=0){
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
else
Całą pamięć obiektów można skasować za
pomocą komendy AT+WOPEN=3 (najpierw
jednak AT musi być zatrzymana aplikacja
Open ). Obiekty nie są natomiast kasowane
poprzez wgranie nowej aplikacji.
Na listingu 4 umieszczono przykład
użycia pamięci Application&Data . Aplikacja
tworzy kilka komend AT, dzięki czemu bę-
dzie można wygodnie obserwować procesy
związane z funkcjonowaniem pamięci .
Na początku należy wydać komendę
AT+SUB=”rozmiar” powodując zadeklaro-
wanie w pamięci komórki o zadeklarowa-
nym rozmiarze wyrażonym w bajtach. Na-
stępnie można dokonać zapisu za pomocą
komendy AT+WRITE=”dane do zapisania” .
Pamięć A&D różni się też tym od pamię-
ci obiektów, że zapis jest dokonywany se-
kwencyjnie, a więc kolejne użycie komendy
AT+WRITE spowoduje dodanie danych po
tych, które były zapisane wcześniej. Zapi-
sane wcześniej dane możemy odczytać za
pomocą funkcji AT+READ . Funkcja ta podaje
również rozmiar odczytywanej celi oraz ilość
wolnej pamięci w tej konkretnej komórce.
Na końcu odczytywanego wektora danych
jest dodawane 0, aby mógł być on wyświe-
tlony za pomocą funkcji adl_atSendRespon-
se() . W postaci komend AT zostały również
zaimplementowane funkcje formatowania
oraz kompaktowania pamięci. Rezultaty
ich działania są wyświetlane w oknie TRA-
CE przez wcześniej zadeklarowaną funkcję
event_Handler() .
Do trwałego przechowywania danych
można w niektórych przypadkach również
użyć obszaru pamięci RAM, który nie jest
zerowany po miękkim lub twardym resecie.
W celu zapoznania się z tym sposobem prze-
chowywania danych polecam stworzenie
i uruchomienie przykładu „ Persistent RAM ”,
dostępnego wśród aplikacji przykładowych,
dostarczanych wraz z IDE.
Więcej informacji na temat produktów
Sierra Wireless można znaleźć na stronach
producenta: www.sierrawireless.com lub
kontaktując się z irmą ACTE Sp. z o.o., która
jest oicjalnym dystrybutorem opisywanych
produktów oraz zapewnia pełne wsparcie
techniczne.
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_ERROR);
}
void Fun_rea (adl_atCmdPreParser_t * param){
adl_adInfo_t Dane;
if ( adl_adInfo ( cell_handle, &Dane )== OK){
wm_sprintf(response,”Rozmiar\t%d\r\nPozostalo\t%d\r\n”,Dane.
size,Dane.remaining);
adl_atSendResponse (ADL_AT_RSP,response);
wm_memcpy(response,Dane.data,Dane.size-Dane.remaining);
response[Dane.size-Dane.remaining]=0;
adl_atSendResponse (ADL_AT_RSP,response);
TRACE((1,Dane.data));
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
else
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_ERROR);
void Fun_rec (adl_atCmdPreParser_t * param){
s32 resp = adl_adRecompact ( event_handle );
TRACE((1,”Format response= %d”,resp));
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
void Fun_for (adl_atCmdPreParser_t * param){
s32 resp = adl_adFormat ( event_handle );
TRACE((1,”Format response= %d”,resp));
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK);
}
void event_Handler ( adl_adEvent_e Event, u32 Progress ){
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
//Status();
adl_atCmdSubscribe (“AT+SUB”, Fun_sub, ADL_CMD_TYPE_PARA | 0x0011);
adl_atCmdSubscribe (“AT+DEL”, Fun_del, ADL_CMD_TYPE_ACT );
adl_atCmdSubscribe (“AT+WRITE”, Fun_wri, ADL_CMD_TYPE_PARA | 0x0011);
adl_atCmdSubscribe (“AT+READ”, Fun_rea, ADL_CMD_TYPE_ACT );
adl_atCmdSubscribe (“AT+FORMAT”, Fun_for, ADL_CMD_TYPE_ACT );
adl_atCmdSubscribe (“AT+RECOMPACT”, Fun_rec, ADL_CMD_TYPE_ACT );
event_handle = adl_adEventSubscribe (&event_Handler);
}
TRACE((1,”event_Handler: Event %d progress %d”,Event,Progress));
w dokumentacji ADL w rozdziale „Memory
resources”.
Na listingu 3 umieszczono przykład uży-
cia pamięci lash obiektów do przechowy-
wania jednorazowo wprowadzonego kodu
PIN. Aplikacja wprowadza dwie komendy
AT jedną do wprowadzenia PIN-u i drugą
do jego usunięcia z pamięci. Wprowadzając
PIN do karty za pomocą komendy AT+PI-
N=”xxxx” powodujemy jego jednoczesne
zapisanie w pamięci. Jeśli jest to pierwsze
uruchomienie lub obiekt został wcześniej
usunięty, to aplikacja subskrybuje się do pa-
mięci lash, informując system operacyjny,
że będzie wykorzystywała tylko jeden obiekt.
Jeśli PIN został już raz wpisany za pomocą
komendy AT+PIN, to po każdym resecie
lub zaniku zasilania aplikacja sprawdza czy
istnieje obiekt, w którym powinien być zapi-
sany PIN, a następnie pobiera go z pamięci
za pomocą funkcji adl_lhRead() i  wpisu-
je do karty za pomocą wcześniej poznanej
funkcji adl_simSubscribe() . Proszę zwrócić
uwagę, że obiekty przy odczycie i zapisie
adresowane są od zera. Istotne jest również,
że nie musimy znać wielkości obiektu w mo-
mencie subskrypcji pamięci lash, dopiero
w momencie jego zapisu do pamięci. W apli-
kacji zostało również pokazane dynamiczne
przydzielanie i  zwalnianie pamięci RAM.
Adrian Chrzanowski
Acte sp. z o.o.
R
E
K
L
A
M
A
elektronikaB2B.pl
ELEKTRONIKA PRAKTYCZNA 7/2010
71
742297930.001.png
 
Zgłoś jeśli naruszono regulamin