GSM_w_elektronice_cz6.pdf

(700 KB) Pobierz
Elektronika Praktyczna
kurs
w elektronice (6)
Obsługa portu szeregowego,
biblioteka WIP
Dodatkowe materiały
na CD i FTP
W  poprzednim odcinku pokazaliśmy, jak z  poziomu aplikacji
stosować komendy AT oraz zapoznaliśmy się z  różnymi metodami
przechowywania danych w  pamięci modemu. W kolejnym odcinku
zajmiemy się obsługą portów szeregowych, a  także opiszemy
bibliotekę internetoweą WIP (Wavecom IP).
Dodatkowe informacje:
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.
Porty szeregowe (UART1, UART2, USB)
w modułach AirPrime Q26 mają dwa tryby
pracy: tryb komend oraz tryb danych. W po-
przednich odcinkach kursu wysyłaliśmy
z aplikacji dane przez port szeregowy, ale
nie potrailiśmy pobierać danych inaczej,
niż przekazując je do aplikacji za pomocą
utworzonych przez nas komend AT. Właśnie
w ten sposób działa tryb komend ( command
mode ). System przyjmuje i interpretuje tylko
dane zaczynające się od przedrostka „AT”.
Natomiast tryb danych ( data mode ) pozwala
na pobieranie przez aplikację dowolnych da-
nych, dzięki czemu modem może komuniko-
wać się z innymi urządzeniami, np. odbior-
nikami GPS wysyłającymi dane o  pozycji
w postaci tekstowych ramek NMEA.
bować się nie tylko do portów szeregowych,
ale również obsługiwać strumienie danych
dla połączeń CSD oraz GPRS. Strukturę blo-
kową FCM pokazano na rysunku 1 .
Tryb pracy command mode jest cechą je-
dynie portów szeregowych, które mogą być
przełączane pomiędzy tryby command data .
Na rysunku 1 symbolizuje to przełącznik „1”.
Podczas transmisji CSD i GPRS tryb komend
nie może być używany, a przełącznik „2” na
schemacie informuje, że oba strumienie da-
nych nie mogą być obsługiwane jednocześnie.
Domyślnie, gdy w modemie nie ma aplikacji
Open AT lub aplikacja nie subskrybuje się do
FCM, zachowanie się portów i strumieni CSD
oraz GPRS jest kontrolowane przez oprogramo-
wanie modemu i wygląda to następująco:
– dane CSD dla wywołanego połączenia
GSM CSD są kierowane do portu szere-
gowego, który zainicjował połączenie
(ATD) lub dzięki któremu zostało ono
odebrane (ATA).
– dane sesji GPRS są kierowane na port
szeregowy, z  użyciem którego została
ona zainicjowana (komenda AT+CGDA-
TA lub ATD).
Na listingu 1 pokazano przykłado-
wy program wykorzystujący mechanizm
FCM do obsługi portu szeregowego. Przed
uruchomieniem należy upewnić się czy
UART2 jest włączony (włączanie – komen-
da AT+WMFM=0,1,2). Aplikacja subskry-
buje się do portu UART2 za pomocą funkcji
adl_fcmSubscribe() . Gdy subskrybcja powie-
dzie się, to automatycznie zostanie wywo-
łana funkcja Uart2_fun() z obsługą zdarze-
nia ADL_FCM_EVENT_FLOW_OPENNED .
To spowoduje przełączenie portu w  tryb
danych. Dodatkowo, utworzono komendę
AT+TEST , która wysyła ustalony ciąg zna-
ków do portu UART2.
Flow Control Manager
Do obsługi portów w trybie danych służy
mechanizm o nazwie Flow Controll Manager
(FCM). Za pomocą FCM możemy zasubskry-
rysunek 1. schemat blokowy Flow Control Manager
126
ELEKTRONIKA PRAKTYCZNA 8/2010
Technologia GSM
742297878.051.png 742297878.062.png 742297878.068.png 742297878.069.png 742297878.001.png 742297878.002.png 742297878.003.png 742297878.004.png 742297878.005.png 742297878.006.png 742297878.007.png 742297878.008.png 742297878.009.png 742297878.010.png 742297878.011.png 742297878.012.png 742297878.013.png 742297878.014.png 742297878.015.png 742297878.016.png 742297878.017.png 742297878.018.png 742297878.019.png
Technologia GSM w elektronice
Listing 1. Program wykorzystujący mechanizm FCM do obsługi portu szeregowego
#include “adl_global.h”
const u16 wm_apmCustomStackSize = 1024;
u8 H_Uart2;
bool Uart2_fun (u8 event)
{
switch (event){
case ADL_FCM_EVENT_FLOW_OPENNED:
TRACE((1,”UART2 otwarty”));
adl_fcmSwitchV24State(H_Uart2, ADL_FCM_V24_STATE_DATA); //przelacz w tryb data
break;
case ADL_FCM_EVENT_V24_DATA_MODE:
TRACE((1,”UART2 - data mode”));
break;
case ADL_FCM_EVENT_V24_AT_MODE:
adl_atSendResponse(ADL_AT_PORT_TYPE (ADL_PORT_UART2, ADL_AT_RSP), “Uart2_AT mode\n\r”);
adl_fcmUnsubscribe(H_Uart2);
break;
}
returnTRUE;
}
boolUart2_data(u16DataLen,u8*Data)
{
asciibufor[50];
wm_memset(bufor,0,50);
wm_memcpy(bufor,Data,DataLen);
TRACE((1,”datalength=%d”,DataLen));
bufor[DataLen]=0;
TRACE((1,bufor));
adl_atSendResponse(ADL_AT_PORT_TYPE(ADL_PORT_UART1,ADL_AT_RSP),“\n\rUART2Data:”);
adl_atSendResponse(ADL_AT_PORT_TYPE(ADL_PORT_UART1,ADL_AT_RSP),bufor);
returnTRUE;
}
voidFun_test(adl_atCmdPreParser_t*paras)
{
ascii * test_string=”\r\nUART2 data mode test\r\n”;
if (paras->Type == ADL_CMD_TYPE_ACT) {
adl_fcmSendData(H_Uart2, test_string, strlen(test_string));
adl_atSendStdResponse(ADL_AT_RSP,ADL_STR_OK);
}
}
void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));
adl_atCmdSubscribe(“AT+TEST”, Fun_test, ADL_CMD_TYPE_ACT);
H_Uart2 = adl_fcmSubscribe(ADL_PORT_UART2, Uart2_fun, Uart2_data);
}
Listing 2. Program wykorzystujący bibliotekę WIP
#include “adl_global.h”
#include “wip.h”
//Mandatoryvariables
//wm_apmCustomStackSize
constu16wm_apmCustomStackSize=1024;
//Localvariables
wip_bearer_tbearer_handle;
//Localfunctions
voidevh_bearer(wip_bearer_tb,s8event,void*ctx)//--
{
asciiIpAddr[16];
wip_in_addr_tappIpAddr;
asciistring[100];
s8bearer_ans;
switch(event)
{
caseWIP_BEV_IP_CONNECTED:
adl_atSendResponse(ADL_AT_RSP,“WIP:connectedOK:jestemwevh_bearer\r\n”);
//ThisAPIprovidesIPinnetworkformat(i.eu32number)
wip_bearerGetOpts(b,WIP_BOPT_IP_ADDR,&appIpAddr,WIP_BOPT_END);
//ThisAPIconvertstheu32IPaddresstoadottednotationIPaddress.
wip_inet_ntoa(appIpAddr,IpAddr,16);
wm_sprintf(string,”WIP:IP%s\r\n”,IpAddr);
adl_atSendResponse(ADL_AT_RSP,string);
break;
caseWIP_BEV_IP_DISCONNECTED:
adl_atSendResponse(ADL_AT_UNS,“WIP:disconnected\r\n”);
break;
caseWIP_BEV_CONN_FAILED:
adl_atSendResponse(ADL_AT_UNS,“WIP:WIP_BEV_CONN_FAILED\r\n”);
break;
caseWIP_BEV_STOPPED:
bearer_ans=wip_bearerClose(bearer_handle);
TRACE((1,”Fun_close:wip_bearerClose=%d”,bearer_ans));
break;
default:
adl_atSendResponse(ADL_AT_UNS,“WIP:othererror\r\n”);
break;
}
}
voidFun_start(adl_atCmdPreParser_t*param){
s8wynik;
ELEKTRONIKA PRAKTYCZNA 8/2010
127
742297878.020.png
kurs
Listing 2. c.d.
ascii*GPRS_APN;
ascii*GPRS_USER;
ascii*GPRS_PASSWORD;
TRACE((1,”WFun_start”));
if(param->Type==ADL_CMD_TYPE_PARA){
GPRS_APN=ADL_GET_PARAM(param,0);
TRACE((3,GPRS_APN));
GPRS_USER=ADL_GET_PARAM(param,1);
TRACE((3,GPRS_USER));
GPRS_PASSWORD=ADL_GET_PARAM(param,2);
TRACE((3,GPRS_PASSWORD));
wynik=wip_bearerOpen(&bearer_handle,“GPRS”,evh_bearer,NULL);
TRACE((1,”Fun_start:wip_bearerOpen=%d”,wynik));
wynik=wip_bearerSetOpts(bearer_handle,
WIP_BOPT_GPRS_APN,GPRS_APN,
WIP_BOPT_LOGIN,GPRS_USER,
WIP_BOPT_PASSWORD,GPRS_PASSWORD,WIP_BOPT_END);
TRACE((1,”Fun_start:wip_bearerSetOpts=%d”,wynik));
wynik=wip_bearerStart(bearer_handle);
TRACE((1,”Fun_start:wip_bearerStart=%d”,wynik));
adl_atSendStdResponse(ADL_AT_RSP,ADL_STR_OK);
}
}
voidFun_close(adl_atCmdPreParser_t*paras)
{
s8wynik;
wynik=wip_bearerStop(bearer_handle);
TRACE((1,”Fun_close:wip_bearerStop=%d”,wynik));
adl_atSendStdResponse(ADL_AT_RSP,ADL_STR_OK);
}
voidadl_main(adl_InitType_eInitType)
{
TRACE((1,“EmbeddedApplication:Main”));
wip_netInit();
adl_atCmdSubscribe(“AT+START”,Fun_start,ADL_CMD_TYPE_PARA|0x0031);
adl_atCmdSubscribe(“AT+CLOSE”, Fun_close, ADL_CMD_TYPE_ACT);
}
Listing 3. Przykład programu nawiązującego połączenie w trybie TCP Client
#include “adl_global.h”
#include “wip.h”
const u16 wm_apmCustomStackSize = 1024;
wip_bearer_t bearer_handle;
u8 H_Uart2;
wip_channel_t client, destination;
bool Uart2_fun (u8 event)
{
switch (event){
case ADL_FCM_EVENT_FLOW_OPENNED:
TRACE((1, “Uart2_Opened”));
adl_fcmSwitchV24State(H_Uart2, ADL_FCM_V24_STATE_DATA);
break;
case ADL_FCM_EVENT_V24_DATA_MODE:
TRACE((1,“Uart2_Datamode”));
break;
caseADL_FCM_EVENT_V24_AT_MODE:
TRACE((1,“Uart2_AT_mode”));
break;
}
returnTRUE;
}
boolUart2_data(u16DataLen,u8*Data)
{
wip_write(destination,Data,DataLen);
returnTRUE;
}
staticvoidClientHandler(wip_event_t*ev,void*ctx)
{
asciibuffer[256];
ascii*init_msg=“HalozklientaWIP\n\r”;
intnread=0;
intnwrite=0;
switch(ev->kind){
caseWIP_CEV_OPEN:
destination=ev->channel;
break;
caseWIP_CEV_PEER_CLOSE:
wip_close(ev->channel);
break;
caseWIP_CEV_READ:
while((nread=wip_read(ev->channel,buffer,sizeof(buffer)))>0)
adl_fcmSendData(H_Uart2,(u8*)buffer,nread);
break;
caseWIP_CEV_WRITE:
nwrite=wip_write(ev->channel,init_msg,sizeof(init_msg));//tekstpowitalny
break;
}
}
staticvoidinalizer(void*ctx){
}
voidevh_bearer(wip_bearer_tb,s8event,void*ctx)//--
wip_bearerStop(bearer_handle);//socketzamkniety,zamknijterazpolaczenie
128
ELEKTRONIKA PRAKTYCZNA 8/2010
742297878.021.png
Technologia GSM w elektronice
Listing 3. c.d.
{
asciiIpAddr[16];
wip_in_addr_tappIpAddr;
asciistring[100];
s8bearer_ans;
switch(event)
{
caseWIP_BEV_IP_CONNECTED:
adl_atSendResponse(ADL_AT_RSP,“WIP:connectedOK:jestemwevh_bearer\r\n”);
wip_bearerGetOpts(b,WIP_BOPT_IP_ADDR,&appIpAddr,WIP_BOPT_END);
wip_inet_ntoa(appIpAddr,IpAddr,16);
wm_sprintf(string,”WIP:IP%s\r\n”,IpAddr);
adl_atSendResponse(ADL_AT_RSP,string);
H_Uart2=adl_fcmSubscribe(ADL_PORT_UART2,Uart2_fun,Uart2_data);
client=wip_TCPClientCreateOpts(“172.29.0.51”,1000,ClientHandler,NULL,WIP_COPT_FINALIZER,
inalizer,WIP_COPT_END);
break;
caseWIP_BEV_IP_DISCONNECTED:
adl_atSendResponse(ADL_AT_UNS,“WIP:disconnected\r\n”);
break;
caseWIP_BEV_CONN_FAILED:
adl_atSendResponse(ADL_AT_UNS,“WIP:WIP_BEV_CONN_FAILED\r\n”);
break;
caseWIP_BEV_STOPPED:
bearer_ans=wip_bearerClose(bearer_handle);
TRACE((1,”Fun_close:wip_bearerClose=%d”,bearer_ans));
adl_atSendStdResponse(ADL_AT_RSP,ADL_STR_OK);
break;
default:
adl_atSendResponse(ADL_AT_UNS,“WIP:othererror\r\n”);
break;
}
}
voidFun_start(adl_atCmdPreParser_t*param){
s8wynik;
ascii*GPRS_APN;
ascii*GPRS_USER;
ascii*GPRS_PASSWORD;
TRACE((1,”WFun_start”));
if(param->Type==ADL_CMD_TYPE_PARA){
GPRS_APN=ADL_GET_PARAM(param,0);
TRACE((3,GPRS_APN));
GPRS_USER=ADL_GET_PARAM(param,1);
TRACE((3,GPRS_USER));
R
E
K
L
A
M
A
ELEKTRONIKA PRAKTYCZNA 8/2010
129
742297878.022.png 742297878.023.png 742297878.024.png 742297878.025.png 742297878.026.png 742297878.027.png 742297878.028.png 742297878.029.png 742297878.030.png 742297878.031.png 742297878.032.png 742297878.033.png 742297878.034.png 742297878.035.png 742297878.036.png 742297878.037.png 742297878.038.png 742297878.039.png 742297878.040.png 742297878.041.png 742297878.042.png 742297878.043.png 742297878.044.png 742297878.045.png 742297878.046.png 742297878.047.png 742297878.048.png 742297878.049.png 742297878.050.png 742297878.052.png 742297878.053.png 742297878.054.png 742297878.055.png 742297878.056.png 742297878.057.png 742297878.058.png 742297878.059.png 742297878.060.png 742297878.061.png 742297878.063.png 742297878.064.png 742297878.065.png 742297878.066.png
kurs
Listing 3. c.d.
GPRS_PASSWORD=ADL_GET_PARAM(param,2);
TRACE((3,GPRS_PASSWORD));
wynik=wip_bearerOpen(&bearer_handle,“GPRS”,evh_bearer,NULL);
TRACE((1,”Fun_start:wip_bearerOpen=%d”,wynik));
wynik=wip_bearerSetOpts(bearer_handle,
WIP_BOPT_GPRS_APN,GPRS_APN,
WIP_BOPT_LOGIN,GPRS_USER,
WIP_BOPT_PASSWORD,GPRS_PASSWORD,WIP_BOPT_END);
TRACE((1,”Fun_start:wip_bearerSetOpts=%d”,wynik));
wynik=wip_bearerStart(bearer_handle);
TRACE((1,”Fun_start:wip_bearerStart=%d”,wynik));
adl_atSendStdResponse(ADL_AT_RSP,ADL_STR_OK);
}
}
voidFun_close(adl_atCmdPreParser_t*paras)
{
s8wynik;
wynik=wip_bearerStop(bearer_handle);
wynik=wip_close(client);
TRACE((1,”Fun_close:wip_close=%d”,wynik));
adl_fcmUnsubscribe(H_Uart2);
}
voidadl_main(adl_InitType_eInitType)
{
TRACE((1,“EmbeddedApplication:Main”));
wip_netInit();
adl_atCmdSubscribe(“AT+START”,Fun_start,ADL_CMD_TYPE_PARA|0x0031);
adl_atCmdSubscribe(“AT+CLOSE”,Fun_close,ADL_CMD_TYPE_ACT);
}
Aby przetestować działanie aplikacji,
należy podłączyć się do UART2 poprzez np.
Hyper Terminal. Każdy znak wysłany do por-
tu UART2 zostanie odebrany przez aplikację,
a następnie zostanie wysłane powiadomie-
nie na UART1.
Zauważmy, że w  funkcji adl_main() ,
oprócz funkcji tworzących komendy AT, znaj-
duje się również funkcja wip_netInit(), która
jest niezbędna do zainicjowania pracy biblio-
teki WIP. Jest to standardowy sposób inicjaliza-
cji biblioteki z parametrami domyślnymi. Gdy
chcemy zmienić niektóre z parametrów stan-
dardowych (np. maksymalną liczbę otwartych
socketów), to wykorzystujemy funkcję wip_ne-
tInitOpts(). Obowiązkowa jest również dyrek-
tywa #include “wip.h ” dołączająca nagłówek
biblioteki WIP do aplikacji.
Wewnątrz funkcji Fun_start() umieszczo-
no sekwencję zestawiającą połączenie GPRS.
Zdarzenia z tym związane są przekazywane
funkcji wskazanej poprzez wip_bearerOpen(),
czyli w naszym przypadku jest to evh_bearer() .
Gdy aplikacja otrzyma zdarzenie WIP_BEV_IP_
CONNECTED, to oznacza, że połączenie zo-
stało nawiązane. To właśnie w sekcji pod tym
zdarzeniem można umieścić funkcję, która na
przykład otworzy socket TCP lub rozpocznie
otwieranie połączenia FTP.
Na listingu 3 zamieszczono aplikację, któ-
ra jest modyikacją poprzedniej. Jej zadaniem
jest nawiązanie połączenia GPRS, a następnie
połączenia TCP Client do zadanego adresu IP.
Równolegle otwarty zostaje UART2 w trybie
transmisji danych ( data mode ). Komunikacji
przez UART2 jest dwukierunkowa.
W porównaniu z programem z listingu 2,
po otrzymaniu zdarzenia IP_BEV_IP_CON-
NECTED nawiązywane jest połączenie TCP
Client za pomocą funkcji wip_TCPClientCre-
ateOpts(). Jako argumenty podawane są: adres
IP hosta, numer portu, a także funkcja Clien-
tHandler() , która zostanie wywołana, gdy wy-
stąpi jakieś zdarzenie związane z tym połą-
czeniem. Dodatkowo (jako opcja) podana jest
funkcja inalizer() . Funkcja ta zostanie wywoła-
na przez system operacyjny w momencie, gdy
po użyciu funkcji wip_close() zostaną zwolnio-
ne wszystkie wcześniej przydzielone temu po-
łączeniu zasoby. Zatem po wydaniu komendy
AT+CLOSE najpierw zostanie zamknięty soc-
ket TCP. Dopiero po jego zamknięciu funkcja
inalizer() zacznie zamykać połączenie GPRS.
Przyjrzyjmy się jeszcze zdarzeniom, które
są obsługiwane przez funkcję ClientHandler() .
Zdarzenie WIP_CEV_OPEN zachodzi zaraz po
tym, jak zostanie nawiązane połączenie TCP
z hostem. Prawie równocześnie zachodzi zda-
rzenie WIP_CEV_WRITE oznaczające, że bufor
nadawczy jest gotowy do przyjmowania da-
nych. To zdarzenie zajdzie też w sytuacji, gdy
wysyłamy dużą ilość danych szybciej, niż łą-
cze GPRS jest w stanie je wysłać. Wtedy bufor
zapełni się i funkcja zapisu wip_write() zwróci
0 jako ilość wysłanych danych. Oznacza to, że
bufor jest pełny i z dalszym wysyłaniem mu-
simy się wstrzymać do kolejnego wystąpienia
WIP_CEV_WRITE .
Zdarzenie WIP_CEV_READ zajdzie w mo-
mencie, gdy w  buforze odbiorczym znajdą
się dane do odczytu. To zdarzenie będzie się
pojawiało za każdym razem, gdy modem od-
bierze nowe dane poprzez GPRS. Zdarzenie
WIP_CEV_PEER_CLOSE oznacza, że nasze po-
laczenie zostało zamknięte przez drugą stronę.
W celu prześledzenia sposobu efektywnego
obsługiwania powyższego zdarzenia w przypad-
ku, gdy przesyłamy duże ilości danych, propo-
nuję zapoznać się z aplikacją tcp_client dostępną
jako aplikacja przykładowa w środowisku M2M
Studio.
Aplikacja serwera TCP różniłaby się od
zaprezentowanej jedynie komendą otwiera-
jącą socket. Zamiast wip_TCPClientCreate-
Opts(), należałoby użyć funkcji wip_TCP-
ServerCreate() . Utworzenie takiej aplikacji
zalecam jako temat samodzielnego treningu.
Oczywiście można się wspomóc aplikacją
tcp_serwer , którą producent dołączył do IDE
jako przykład programu użytkowego.
Adrian Chrzanowski
Acte sp. z o.o.
Internetowa biblioteka WIP
Jak wspomniałem wcześniej, mechanizmu
FCM można również użyć do obsługi strumie-
ni CSD oraz GPRS. Jeśli w przypadku CSD uży-
cie mechanizmu FCM wydaje się zasadne, to
dla GPRS byłoby o wiele bardziej skompliko-
wane i wiązałoby się na przykład z konieczno-
ścią samodzielnego formowania ramek TCP/IP.
W takiej sytuacji z pomocą przychodzi dostęp-
na w środowisku biblioteka internetowa WIP.
Pozwala ona na obsługę protokołów DHCP,
NAT, ICMP, TCP, UDP, FTP, HTTP, POP3, SMTP,
SNMP oraz na wysyłanie MMS-ów. Biblioteka
jest dostępna w IDE w postaci pluginu o na-
zwie WIP i może być dołączona do projektu na
etapie jego tworzenia (za pomocą kreatora) lub
w dowolnym momencie, gdy zdecydujemy, że
jest ona potrzebna ( Project –> Properties –>
Open AT Application –> Plugin ). Opis bibliote-
ki, w którym znajdziemy m.in. opis funkcji API
oferowanych przez WIP, znajdziemy w doku-
mentacji M2M Studio ( Help –> Help Contents
–> Plug-ins Documentation –> WIP Open AT
Plug-in Package ).
Na listingu 2 zamieszczono przykładowy
program wykorzystujący bibliotekę WIP. Jej za-
daniem jest nawiązanie połączenia GPRS przy
użyciu biblioteki WIP.
Aplikacja tworzy dwie komendy AT – jed-
ną do nawiązywania sesji GPRS (AT+START),
a drugą do jej zamykania (AT+CLOSE). Ko-
menda AT+START jako argumenty przyjmuje
nazwę APN oraz opcjonalne login i hasło. Każ-
dorazowo po nawiązaniu połączenia z APN
wyświetlany jest adres IP przydzielony karcie
SIM.
130
ELEKTRONIKA PRAKTYCZNA 8/2010
742297878.067.png
Zgłoś jeśli naruszono regulamin