本文是Linux作業系統下的GPRS模組實現無線上網的功能,代碼及方法很難懂所以要耐心的讀代碼,相信你能夠學到很多。
linux下通過gprs模組撥接
首先從/usr/share/doc/ppp-2.4.4/scripts中cp ppp-on,ppp-off,ppp-on-dialer三個指令碼到/home/a/ppp。然後做如下修改:
在ppp-on裡
1.改電話號碼為*99***1#
2.將帳號與密碼清除
3.修改DIALER_SCRIPT的路徑為/home/a/ppp/ppp-on-dialer
4.把下裝置改成/dev/ttyS0,速率改為115200
5.將crtscts參數去掉,
在ppp-on-dialer裡把帳號密碼那塊去掉。
下面是對指令碼的一些說明。當然都是網上搜來的了。:-)
/home/a/ppp/ppp-on
#!/bin/sh
#
# Script to initiate a ppp connection. This is the first part of the
# pair of scripts. This is not a secure pair of scripts as the codes
# are visible with the 'ps' command. However, it is simple.
#
# These are the parameters. Change as needed.
TELEPHONE=*99***1# # The telephone number for the connection
ACCOUNT= # The account name for logon (as in 'George Burns')
PASSWORD= # The password for this account (and 'Gracie Allen')
LOCAL_IP=0.0.0.0 # Local IP address if known. Dynamic = 0.0.0.0
REMOTE_IP=0.0.0.0 # Remote IP address if desired. Normally 0.0.0.0
NETMASK=255.255.255.0 # The proper netmask if needed
#
# Export them so that they will be available at 'ppp-on-dialer' time.
export TELEPHONE ACCOUNT PASSWORD
#
# This is the location of the script which dials the phone and logs
# in. Please use the absolute file name as the $PATH variable is not
# used on the connect option. (To do so on a 'root' account would be
# a security hole so don't ask.)
#
DIALER_SCRIPT=/home/a/ppp/ppp-on-dialer
#
# Initiate the connection
#
# I put most of the common options on this command. Please, don't
# forget the 'lock' option or some programs such as mgetty will not
# work. The asyncmap and escape will permit the PPP link to work with
# a telnet or rlogin connection. You are welcome to make any changes
# as desired. Don't use the 'defaultroute' option if you currently
# have a default route to an ethernet gateway.
#
exec /usr/sbin/pppd debug lock modem /dev/ttyS0 115200 \
asyncmap 20A0000 escape FF kdebug 0 $LOCAL_IP:$REMOTE_IP \
noipdefault netmask $NETMASK defaultroute connect $DIALER_SCRIPT
exec /usr/sbin/pppd debug lock modem /dev/ttyS0 115200 \
asyncmap 20A0000 escape FF kdebug 0 $LOCAL_IP:$REMOTE_IP \
noipdefault netmask $NETMASK defaultroute connect $DIALER_SCRIPT這個命令的作用是:(可以使用man pppd查看協助)
運行/usr/sbin/pppd程式,給它傳入命令列參數的意義是:
/dev/ttyS0: 撥號所用的MODEM所串連的串口(ttyS0是串口1,ttyS1是串口2...)
115200 : MODEM的通訊速率(57600 BPS)
modem : 用MODEM進行撥號。
nocrtscts : 無流控
lock : 鎖定這個裝置
debug :輸出調試資訊
defaultroute : 此撥號連線作為預設路由
connect /home/a/ppp/ppp-on-dialer:使用/home/a/ppp/ppp-on-dialer進行撥號
/home/a/ppp/ppp-on-dialer
#!/bin/sh
#
# This is part 2 of the ppp-on script. It will perform the connection
# protocol for the desired connection.
#
exec chat -v \
TIMEOUT 3 \
ABORT '\nBUSY\r' \
ABORT '\nNO ANSWER\r' \
ABORT '\nRINGING\r\n\r\nRINGING\r' \
'' \rAT \
'OK-+++\c-OK' ATH0 \
TIMEOUT 30 \
OK AT+IPR=115200 \
OK AT+CGDCONT=1,"IP","CMNET" \
OK AT+CGACT=1,1 \
OK ATDT*99***1# \
CONNECT '' \
# ogin:--ogin: $ACCOUNT \
# assword: $PASSWORD
chat命令的協助請參考man -a chat查看。
ABORT BUSY
ABORT ERROR
ABORT NO CARRIER
ABORT NO DIALTONE
ABORT RING
OK AT+IPR=115200
OK AT+CGACT=1,1
/home/a/ppp/ppp-off
#!/bin/sh
##############################################
# Determine the device to be terminated.
#
if [ "$1" = "" ]; then
DEVICE=ppp0
else
DEVICE=$1
fi
###############################################
# If the ppp0 pid file is present then the program is #running. Stop it.
if [ -r /var/run/$DEVICE.pid ]; then
kill -INT `cat /var/run/$DEVICE.pid`
#
# If the kill did not work then there is no process running for this
# pid. It may also mean that the lock file will be left. You may wish
# to delete the lock file at the same time.
if [ ! "$?" = "0" ]; then
rm -f /var/run/$DEVICE.pid
echo "ERROR: Removed stale pid file"
exit 1
fi
#
# Success. Let pppd clean up its own junk.
echo "PPP link to $DEVICE terminated."
exit 0
fi
#
# The ppp process is not running for ppp0
echo "ERROR: PPP link is not active on $DEVICE"
exit 1
int main(void)
{
u8_t buf[MAX_READ_LEN + 1];
int len,pd;
sys_err err;
int * fd = NULL;
int *linkstateCx = NULL;
/*
*init basic parametes of ourselves
*/
GPIOInit(); //GPIO口初始化
sys_timer_init(); //系統時鐘初始化
local_sys_init(); //這裡面有串口的初始化,定時器的初始化等
lwip_init(); //lwip協議的初始化
DEBUG_EVENT("main()\r\n"); //DEBUG_EVENT是一個向串口輸出提示資訊的函數
/*
*start config GPRS Modem, such as HUAWEI GTM900, MC35i,etc.
*/
err = active_Modem(); //啟用GPRS模組
if(err NEQ SYS_ERR_OK)
{
DEBUG_EVENT("Modem open failed! we must shut down system!\r\n");
shut_system();
}
DEBUG_EVENT("Modem open successful!\r\n");
DEBUG_EVENT("System block 30 seconds!\r\n");//等待30秒,等待SIM卡找到網路
/*
*wait for GPRS Modem serching network,
* initinalize: such as SMS, Telephone Book etc.
*/
second_sleep(30);
err = init_Modem(); //寫一些基本的AT命令
if(err NEQ SYS_ERR_OK)
{
DEBUG_EVENT("Modem basic AT Commands initialize failed! we must shut down system\r\n");
shut_system();
}
DEBUG_EVENT("Modem basic AT Commands initialize successful!\r\n");
/*
*start Dial GPRS Number, such as: *99***1#
*/
start_tcpip: //start_tcpip是一個標號
err = dial_GPRS(); //撥ATD*99***1#
if(err NEQ SYS_ERR_OK)
{
DEBUG_EVENT("Dial GPRS Failed,we must shut down system!\r\n");
shut_system();
}
DEBUG_EVENT("Dial GPRS successful, now we start PPP Config!\r\n");
/*
*start config PPP,and send LCP packet to GPRS Modem
*/
pd = pppOpen((void*)fd, &pppStateCallback, (void *)linkstateCx);/*send lcp req to peer*/
while(1)
{
/*
*check if one timer is overflow, if so, run it
*/
check_sys_timer();
/*
*check the receive buffer of Modem
*/
if(get_modem_datalen() > 0)//如果modem收到資訊
{
DEBUG_EVENT(" Receive some data from Modem:\r\n");
len = get_modem_data(buf); //接收下來
pppInProc(pd, buf, len); //進行處理
}
/*
*check the receive buffer of User Equipment
*/
if(get_user_datalen() > 0) //如果使用者向modem發資訊
{
DEBUG_EVENT("Receive some data from User Eqipment!\r\n");
len = get_user_data(buf);//接收下來
if(get_Mytcpip_state() EQ UDP_ESTABLISHED)//判斷存在的是哪種串連
{
if( udp_write(buf, len) NEQ ERR_OK)
{
DEBUG_ERR("Send some data to UDP Peer, but failed!\r\n");
//add you code here.
//store the data
}
}
else if(get_Mytcpip_state() EQ TCP_ESTABLISHED))//判斷存在的是哪種串連
{
if( tcp_write(tcp_active_pcbs, (const void *)buf, len, 1) NEQ ERR_OK)
{
DEBUG_ERR("Send some data to TCP Peer, but failed!\r\n");
//add you code here.
//store the data
}
}
else
{
DEBUG_EVENT("No TCP or UDP Connect exist!drop the data\r\n");
}
}
/*
*check the state of ppp
*if the link is DEAD, I deal it very simple,
*do not release the source of PPP/TCP/IP/UDP etc.
*just call the function: lwip_init(). but it work.
*then goto the head of main func.
*The state of DCD should be checked here,but I will ignore it.
*/
if(ppp_dead(pd) EQ TRUE)//如果鏈路死去
{
lwip_init();
set_Mytcpip_state(PPP_DEAD);
goto start_tcpip; //回去重新撥號
}
/*
*check the state of my tcpip
*/
switch(get_Mytcpip_state())//檢查目前的狀態
{
case PPP_ESTABLISHED: //這個是剛握完手的狀態
if(get_sys_err() < MAX_SYS_ERR_ALLOW)
{
tcpip_open(); //所以握完手之後要開啟tcp_ip(這個函數裡可以選擇是用udp還是tcp,我選的udp)
break;
}
else
set_Mytcpip_state(TCPIP_STATE_UNKNOWN);
case TCPIP_STATE_UNKNOWN:
shut_system();
break;
default:
break;
}
}
}