STM32F4使用USB接口3G网卡

2020-03-01 11:54发布

本帖最后由 lin704932121 于 2018-5-4 23:34 编辑

    大概去年这时候,21ic发了一波STM32F469I-Discovery板子。我很高兴能拿到这拿到这块板子,并写了两篇试用帖子【STM32F469I试用】Linux下USB无线网卡驱动的移植【STM32F469I试用】USB摄像头的采集与显示。最近,有坛友问我是否有相应的3G网卡驱动,我趁这个假期把之前移植好的代码整理了一下,分享给大家。这个3G网卡驱动大概消耗十几KB的内存。
一、USB 3G网卡拨号流程
    USB 3G网卡和PC一般是通过modem(也可以说是虚拟串口)来进行通信的。3G网卡插入后,首先要用AT指令拨打指定运营商号码,再通过PPP认证协议获取到自身的IP地址。然而现在厂商为了方便用户安装驱动程序,
3G网卡一上电是一个存储类,用户通过它可以安装.exe文件的驱动程序。驱动程序安装完成后,3G网卡再次上电,驱动程序会向3G网卡发送一串特定指令。3G 网卡收到特定指令后,会使USB的D+和D-引脚浮空,造成USB断开。接着PC会再一次枚举3G网卡,此时3G网卡就会成为modem(虚拟串口)类。由于每个厂商甚至每种型号的3G网卡的特定指令都不一样,因此如果厂商没有提供Linux下的驱动话,在Linux下进行拨号上网就便的很困难。还好,有人抓取了windows下的驱动程序和3G网卡之间的USB通信协议包,获取到了这些特定指令,详情可见usb_modeswitch这个开源项目。
    下图是将
usb_modeswitch移植到STM32F4后的拨号流程图,3G网卡插入后,首先判断modem驱动是否支持该型号网卡,如果支持就直接使用AT指令进行拨号,然后再进行ppp认证。如果不支持再判断usb_modeswitch是否可以转换网卡的模式
3G网卡拨号流程图.PNG

二、联通USB 3G网卡的使用
   
我手上有个联通华为E261型号的3G网卡,就用它来做测试吧。

    1.运行 EvalBoardsSTSTM32469I-DiscoveryuCOS-IIIKeilMDKuCOS-III.uvproj  ,编译并直接烧写程序。工程环境用的是MDK 4.7。
    2.程序烧写完成后会同时在USART3和LCD上输出信息。USART3 连接到了板子上的STLINK,PC机上直接打开这个虚拟串口就可以使用它了。
    2.用一根OTG线连接板子上USB FS端口,并插入3G网卡。   
    3.如下图串口终端中输入ping命令测试网络连通性

测试实物i图 测试实物i图
     
    UDP上行带宽测试

   
工程里包含有iperf带宽测试程序。如下图,在
串口终端中输入:
     iperf -c 120.25.217.198 -u -b 4Mbits -t 18 -i 1
    其中,
120.25.217.198是我的一个云服务器ip地址,-u代表udp测试,-b 4Mbits代表测试带宽4Mbits/s,-t 18代表测试时间18秒,-i 1代表每秒钟报告一次测试结果。
    E261 UDP带宽测试 E261 UDP带宽测试
    可以看到,服务器报告的测试带宽为1.58Mbits,丢包率0.044%。

    TCP上行测试
    如下图,在串口终端中输入:
     iperf -c 120.25.217.198 -t 18 -i 1

E261 TCP测试1 E261 TCP测试1
      可以看到,TCP测试带宽仅为250Kbits/s,远远不如UDP测试的速率。这其中一方面是因为3g网卡和服务器的传输延迟大,另一方面是lwip配置的发送缓冲区不够大。将lwipopts.h中TCP_SND_BUF修改为(8*TCP_MSS),重新编译。
  1. /* TCP sender buffer space (bytes). */
  2. #define TCP_SND_BUF             (4*TCP_MSS)
复制代码-->
  1. /* TCP sender buffer space (bytes). */
  2. #define TCP_SND_BUF             (8*TCP_MSS)
复制代码   如下图,重新进行TCP上行测试,可以看到TCP测试带宽提高到了550Kbits/s。然而提高发送缓冲区也意味着消耗更多内存,终端中输入stats命令,可以看到内存堆的最高消耗由15KB提高到了21KB。
MEM HEAP
        avail: 24576
        used: 1532
        max: 15920
        err: 0
-->
MEM HEAP
        avail: 24576
        used: 1532
        max: 21836
        err: 0
E261 TCP测试2 E261 TCP测试2

三、其它运营商3G网卡使用
    usb_modeswitch只是转换3G网卡模式,并不识别3g网卡的运营商。代码中默认是中国联通的拨号脚本,如果想使用中国移动或中国电信3g上网卡,需要在modem.c文件modem_probe()函数中,取消注释相应运营商的拨号函数。
  1.     for(i=0;i<4;i++)
  2.     {
  3.         msleep(3000+2000*i);
  4.         if((ret = modem_dial_china_unicom(modem)) == 0) break;           //中国联通拨号脚本函数
  5. //        if((ret = modem_dial_china_telecom(modem)) == 0) break;        //中国电信拨号脚本函数
  6. //        if((ret = modem_dial_china_mobile(modem)) == 0) break;         //中国移动拨号脚本函数
  7.     }
复制代码当然,也可以尝试使用AT+COPS?指令来识别出3g网卡当前所使用的运营商,再使用不同的拨号脚本。

手里还有另一块华为MU509联通制式模块,顺便也附上它的UDP带宽测试结果图吧。测试结果的带宽并不高,只有380Kbits/s左右。
MU509 UDP测试.jpg

USB-3G-Modem-for-STM32F4xx.rar (4.08 MB, 下载次数: 233) 2017-1-24 16:28 上传 点击文件名下载附件

2017/2/19追记:
我重新运行了板子上的代码。插上华为E261型号3G网卡后,AT指令拨号总是失败。然而我假期在家里测试是可以的,来到北京就不行了?
我试着在PC上使用USBPcap抓取3G网卡通讯协议包,发现PC对3G网卡发送有一条特殊AT指令AT&FE0V1X1&D2&C1S0=0。将该指令添加到拨号脚本的函数里,3G网卡可以正常拨号。暂时还不明白这条指令是什么意思。
在modem.c文件modem_dial_china_unicom()函数里,添加AT&FE0V1X1&D2&C1S0=0指令。
  1.      struct modem_chat chat[] =
  2.      {
  3.         {"AT ","OK"},
  4.         {"AT+CGDCONT=1,"IP","3gnet",,0,0 ","OK"},
  5.         {"AT+CFUN=1 ","OK"},            
  6.         {"ATDT*99# ", "CONNECT"},
  7.         { } /* Terminating entry */
  8.      };
复制代码  修改为:
  1.     struct modem_chat chat[] =
  2.     {
  3.         {"AT ","OK"},
  4.         {"AT+CGDCONT=1,"IP","3gnet",,0,0 ","OK"},
  5.         {"AT+CFUN=1 ","OK"},           
  6.         {"AT&FE0V1X1&D2&C1S0=0 ","OK"},
  7.         {"ATDT*99# ", "CONNECT"},
  8.         { } /* Terminating entry */
  9.     };
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。