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
i
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
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
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
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
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
Plik z chomika:
insane2t
Inne pliki z tego folderu:
GSM_dla_elektronice_cz1.pdf
(421 KB)
GSM_w_elektronice_cz2.pdf
(4320 KB)
GSM_w_elektronice_cz3.pdf
(917 KB)
GSM_w_elektronice_cz4.pdf
(696 KB)
GSM_w_elektronice_cz5.pdf
(412 KB)
Inne foldery tego chomika:
APARATURA pomiarowa
ARDUINO
Automatyka i PLC
CadSoft EAGLE
Czasopisma
Zgłoś jeśli
naruszono regulamin