嵌入式系统经常需要具备无线上网的功能,但在有的应用场景中无法使用wifi,这时可以通过GPRS模块上网。GPRS模块是基于AT命令进行控制的。对于单片机这类没有复杂操作系统的平台来说,往往要通过应用程序,直接发送AT命令给GPRS模块,以使GPRS模块连接到网络并建立TCP连接,进而完成通信。对于具有Linux、Android等系统的平台而言,则不需要自己编写程序发送AT命令,可以使用ppp服务进行拨号上网。

Linux系统下,执行man ppp,可以看到PPP的介绍。

即Point to Point Protocol,是一种用于建立通过拨号调制解调器的网络连接、DSL连接或者其它类型的点对点连接的协议。

    RIL:Radio Interface Layer。

ppp源码,并编译出ppp拨号上网所必需的可执行文件,pppd和chat。除了这两个可执行程序外,还需要一些脚本,具体的脚本如下所示:



[plain]  view plain  copy


 


    1. [root@Neolix /]# ls /etc/ppp/  -R  
    2. /etc/ppp/:  
    3. chap-secrets       ioptions           options            resolv.conf  
    4. connect-errors     ip-down            pap-secrets  
    5. gprs-connect-chat  ip-up              peers  
    6.   
    7. /etc/ppp/peers:  
    8. gprsdial


           

            ip-up:ppp拨号成功后,会调用这个脚本进行一些设置;

            ip-down:连接断开后,会调用这个脚本;

    pppd call gpradial即可实现拨号,gprs-connect-chat里是chat与gprs模块之间聊天所需的AT命令及应答。

      问题一:同样的脚本可以使3G模块正常拨号,但是2G模块拨号失败,拨号过程的信息如下:



    [plain]  view plain  copy


     

    1. pppd call gprsdial  
    2. timeout set to 15 seconds  
    3. abort on (DELAYED)  
    4. abort on (BUSY)  
    5. abort on (NO DIALTONE)  
    6. abort on (NO CARRIER)  
    7. timeout set to 40 seconds  
    8. send (AT^M)  
    9. expect (OK)  
    10. ^M  
    11. OK  
    12.  -- got it  
    13.   
    14. send (ATE0^M)  
    15. expect (OK)  
    16. ^M  
    17. ^M  
    18. OK  
    19.  -- got it  
    20.   
    21. send (AT+CGDCONT=1,"IP","CMNET"^M)  
    22. expect (OK)  
    23. ^M  
    24. ^M  
    25. OK  
    26.  -- got it  
    27.   
    28. send (AT+CGEQREQ=1,2,128,384,,,0,,,,,,^M)  
    29. expect (OK)  
    30. ^M  
    31. ^M  
    32. OK  
    33.  -- got it  
    34.   
    35. send (ATDT*98*1#^M)  
    36. expect (CONNECT)  
    37. ^M  
    38. ^M  
    39. CONNECT  
    40.  -- got it  
    41.   
    42. send (^M)  
    43. Script /sbin/chat -s -v -f /etc/ppp/gprs-connect-chat finished (pid 131), status  
    44.  = 0x0  
    45. Serial connection established.  
    46. using channel 2  
    47. Using interface ppp0  
    48. Connect: ppp0 <--> /dev/ttyS3  
    49. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    50. Warning - secret file /etc/ppp/pap-secrets has world and/or group access  
    51. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    52. No auth is possible  
    53. sent [LCP ConfRej id=0x1 <auth pap>]  
    54. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    55. No auth is possible  
    56. sent [LCP ConfRej id=0x1 <auth pap>]  
    57. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    58. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    59. No auth is possible  
    60. sent [LCP ConfRej id=0x1 <auth pap>]  
    61. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    62. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    63. No auth is possible  
    64. sent [LCP ConfRej id=0x1 <auth pap>]  
    65. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    66. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    67. No auth is possible  
    68. sent [LCP ConfRej id=0x1 <auth pap>]  
    69. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    70. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    71. No auth is possible  
    72. sent [LCP ConfRej id=0x1 <auth pap>]  
    73. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    74. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    75. No auth is possible  
    76. sent [LCP ConfRej id=0x1 <auth pap>]  
    77. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    78. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    79. No auth is possible  
    80. sent [LCP ConfRej id=0x1 <auth pap>]  
    81. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    82. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    83. No auth is possible  
    84. sent [LCP ConfRej id=0x1 <auth pap>]  
    85. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    86. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    87. No auth is possible  
    88. sent [LCP ConfRej id=0x1 <auth pap>]  
    89. sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x7ae02b5a> <pcomp> <accomp>]  
    90. rcvd [LCP ConfReq id=0x1 <asyncmap 0xa0000> <auth pap> <pcomp> <accomp>]  
    91. No auth is possible  
    92. sent [LCP ConfRej id=0x1 <auth pap>]  
    93. LCP: timeout sending Config-Requests  
    94. Connection terminated.  
    95. Modem hangup


    pppd的脚本gprsdial中加上local选项,local的意思是不使用调制解调器的控制线路,pppd将会忽略载波检测。修改后的脚本内容如下:



    [plain]  view plain  copy


     
        
     
    1. # Usage:   root>pppd call gprs  
    2. /dev/ttyS3  
    3. 115200  
    4. #crtscts  
    5. modem  
    6. noauth  
    7. debug  
    8. nodetach  
    9. local  
    10. #hide-password  
    11. usepeerdns  
    12. noipdefault  
    13. defaultroute  
    14. user "cmnet"  
    15. 0.0.0.0:0.0.0.0


            问题二:通过AT命令“ATD10001;”拨打电话时,模块返回“NO DIALTONE”,通过AT命令“ATD*99#”拨号进行数据连接时,模块返回“NO CARRIER”

            原因:此问题是由于没有插天线,信号不好导致的。

           

            问题三:2G的模块(sim800),用3G的SIM卡,能正常通信和拨打电话吗?

            答案:可以。

            问题四:ip-up:ppp拨号成功会,会调用这个脚本;

            联网后,DNS不起作用!
            可以在ip-up文件中添加设置DNS的命令,如下所示:  


    [plain]  view plain  copy


     

    1. /system/bin/ndc resolver setifdns "$NAME" "$DNS1" "$DNS2"  
    2. /system/bin/ndc resolver setdefaultif "$NAME"

           

            调试过程中几个常用的AT命令:


    [plain]  view plain  copy


     

     
     
    1. AT+CSMINS?    //查询是否插入SIM卡  
    2. AT+CSQ        //查询信号质量  
    3. ATDxxxxxx;    //拨打电话,命令尾一定要要分号


    [plain]  view plain  copy


     

     
     
    1. <pre class="plain" name="code">AT+CIMI      //查询国际移动用户标识  
    2. AT+COPS?     //查询运营商  
     
    这两条命令均可以用于查询SIM卡是

    移动的还是联通的。



            Android系统下增加自启动服务

       首先,在init.rc脚本中增加pppd服务,实现开机自动拨号上网(但通常这一动作是由Android的RIL层触发的,函数为requestSetupDataCall())。Android中有专门的脚本init.gprs-pppd用于启动pppd,当然也可以自己写一个类似的脚本用于启动pppd服务。


    [plain]  view plain  copy


     

    1. service pppd /system/etc/ppp/init.gprs-pppd call gprsdial  
    2.     class main  
    3.     user root  
    4.     group radio cache inet misc  
    5. service ril-daemon /system/bin/rild  
    6.     class main  
    7.     socket rild stream 660 root radio  
    8.     socket rild-debug stream 660 radio system  
    9.     user root  
    10.     group radio cache inet misc audio log  
    11. service ril-daemon3 /system/bin/rild3  
    12.     class main  
    13.     socket rild3 stream 660 root radio  
    14.     socket rild-debug stream 660 radio system  
    15.     user root  
    16.     group radio cache inet misc audio log

            此步骤需要注意的是,pppd服务的class需要和rild服务的class保持一致。init.gprs-pppd脚本的内容如下:


    [plain]  view plain  copy


     

    1. #!/system/bin/sh  
    2. # An unforunate wrapper script   
    3. # so that the exit code of pppd may be retrieved  
    4. # this is a workaround for issue #651747  
    5. #trap "/system/bin/sleep 1;exit 0" TERM  
    6.   
    7. PPPD_PID=  
    8. /system/bin/setprop "net.gprs.ppp-exit" ""  
    9. /system/bin/log -t pppd "Starting pppd"  
    10. /system/bin/pppd $*  
    11.   
    12. PPPD_EXIT=$?  
    13. PPPD_PID=$!  
    14.   
    15. /system/bin/log -t pppd "pppd exited with $PPPD_EXIT"  
    16. /system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT"