GSM_w_elektronice_cz4.pdf

(696 KB) Pobierz
Elektronika Praktyczna
Kurs
w elektronice (4)
Programowanie w Open AT
Dodatkowe materiały
na CD i FTP
W  poprzednim odcinku naszego cyklu zapoznaliśmy się ze
środowiskiem programistycznym oraz dostępnymi dla programisty
narzędziami. Stworzyliśmy również pierwsza prostą aplikację. Teraz
przyszła kolej na dalsze poznawanie możliwości Open AT.
W kolejnym kroku spróbujmy napisać
aplikację, która wpisuje do karty PIN oraz
tworzy własną komendę AT pozwalającą
wysłać SMS na wskazany numer. Tę apli-
kację potraktujmy jako ćwiczenie i pomiń-
my fakt, że istnieje gotowa komenda AT,
która na to pozwala. Przykład realizacji
postawionego wyżej zadania umieszczono
na list.   2 .
Aplikacja najpierw wpisuje kod PIN
za pomocą funkcji adl_simSubscribe() .
Następnie czeka do momentu, aż kar-
ta SIM będzie w  pełni zainicjalizowana
( ADL_SIM_STATE_FULL_INIT ). Wtedy sub-
skrybuje się do serwisu SMS oraz tworzy
nową komendę AT+WYSLIJ . Wystąpienie
zdarzenia ADL_SIM_STATE_FULL_INIT nie
oznacza jednak, że moduł zdążył się już za-
łogować do sieci. Aby nasza aplikacja dzia-
łała niezawodnie, należałoby sprawdzić
stan zalogowania komendą AT+CREG?
Takie rozwiązanie zostanie przedstawione
w następnym odcinku cyklu, tymczasem
w tym odcinku będziemy sprawdzać jedy-
nie wystąpienie zdarzenia ADL_SIM_STA-
TE_FULL_INIT.
Na początek zajmiemy się zagadnie-
niem obsługi karty SIM. Moduły GSM,
podobnie jak telefony komórkowe, do pra-
widłowej pracy w sieci potrzebują karty
SIM. Open AT daje programiście możliwość
wprowadzenia kodów PIN i PUK związa-
nych z kartą SIM oraz sprawdzenia statu-
su karty. Stwórzmy zatem nową aplikację,
która będzie automatycznie wpisywała PIN
oraz wyświetlała status karty. Sposób two-
rzenia aplikacji został dokładniej omówio-
ny w poprzednim odcinku cyklu (dla przy-
pomnienia z menu File wybieramy New ,
a potem Open AT Project ).
Zwróćmy uwagę, że inicjalizacja karty
chwilę trwa i zdarzenie ADL_SIM_EVENT_
FULL_INIT zostaje wyświetlone dopiero po
pewnym czasie. Ze względu na chęć mak-
symalnego uproszczenia, w aplikacji nie
zawarłem obsługi wszystkich możliwych
zdarzeń związanych z kartą SIM. Zostały
one dokładnie omówione w dokumentacji
(„Open AT ADL Development Guide”, Help
–> Help Contents –> Open AT Embedded
Software Suite package version 6.32 ). Moż-
na je również zobaczyć, zaznaczając jedno
ze zdarzeń i naciskając F3. Nazwy zdarzeń
są zdeiniowane w  pliku nagłówkowym
jako struktura wyliczeniowa. W dokumen-
tacji zostały również opisane pozostałe
funkcje dotyczące karty SIM pozwalające
m.in. podać kod PUK, sprawdzić status
karty, liczbę pozostałych prób wprowadze-
nia kodu PIN lub PUK.
Obsługa karty SIM, tworzenie
nowych komend AT
Przykładową aplikację wpisującą kod
PIN przedstawiono na list.   1 .
Działanie aplikacji rozpoczyna się od
funkcji adl_main() , w  której jest wpisy-
wany kod PIN oraz inicjowana karta SIM
i zostaje wskazana funkcja, która będzie
wywoływana, gdy wystąpi zdarzenie zwią-
zane z kartą SIM (w przypadku karty bez
numeru PIN należy jako drugi argument
funkcji adl_simSubscribe() podać NULL ).
Inicjalizacja karty wymaga trochę czasu.
Widać to po kolejnych wywołaniach funk-
cji SimHandler() z różnymi zdarzeniami.
Jeśli podano poprawny kod PIN, to
aplikacja przez interfejs RS232 prześle na-
stępujący ciąg komunikatów:
OK
ADL_SIM_EVENT_INSERTED
ADL_SIM_EVENT_PIN_OK
ADL_SIM_EVENT_FULL_INIT
List. 1. sposób obsługi karty sIM
#include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
ascii * PinCode = “9172”; //tu wpisać właściwy PIN
void SimHandler (u8 Event){
TRACE (( 1, “Funkcja SimHandler: Event=%d”,Event ));
switch (Event){
case ADL_SIM_EVENT_REMOVED: //< SIM removed event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_REMOVED\r\n”);
break ;
case ADL_SIM_EVENT_INSERTED: //< SIM inserted event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_INSERTED \r\n”);
break ;
case ADL_SIM_EVENT_FULL_INIT: //< SIM Full Init done event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_FULL_INIT\r\n”);
break ;
case ADL_SIM_EVENT_PIN_ERROR: //< Wrong PUK input event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_PIN_ERROR\r\n”);
break ;
case ADL_SIM_EVENT_PIN_OK: //< PIN code OK event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_PIN_OK\r\n”);
break ;
case ADL_SIM_EVENT_PIN_WAIT: //< PIN wait event
adl_atSendResponse ( ADL_AT_RSP, “\r\n ADL_SIM_EVENT_PIN_WAIT\r\n”);;
break ;
}//end switch
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Funkcja Main” ));
adl_simSubscribe ( SimHandler, PinCode );
}
Tab. 1. Parametry funkcji adl_atCmd-
Subscribe
Parametr Przykład komendy
ADL_CMD_TYPE_PARA AT+cmd=x, y
ADL_CMD_TYPE_TEST AT+cmd=?
ADL_CMD_TYPE_READ AT+cmd?
ADL_CMD_TYPE_ACT AT+cmd
92
ELEKTRONIKA PRAKTYCZNA 6/2010
Technologia GSM
742297974.015.png 742297974.016.png 742297974.017.png 742297974.018.png
Programowanie w Open AT
Subskrypcja do lokalnej
usługi SMS za pomocą adl_sms-
Subscribe() polega na wskaza-
niu dwóch funkcji oraz trybu,
w jakim chcemy wysyłać SMS-y.
Pierwsza ze wskazywanych funk-
cji będzie wywołana przez system
w momencie, gdy nasze urządze-
nie odbierze SMS. Zmiennymi
wejściowymi tej funkcji są ciągi
znaków zawierające numer tele-
fonu, od którego otrzymaliśmy
wiadomość oraz jej treść. W opi-
sywanej aplikacji są one po sfor-
matowaniu wysyłane przez port
szeregowy. Wartość zwracana
przez funkcję (w  naszym przy-
padku ADL_SMS_FILTER_INDICA-
TION_AND_DELETE ) mówi, czy
SMS ma zostać zapisany na kar-
cie SIM, a powiadomienie o jego
otrzymaniu ( +CMTI ) wysłane
przez port szeregowy.
Druga z funkcji, które podaje-
my jako argument adl_smsSubscri-
be() , to funkcja kontrolna. Jest wy-
woływana, gdy nasze urządzenie
wysłało SMS. Zmienna wejścio-
wa tej funkcji mówi o tym, jakim
rezultatem zakończył się proces
wysyłania – powodzeniem lub błę-
dem (nie należy mylić z raportem
o doręczeniu). Informacje przeka-
zywane przez tę funkcję są takie
same, jak zwykle obserwowane
na ekranie telefonu komórkowego,
a mówiące o tym, czy SMS został wysłany
pomyślnie.
Nową komendę AT tworzy funkcja
adl_atCmdSubscribe() . Jako jej argumenty
podaje się:
– ciąg znakowy będący treścią komendy
(musi zaczynać się od „AT”),
– funkcję, która zostanie wywołana, jeśli
komenda będzie odebrana przez który-
kolwiek z aktywnych portów szerego-
wych,
List. 2. sposób tworzenia nowej komendy AT
#include „adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
ascii * PinCode = „9172”;
s8 sms_handle;
bool SmsHandler ( ascii * SmsTel, ascii * SmsTimeOrLength, ascii * SmsText ){
ascii tekst[0x50];
wm_sprintf (tekst,” Numer telefonu: %s \n\r”,SmsTel );
adl_atSendResponse ( ADL_AT_UNS, tekst );
wm_sprintf (tekst,” Tresc wiadomosci: %s \n\r”,SmsText );
adl_atSendResponse ( ADL_AT_UNS, tekst );
return ADL_SMS_FILTER_INDICATION_AND_DELETE;
}
void SmsCtrlHandler (u8 Event, u16 Nb)
{
if (Event == ADL_SMS_EVENT_SENDING_ERROR)
adl_atSendResponse ( ADL_AT_UNS, „\r\n SMS nie zostal wyslany\r\n” );
else if (Event == ADL_SMS_EVENT_SENDING_OK)
adl_atSendResponse ( ADL_AT_UNS, „\r\n SMS zostal wyslany pozytywnie\r\n” );
}
void Fun_wyslij (adl_atCmdPreParser_t * param) {
ascii * NR_tel;
ascii * SMS_Content;
if (param->Type == ADL_CMD_TYPE_PARA){ //sprawdź czy wywołanie z parametrami
NR_tel = ADL_GET_PARAM ( param, 0 ); //pobierz pierwszy parametr
TRACE (( 3,NR_tel));
SMS_Content = ADL_GET_PARAM ( param, 1 ); //pobierz drugi parameter
TRACE (( 3,SMS_Content));
adl_smsSend ( sms_handle, NR_tel, SMS_Content, ADL_SMS_MODE_TEXT );
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_OK); //wyświetl OK
}
else {
adl_atSendResponse ( ADL_AT_UNS, „\r\n Tylko wywolanie z parametrami\r\n” );
adl_atSendStdResponse (ADL_AT_RSP,ADL_STR_ERROR);
}
}
void SimHandler (u8 Event){
if (Event == ADL_SIM_STATE_FULL_INIT){ //sprawdź czy karta w pelni gotowa
sms_handle = adl_smsSubscribe (SmsHandler, SmsCtrlHandler, ADL_SMS_MODE_TEXT );
adl_atCmdSubscribe („AT+WYSLIJ”, Fun_wyslij, ADL_CMD_TYPE_PARA | 0x0022);
}
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, „Embedded Application : Main” ));
adl_simSubscribe (SimHandler,PinCode);
}
– iloczyn logiczny parametrów określa-
jący, w jakich trybach może być wywo-
łana komenda.
Zestawienie parametrów określają-
cych możliwe tryby wywołania komendy
umieszczono w  tab.   1 .
Podczas tworzenia nowej komendy AT
jest możliwe ograniczenie liczby przyjmo-
wanych parametrów. Zilustrują to kolejne
dwa przykłady. Deklaracja w  postaci adl_
atCmdSubscribe(„AT+WYSLIJ”, Fun_wyslij,
ADL_CMD_TYPE_PARA|0x0022); spowoduje
utworzenie nowej komendy AT+WYSLIJ jako
komendy z parametrami. Wymagane są mini-
malnie oraz maksymalnie 2 parametry. Nie-
zgodne wywołanie komendy spowoduje, że
system odpowie błędem (komunikat ERROR ).
Jeśli chcemy, aby komenda przyjmowała co
najmniej jeden parametr, ale nie więcej niż
trzy, to deklaracja musiałaby wyglądać nastę-
pująco: adl_atCmdSubscribe(“AT+WYSLIJ”,
Fun_wyslij, ADL_CMD_TYPE_PARA | 0x0013);
R
E
K
L
A
M
A
ELEKTRONIKA PRAKTYCZNA 6/2010
93
742297974.001.png
 
Kurs
List. 3. Obsługa cyfrowych linii GPIO
include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
adl_ioDefs_t Wejscia[2];
adl_ioDefs_t Wyjscie[1];
s32 io_handle_we;
s32 io_handle_wy;
s32 GpioEventHandle;
bool Stan_diody = FALSE;
void GPIO_TELE_handler ( s32 gpio_handle, adl_ioEvent_e Event, u32 Size, void * Param )
{
ascii tekst [30] ={0};
TRACE (( 1, “Gpio event %d / %d”, Event, Size ));
// Switch on event
if ( Event == ADL_IO_EVENT_INPUT_CHANGED ) {
if (((((adl_ioDefs_t*)Param)[0]) & ADL_IO_NUM_MSK) == 19){
TRACE (( 1, “GPIO %d new value: %d”,
(((adl_ioDefs_t *)Param)[0]) & ADL_IO_NUM_MSK,
((((adl_ioDefs_t *)Param)[0] ) & ADL_IO_LEV_MSK ) & ADL_IO_LEV_HIGH ));
wm_sprintf(tekst,”\r\n Zmieniono stan GPIO 19 na %d\r\n”,
adl_ioReadSingle ( io_handle_we, &Wejscia[0]) );
adl_atSendResponse ( ADL_AT_UNS, tekst);
}
if (((((adl_ioDefs_t*)Param)[0]) & ADL_IO_NUM_MSK) == 23){
TRACE (( 1, “GPIO %d new value: %d”,
(((adl_ioDefs_t *)Param)[0] ) & ADL_IO_NUM_MSK ,
((((adl_ioDefs_t *)Param)[0] ) & ADL_IO_LEV_MSK ) & ADL_IO_LEV_HIGH ));
wm_sprintf(tekst,”\r\n Zmieniono stan GPIO 23 na %d\r\n”,
adl_ioReadSingle ( io_handle_we, &Wejscia[1] ) );
adl_atSendResponse ( ADL_AT_UNS,tekst);
}
}
}
void GPIO_TimerHandler ( u8 ID )
{
/* Hello World */
TRACE (( 1, “Embedded : GPIO_TimerHandler” ));
i f (Stan_diody){
adl_ioWriteSingle (io_handle_wy, &Wyjscie[0], TRUE);
Stan_diody = FALSE;
}
else {
adl_ioWriteSingle (io_handle_wy, &Wyjscie[0], FALSE);
Stan_diody = TRUE;
}
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
Wejscia[0] = ADL_IO_GPIO | 19 | ADL_IO_DIR_IN; //pin45
Wejscia[1] = ADL_IO_GPIO | 23 | ADL_IO_DIR_IN; //pin55
Wyjscie[0] = ADL_IO_GPIO | 24 | ADL_IO_DIR_OUT |ADL_IO_LEV_LOW; //pin58
GpioEventHandle = adl_ioEventSubscribe ( GPIO_TELE_handler );
io_handle_we = adl_ioSubscribe (2, Wejscia, ADL_TMR_TYPE_100MS, 1, GpioEventHandle );
io_handle_wy = adl_ioSubscribe ( 1, Wyjscie, 0, 0, 0 );
adl_tmrSubscribe ( TRUE, 20, ADL_TMR_TYPE_100MS, GPIO_TimerHandler );
}
Tab. 2. Parametry elektryczne cyfrowych linii I/O i wewnętrznego zasilacza
Parametr Typ I/O Minimum Typowo Maksimum Uwagi
Wewnętrzne zasilanie
2,8 V
VCC_2V8 2,74 V 2,8 V 2,86 V
na jest funkcja zdarzeniowa, która będzie
wywoływana przez system, gdy na którejś
z linii nastąpi zmiana. Podczas subskryp-
cji linii wejściowych za pomocą funkcji
adl_ioSubscribe() okres próbkowania zosta-
je ustawiony na 100 ms (najkrótszy okres
próbkowania to 18,5 ms). Na końcu funkcji
adl_main() jest wywołany cykliczny timer
o okresie 2 s, wywołujący funkcję GPIO_
TimerHandler() . W  funkcji tej stan linii
GPIO24 zostaje zmieniony na przeciwny
do przedniego. W ten sposób na tym wyj-
sciu jest generowany przebieg prostokątny
o okresie 4 s.
Funkcja zdarzeniowa GPIO_TimerHan-
dler() będzie wywoływana przez system
zawsze, gdy nastąpi zmiana na zadeklaro-
wanych liniach GPIO. Wewnątrz funkcji
następuje sprawdzenie, stan której linii
został zmieniony (możliwa jest sytuacja, że
obie linie zmienią swój stan). Stan linii po
zmianie można sprawdzić na dwa sposoby:
wykorzystując zmienną wejściową Param
lub odczytując stan linii funkcją adl_ioRe-
adSingle() .
Doprowa-
dzenie I/O
VIL CMOS –0,5 V
0,84 V
VIH CMOS 1,96 V
3,2 V IOL=–4 mA
VOL CMOS
0,4 V IOL=–4 mA
VOH CMOS 2,4 V
IOH=4 mA
IOH CMOS
4 mA
IOL CMOS
-4 mA
Obsługa cyfrowych linii GPIO
Kolejnym zagadnieniem jest obsługa
cyfrowych linii wejścia/wyjścia – GPIO.
W przedstawionym niżej przykładzie wy-
korzystano trzy linie cyfrowe. Dwie z nich
– GPIO19 i GPIO23 – pracują jako wejścia
cyfrowe, natomiast GPIO24 jako wyjście.
Linie pracują w logice CMOS z napięciem
logicznej „1” wynoszącym 2,8 V. Ich para-
metry elektryczne zamieszczono w  tab.   2 .
Przestrzegając parametrów zamiesz-
czonych w tab. 1, do linii wyjścia GPIO24
podłączymy diodę z odpowiednio dobra-
nym rezystorem, a do linii wejść cyfrowych
GPIO19 i GPIO23 prosty układ rezystorowy
z przełącznikiem, pozwalający na podawa-
nie naprzemiennie stanu niskiego lub wy-
sokiego.
Przykładową aplikację demonstru-
jącą działanie GPIO pokazano na list.   3 .
Działanie aplikacji rozpoczyna się od zde-
iniowania linii GPIO oraz nadania im od-
powiednich funkcji (dwa wejścia i jedno
wyjście). Dla linii wejściowych deiniowa-
94
ELEKTRONIKA PRAKTYCZNA 6/2010
742297974.002.png 742297974.003.png 742297974.004.png 742297974.005.png 742297974.006.png 742297974.007.png 742297974.008.png 742297974.009.png 742297974.010.png 742297974.011.png 742297974.012.png 742297974.013.png
Programowanie w Open AT
www.sklep.avt.pl
List. 4. Aplikacja łącząca obsługę GPIO i obsługę karty sIM
#include „adl_global.h”
const u16 wm_apmCustomStackSize = 1024*3;
adl_ioDefs_t Wyjscie[1];
ascii * PinCode = “9172”;
s32 io_handle_wy;
adl_ioDefs_t Wyjscie[1];
s8 sms_handle;
bool SmsHandler ( ascii * SmsTel, ascii * SmsTimeOrLength, ascii * SmsText ){
TRACE((1,”SMS Received”));
if (wm_strcmp(SmsText,”HIGH”)==0){
adl_ioWriteSingle (io_handle_wy, &Wyjscie[0], TRUE);
return ADL_SMS_FILTER_INDICATION_AND_DELETE;
}
if (wm_strcmp(SmsText,”LOW”)==0){
adl_ioWriteSingle (io_handle_wy, &Wyjscie[0], FALSE);
return ADL_SMS_FILTER_INDICATION_AND_DELETE;
}
adl_smsSend (sms_handle, SmsTel, “Niewlasciwa komenda”, ADL_SMS_MODE_TEXT );
return ADL_SMS_FILTER_INDICATION_AND_DELETE;
}
void SmsCtrlHandler (u8 Event, u16 Nb)
{
if (Event == ADL_SMS_EVENT_SENDING_ERROR)
adl_atSendResponse ( ADL_AT_UNS, “\r\n SMS nie zostal wyslany\r\n” );
else if (Event == ADL_SMS_EVENT_SENDING_OK)
}
adl_atSendResponse ( ADL_AT_UNS, “\r\n SMS zostal wyslany poprawnie\r\n” );
void SimHandler (u8 Event){
TRACE((1,”Event = %d”, Event));
if (Event == ADL_SIM_STATE_FULL_INIT) //sprawdź czy karta gotowa
sms_handle = adl_smsSubscribe (SmsHandler, SmsCtrlHandler, ADL_SMS_MODE_TEXT );
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
Wyjscie[0] = ADL_IO_GPIO | 24 | ADL_IO_DIR_OUT |ADL_IO_LEV_LOW; //pin58
io_handle_wy = adl_ioSubscribe ( 1, Wyjscie, 0, 0, 0 );
adl_simSubscribe (SimHandler,PinCode);
}
Podsumowanie
Opisane serwisy oferują znacznie więcej
możliwości, niż zostało to opisane, o czym
można się łatwo przekonać, czytając doku-
mentację biblioteki ADL – „ Open AT ADL
Development Guide” . Podsumowując ten od-
cinek, warto przedstawić aplikację łączącą
omawiane usługi: SIM, SMS i GPIO. Jej przy-
kład zamieszczono na list.   4.
Aplikacja najpierw wpisuje PIN do karty
SIM, a następnie czeka na pełną inicjalizację.
Po odebraniu SMS-a z komendą LOW lub
HIGH aplikacja ustawi odpowiednio stan wyj-
ścia GPIO24. W przypadku, gdy komenda róż-
ni się od dwóch zadeklarowanych, zostaje ode-
słany SMS o treści „ Niewlasciwa komenda ”.
Więcej informacji na temat produktów
Sierra Wireless można znaleźć na stronach
producenta: www.sierrawireless.com lub kon-
taktując się z irmą ACTE Sp. z o.o., która jest
oicjalnym dystrybutorem opisywanych pro-
duktów oraz zapewnia pełne wsparcie tech-
niczne.
Adrian Chrzanowski
Acte sp. z o.o.
R
E
K
L
A
M
A
ELEKTRONIKA PRAKTYCZNA 6/2010
95
742297974.014.png
 
Zgłoś jeśli naruszono regulamin