1 系统方案
本文设计的嵌入式WiFi方案是智能手机以WiFi方式遥控智能小车的系统,系统架构如图1所示。手机端就是一个运行在手机上的Android应用程序,小车端的核心控制板采用STM32F105RB芯片,WiFi网卡采用基于RT5370的嵌入式模块。RT5370是一款USB接口的WiFi芯片,基于其实现的USB无线网卡非常常见,价格优势明显。STM32F105RB是ST公司STM32系列芯片的一款,72 MHz主频,具有128 KB Flash、48 KB RAM和丰富的I/O资源,同时价格比较低,在中小嵌入式系统中广泛采用,同时其支持USB OTG,可以驱动RT5370。
该系统的核心就是在基于STM32F105RB的小车控制板上实现对RT5370 WiFi模块的支持,使该控制板工作在AP模式,手机通过WiFi从控制板获得IP,然后运行相应的Android应用程序控制小车。
2 硬件设计
小车控制板包括WiFi接口和功率输出驱动两大部分。因为本文的重点是嵌入式WiFi实现,所以只给出该部分的硬件实现,如图2所示。图中STM32F105RB的USB工作在主机模式,与WiFi模块通过6引脚2.0 mm的单排针连接。由于STM32F105RB USB模块内部有下拉电阻,所以电路连接非常简单。
3 软件流程及移植
系统软件架构如图3所示。整个系统由USB驱动、WiFi协议栈、网络协议栈、应用程序4个主要部分组成。
USB部分实现WiFi网卡和系统MCU之间的通信,WiFi网卡收发的数据通过USB与MCU进行交互,STM32F105RB作为USB主机,WiFi网卡作为USB客户端。
WiFi协议栈负责802.11协议的解析和封装,向下和USB驱动交互,向上和TCP/IP协议栈交互:发送端,从TCP/IP协议栈接收数据,封装成WiFi封包,通过调用USB驱动实现物理发送;接收端,从USB驱动接收数据,解析802.11协议,传送给TCP/IP协议栈,实现向应用层的传递。
TCP/IP协议栈实现IP、ICMP、UDP、TCP等协议,包括实现协议封装、解析以及基本的路由。当前有很多优秀的开源TCP/IP协议栈,本项目中选用LWIP,因为该协议比较成熟,适合资源有限的嵌入式系统。LWIP支持DHCP客户端,但是在该系统中作为AP来用,需要DHCP服务器,这里自己设计了一个简单的DHCP服务器。
应用程序部分,调用网络编程接口和手机进行通信,将收到的数据转化为驱动小车输出的PWM信号,来驱动小车。
3.1 USB驱动
ST公司的固件库提供了对于USB的支持。本系统就基于该USB库架构,实现了USB WiFi模块需要的特定功能。
STM32的USB库架构如图4所示,其给用户提供的接口非常清晰,包括USB主机的初始化,以及对应状态机的实现。
3.1.1 USB主机初始化
USB主机的初始化通过USBH_Init函数实现,这个函数有5个结构类型的参数,在调用这个函数前,需要先设置好这5个参数的内容。该函数原形如下:
参数pdev,phost分别代表STM32 USB的核心控制结构和USB主机的控制结构,在STM32的USB库中已经定义,对应USB_OTG_CORE和USB_HOST。USB_OTG_FS_CORE_ID表示工作在USB的全速方式。参数Class_cb和usr_cb为用户定义的USB类控制结构和用户定义的初始化结构。这两个结构是要实现的内容,其中,用户定义的USB类控制结构,包括初始化、释放、请求和状态机4个处理函数,分别在代表用户设计的USB类的初始化、释放、初始化请求和正常工作状态中会用到。
用户根据要求分别实现对应的功能,对应本项目的WiFi模块,具体的移植实现如下:
其中,USBH_CDC_InterfaceInit实现WiFi模块的初始化,对应Linux版本驱动中的芯片寄存器配置、通信缓冲区配置、加载固件的挂钩函数等处理,以及在MainVirtualIF_open中实现打开WiFi等操作。USBH_CDC_Handle则实现USB的状态机功能。
用户定义的初始化函数是给用户提供一个实现自己特定初始化操作的接口,这里没有用到。
这些参数都设置好后,直接调用USBH_Init即可实现对USB硬件和架构的初始化。
3.1.2 USB状态机
USB初始化完成后,其核心处理都是由USB状态机USBH_Process来实现从枚举、功能处理到异常恢复等的管理,其中会通过函数挂钩的方式调用在初始化过程中设置的对应函数。
具体状态转换过程如图5所示。首先主机检测是否有USB模块插入,如果有,则转入枚举过程。对于本系统来说,WiFi模块直接安装在控制板上,上电后就会检测到有插入并转入枚举过程;枚举结束后,STM32F105RB的USB库会给用户提供一个用户输入和特定类初始化的操作,对于该WiFi模块,归属于通信类,在类初始化操作中会作WiFi模块相应地初始化,包括读取模块的配置信息、MAC地址等;在这些初始化过程完成后,会进入模块状态机处理过程,对于该WiFi模块来说,就是循环处理接收数据的过程。在这个过程中如果发生异常,则进入异常处理后重新从空闲状态开始状态切换。标准的STM32F105RBUSB模块还有USB模块拔除的状态转换,由于该项目中WiFi模块直接装在母板上,所以不会进入这个状态。
特别地,USB WiFi状态机处理函数主要实现WiFi数据的传输,具体的传输通过USB的批处理传输方式进行。对于数据接收,系统会一直轮询WiFi模块,判断是否有数据可用。如果有,则将数据读入接收缓冲区中,并设置相应的标志通知上层软件。对于数据发送,上层直接发起数据传输,调用USB发送函数,进行发送。
3.2 802.1 1协议驱动
WiFi协议栈的实现基于Mediatek官方提供的Linux源码驱动,相应移植到该项目的STM32F105RB系统中。图6分析了RT5370 Linux的驱动流程和需要完成的对应移植工作。
从左边的驱动流程可以看出,首先是设置Linux驱动架构下面的probe、open等函数,在本系统中这块并不需要,直接从硬件初始化开始,由于驱动本身就是可移植性比较好的C语言代码,所以这块代码基本可以直接移植过来;然后是驱动所需的通信缓冲区的资源初始化,这部分和操作系统相关,根据本系统的情况,直接预留相应的内存作为通信缓冲区;WiFi对应的配置信息在Linux下是一个配置文件,在存在根文件的系统中,对于没有文件系统的情况,直接将对应的配置值以默认值的方式保存,但是这也导致了一个问题,相应的WiFi配置(如SSID等)不可以更改,需要在后续实现中完善;这些设置工作都准备好后,启动对应的定时器和2个任务分别处理WiFi的广播Beacon连接信息和实际用户数据,并用相应的定时器和模块实现。
3.3 TCP/IP协议栈LWIP
完成了WiFi驱动从Linux到STM32F105RB系统的移植后,相当于实现了OSI模型中网络层的移植,后续就是相应协议栈的移植。本项目中协议栈选用LWIP,版本是v1.3.2。需要指出的是,由于该项目的USB WiFi工作于AP模式,需要实现DHCP服务器的功能。而在LWIP中只有DHCP客户端功能,服务器需要自己实现,在本项目中根据需要实现了一个简单的DHCP服务器。
3.4 应用程序
在实现了WiFi驱动、协议栈以及DHCP服务器后,基于STM32的WiFi已经可以工作,分别用手机和计算机与控制板连接,成功获得IP,在计算机端运行ping命令,可以成功ping通。在此基础上,编写基于LWIP的套接子程序,以及相应的小车驱动程序,实现通过手机可以流畅地控制小车。
结语
试验表明,该系统实现的WiFi除具有成本方面的优势外,还具有系统启动快、通信响应快的特点,通常系统2 s即可以启动,手机3 s即可以获得IP,比常用路由器的响应快了很多;ICMP响应通常小于2 ms,响应速度的优势也非常明显。用手机通过WiFi控制智能小车,可以做到流畅控制。理论和实践证明,在基于Cortex—M3的低成本嵌入式系统中实现WiFi是完全可行的。
当然,由于时间限制,该项目WiFi系统的加密功能,以及通常的WiFi系统需要的基于web界面方式的配置功能尚未实现。考虑到当前STM32F105RB的资源使用情况,我们使用了80 KB空间,系统还留有48 KB空间,后续完整实现加密和Web界面配置在理论上是可行的,有待进一步验证。