正点原子wifi实验分析:
ATK-RTM04的几种模式分析:
1. WIFI使能,工作在AP模式下,ETH1、ETH2功能使能,ETH1作为WAN,ETH2作为LAN.此时模块相当于一个无线路由器,只是只有一个LAN口。
WLAN口为广域网接入口,LAN口为本地的网络引出口。WIFI设备能够连接到该模块。
WAN端默认为动态IP地址方式。LAN、WIFI为同一局域网,默认开启服务器。
注意:在ATK-RM04与MCU的连接方式为SERIAL方式,而不是网线。
2. 串口转以太网模型,ETH1(WLAN)使能,WIFI、ETH2(LAN)功能关闭。通过适当的设置,COM1的数据与ETH1(WLAN)的网路数据相互转换。
以太网可以配置配置为动态IP地址(DHCP),也可以配置为静态IP地址。
3.WIFI使能,工作在CLIENT模式下,ETH1(WLAN)、ETH2(LAN)功能关闭。通过适当的设置,COM1的数据与WIFI的网络数据相互转换。
WIFI STA可以配置为动态IP地址(DHCP),也可以配置为静态IP地址(STATIC)。
4.WIFI使能,工作在AP模式下,ETH1、ETH2功能关闭。通过适当设置,COM1的数据与WIFI的网路数据相互转换。
上述的1和4模式的不同在于,第四种的作用未打开ETH1、ETH2的WLAN、LAN功能。
WPS/RST按键和ES/RST按键(KEY2/KEY1) 建立无线连接(无需输入SSID和密码)。其他模式下,该按键仅用作恢复默认设置(RST),长按该按键(T>6S),即可让模块恢复默认设置。 atk_rm04_test(void) //main()函数中调用 ,原型在common.c中定义的。 ->Show_Str_Mid(0,20,"ATK-RM04 WIFI模块测试",16,240); //显示函数 情况下 ,发送连续的指令+++1B1B1B来进入AT模式。第二种方式是通过硬件方式的RST置位ESL_CTRL来实现。 为空,返回值肯定大于0,如果为USART3_RX_BUF为空,则返回为0,则break。 3. atk_rm04_mtest_ui(x u16,u16 y) // 显示主界面 atk_rm04_send_cmd("at+wifi_conf=?","?",20); //获取WIFI配置 4. atk_rm04_at_response(1); 端、UDP服务器、UDP客户端模式的一种。 接着发送命令,选择作为服务器还是客户端,如果设置为客户端就要设置remote IP地址,但是作为服务器就只要设置地址就 可以。 6.atk_rm04_wifista_test(); //WIFI STA测试 if(netpro&0X01) //客户端 7.atk_rm04_wifiap_test(); //WIFI AP测试 if(netpro&0x01) //客户端 printf("%s",USART3_RX_BUFP); //发送到串口 sprintf((char *)p,"收到%d字节,内容如下",rlen); //接收到的字节数 extern _ARMABI int _vprintf(const char * __restrict /*format*/, __va_list /*arg*/) __attribute__((__nonnull__(1)));
WPS/RST即KEY2按键,在路由器模式下,该按键作为路由器的WPS按键,短按(100ms
ES/RST即KEY1按键,在路由器模式下,该按键仅用作恢复默认设置,操作同KEY2按键。在其他模式下,短按该按键(100ms
注意:在任何模式下,长按KEY1/KEY2,均可让模块恢复默认设置,不过一般要第二次或第三次才会成功。
问:为什么在非路由器模式下,才会要AT指令模式???????
->atk_rm04_quit_trans(); //退出透传
->while(atk_rm04_send_cmd("at","\r\n",20)) //检查WIFI模块是否在线
{
atk_rm04_quit_trans(); //退出透传
}
1.atk_rm04_quit_trans()函数作用是退出透传模式,进入AT模式(发送指令)。有两种方法一种是从串口方式退出透传模式,在大于组帧宽度的
2.atk_rm04_send_cmd(u8 *cmd,u8 *ack,u16 waittime)发送AT指令函数分析:
->USART3_RX_STA = 0; //[15]:0,未收到数据;1,收到数据
//[14:0] 收到的数据长度。
u3_printf("%s\r",cmd); //发送命令
u3_printf(char* fmt,...) //发送命令函数原形定义
-> va_list ap;
struct __va_list{void *__vp;}va_list;
va_start(ap , fmt); //stdio.h中定义的
#define va_start(ap , parmN) __va_start(ap , parmN)
vsprintf((char*)USART3_TX_BUF,fmt,ap); //stdio.h中定义
va_end(ap);
i = strlen((const char*)USART3_TX_BUF);
for(j = 0,j < i ;j++)
{
while((USART3->SR&0x40)==0);
USART3->DR = USART3_TX_BUF[j];
}
上面函数的原形的参数实际上省略了,在调用函数中cmd参数,被传递到USART3_TX_BUF中,然后发出。(原理不详???)
if(atk_rm04_check_cmd(ack))break;
->strx = strstr((const char*)USART3_RX_BUF,(const char*)str);
此函数为stdio.h中定义的,作用是对比byte字节,在str字符串的位置为第几个。
该函数通过检查每次接收USART3_RX_BUF[]中一个字节,对比ack应答字符串中的位置,如果USART3_RX_BUF中的内容是正确的且不
->atk_rm04_msg_show(x,y+125,0)
atk_rm04_msg_show(u16 x,u16 y,u8 wanip) //x,y为显示信息的其实坐标,wanip为0,全部更新显示;1,仅更新wanip
->atk_rm04_send_cmd("at+ver=?","?",20); //获取版本号
p=atk_rm04_check_cmd("\r\n");
Show_Str(x,y,240,16,"版本:",16,0);Show_Str(x+40,y,240,16,p+2,16,0);
atk_rm04_send_cmd("at+netmode=?","?",20); //获取网络模式
p=atk_rm04_check_cmd("\r\n");
Show_Str(x,y+16,240,16,"网络模式:",16,0);Show_Str(x+72,y+16,240,16,(u8*)ATK_RM04_NETMODE_TBL[*(p +2)-'0'],16,0);
p=atk_rm04_check_cmd("\r\n");
p1=(u8*)strstr((const char*)p,",");
*p1=0;p1++;
Show_Str(x,y+32,240,16,"SSID号:",16,0);Show_Str(x+56,y+32,240,16,p+2,16,0);
p=p1;
p1=(u8*)strstr((const char*)p,",");
*p1=0;p1++;
Show_Str(x,y+48,240,16,"加密方式:",16,0);Show_Str(x+72,y+48,240,16,p,16,0);
Show_Str(x,y+64,240,16,"密码:",16,0);Show_Str(x+40,y+64,240,16,p1,16,0);
发送一系列的AT指令获取wifi的各项信息参数版本号、网络模式、WIFI配置、SSID号、加密方式、密码。WANIP地址。
在while循环中使用该句检查USART3_RX_BUF中是否接受到AT指令,并且返回给电脑。
while(key)
5.atk_rm04_cometh_test(); //串口以太网测试
->netpro = atk_rm04_netpro_sel(50,30,(u8*)ATK_RM04_NETMODE_TBL[1])
该函数是用来进行网络模式的设置,ATK_RM04_NETMODE_TBL[]数组存放着模式名称,通过key来按键选择TCP服务器、TCP客户
if(netpro&0X01) //客户端
{
if(atk_rm04_ip_set("ETH-COM 远程IP设置",(u8*)ATK_RM04_WORKMODE_TBL[netpro],(u8*)portnum,ipbuf))
sprintf((char*)p,"at+remoteip=%s",ipbuf);
atk_rm04_send_cmd(p,"ok",500);
atk_rm04_send_cmd("at+mode=client","ok",500);
}else atk_rm04_send_cmd("at+mode=server","ok",500);
if(atk_rm04_send_cmd("at+net_commit = 1","\r\n",12,0));//提交网络配置,最长可能等待40s 这一步很重要,如果这一步不成功,则会直接退回,否则进行else语句 中的其他设置,进行wan ip获取。
else
atk_rm04_send_cmd("at+reconn = 1","ok",500); //重启串口转换服务
atk_rm04_quit_trans(); //退出透传
while(1)
{
atk_rm04_get_wanip(p); //获取WAN IP
if(p[0]!=0)break; //成功获取到了IP地址
Show_Str(30,80,200,12,"ATK-RM04 连接路由器失败",12,0); //连接失败
delay_ms(800);
Show_Str(30,80,200,12,"ATK-RM04 等待连接中....",12,0);
delay_ms(800);
}
..
if((netpro&0x01)==0)atk_rm04_get_wanip(ipbuf); //服务器模式,再次获取WAN IP
USART3_RX_STA = 0;
key == KEY0_PRES
u3_printf("%s",p);//发送该数据到ATK-RM04模块
->netpro = atk_rm04_netpro_sel(50,30,(u8*)ATK_RM04_NETMODE_TBL[1])
该函数是用来进行网络模式的设置,ATK_RM04_NETMODE_TBL[]数组存放着模式名称,通过key来按键选择TCP服务器、TCP客户 端、UDP服务器、UDP客户端模式的一 种。 接着发送命令,选择作为服务器还是客户端,如果设置为客户端就要设置remote IP地址,但是作为服务器就只要设置地址就 可以。
{
if(atk_rm04_ip_set("WIFI-STA 远端IP设置",(u8*)ATK_RM04_WORKMODE_TBL[netpro],(u8*)portnum,ipbuf))
sprintf((char*)p,"at+remoteip=%s",ipbuf);
atk_rm04_send_cmd(p,"ok",500); //
atk_rm04_send_cmd("at+mode=client","ok",500); //
}else atk_rm04_send_cmd("at+mode=server","ok",500);
if(atk_rm04_send_cmd("at+net_commit = 1","\r\n",12,0));//提交网络配置,最长可能等待40s这一步很重要,如果这一步不成功,则会直接退回,否则进行else语句 中的其他设置,进行wan ip获取。
else
{
atk_rm04_send_cmd("at+reconn = 1","ok",500); //重启串口转换服务
atk_rm04_quit_trans(); //退出透传
while(atk_rm04_get_wifista_state()==0) //等待ATK-RM04连接路由器
{
Show_Str(30,80,200,12,"ATK-RM04 连接路由器失败",12,0); //连接失败
delay_ms(800);
Show_Str(30,80,200,12,"ATK-RM04 等待连接中....",12,0);
delay_ms(800);
}
atk_rm04_get_wanip(ipbuf);
...
}
atk_rm04_send_cmd("at+netmode=3","ok",500);
atk_rm04_send_cmd("at+dhcpd=1","ok",500);
atk_rm04_send_cmd("at+dhcpc=0","ok",500);
atk_rm04_send_cmd("at+dhcpd_ip=192.168.16.100,192.168.16.200,255.255.255.0,192.168.16.1","ok",500);
atk_rm04_send_cmd("at+dhcpd_dns=192.168.16.1,0.0.0.0","ok",500);
atk_rm04_send_cmd("at+net_ip=192.168.16.254,255.255.255.0,192.168.16.1","ok",500);
atk_rm04_send_cmd("at+net_dns=192.168.16.1,0.0.0.0","ok",500);
->netpro = atk_rm04_netpro_sel(50,30,(u8*)ATK_RM04_NETMODE_TBL[1])
该函数是用来进行网络模式的设置,ATK_RM04_NETMODE_TBL[]数组存放着模式名称,通过key来按键选择TCP服务器、TCP客户 端、UDP服务器、UDP客户端模式的一 种。 接着发送命令,选择作为服务器还是客户端,如果设置为客户端就要设置remote IP地址,但是作为服务器就只要设置地址就 可以。
{
if(atk_rm04_ip_set("WIFI-AP 远程IP设置",(u8*)ATK_RM04_WORKMODE_TBL[netpro],(u8*)portnum,ipbuf))
sprintf((char*)p,"at+remoteip=%s",ipbuf);
atk_rm04_send_cmd(p,"ok",500); //设置远端(连接)IP地址
atk_rm04_send_cmd("at+mode=client","ok",500); //设置为客户端
}else atk_rm04_send_cmd("at+mode=server","ok",500); //设置为服务端
}
if(atk_rm04_send_cmd("at+net_commit = 1","\r\n",12,0));//提交网络配置,最长可能等待40s
*****这一步很重要,如果这一步不成功,则会直接退回,否则进行else语句中的其他设置,进行wan ip获取。
**** else
{
atk_rm04_send_cmd("at+reconn = 1","ok",500); //重启串口转换服务
while((netpro&0x01)==0) //服务器模式
{
atk_rm04_quit_trans();
atk_rm04_get_wanip(ipbuf);
if(ipbuf[0]) break;
}
#pragma __printf_args
extern _ARMABI int printf(const char * __restrict /*format*/, ...) __attribute__((__nonnull__(1)));
#pragma __printf_args
extern _ARMABI int sprintf(char * __restrict /*s*/, const char * __restrict /*format*/, ...) __attribute__((__nonnull__(1,2)));
#if defined(__cplusplus) && !defined(__STDIO_NO_EXPORTS)
using ::std::size_t;
using ::std::fpos_t;
using ::std::FILE;
using ::std::remove;
using ::std::rename;
using ::std::tmpfile;
using ::std::tmpnam;
using ::std::fclose;
using ::std::fflush;
using ::std::fopen;
using ::std::freopen;
using ::std::setbuf;
using ::std::setvbuf;
using ::std::fprintf;
using ::std::_fprintf;
using ::std::printf;
using ::std::_printf;
using ::std::sprintf;
using ::std::_sprintf;
#if !defined(__STRICT_ANSI__) || (defined(__STDC_VERSION__) && 199901L <= __STDC_VERSION__)
using ::std::snprintf;
using ::std::vsnprintf;
using ::std::vfscanf;
using ::std::vscanf;
using ::std::vsscanf;
#endif
using ::std::_snprintf;
using ::std::_vsnprintf;
using ::std::fscanf;
using ::std::_fscanf;
using ::std::scanf;
using ::std::_scanf;
using ::std::sscanf;
using ::std::_sscanf;
using ::std::_vfscanf;
using ::std::_vscanf;
using ::std::_vsscanf;
using ::std::vprintf;
using ::std::_vprintf;
using ::std::vfprintf;
using ::std::_vfprintf;
using ::std::vsprintf;
using ::std::_vsprintf;
using ::std::fgetc;
using ::std::fgets;
using ::std::fputc;
using ::std::fputs;
using ::std::getc;
using ::std::getchar;
using ::std::gets;
using ::std::putc;
using ::std::putchar;
using ::std::puts;
using ::std::ungetc;
using ::std::fread;
using ::std::__fread_bytes_avail;
using ::std::fwrite;
using ::std::fgetpos;
using ::std::fseek;
using ::std::fsetpos;
using ::std::ftell;
using ::std::rewind;
using ::std::clearerr;
using ::std::feof;
using ::std::ferror;
using ::std::perror;
using ::std::_fisatty;
using ::std::__use_no_semihosting_swi;
using ::std::__use_no_semihosting;
#endif