开发板的USART1与电脑连接,WIFI模块发送信号与手机连接。
在电脑上安装串口助手,在手机上安装网络调试助手app
正文开始!
串口使用到了USART1和USART3
其中USART1负责与电脑连接,相互通信
USART3负责与WIFI模块连接,MCU通过USART3将数据发送到WIFI模块,WIFI模块再将数据发送给手机app。
其中串口初始化的代码不再复述。关键讲解功能的实现步骤。
MCU向USART1和USART3打印字符串的代码:
其中MCU向USART1打印字符串是默认的,所以直接使用printf() 即可
但是MCU向USART3打印字符串 使用u3_printf()
void u3_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART3_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
USART_SendData(USART3,USART3_TX_BUF[j]);
}
}
且需要注意: 在本案例中,USART3初始化中需要初始化 定时器,
该定时器的作用为:
通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到。
main.c
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
delay_init();
KEY_Init();
uart1_init(115200); //串口初始化为115200
uart3_init(115200);
printf("Init_Ready\n");//如果初始化成功,则向USART1发送Init_Ready
printf("check wifi online:");//这里是等待WIFI模块返回自检成功的标志"OK"
atk_8266_test();
}
随着我们的目光落在atk_8266_test()函数上,让我们来分析一下这个函数的功能,这里有一个重要的函数 atk_8266_send_cmd() 我们来先分析一下:
它有三个参数
cmd:发送的命令字符串
。
ack:期待的应答结果,如果为空,则表示不需要等待应答
。
waittime:等待时间(单位:10ms)
。
返回值:0,发送成功(得到了期待的应答结果) 1,发送失败
u8 atk_8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
{
u8 res=0;
USART3_RX_STA=0;
u3_printf("%s\r\n",cmd); //发送命令
if( ack && waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(10);
if(USART3_RX_STA&0X8000)//接收到期待的应答结果
{
if(atk_8266_check_cmd(ack))
{
printf("ack:%s\r\n",(u8*)ack);
break;//得到有效数据
}
USART3_RX_STA=0;
}
}
if(waittime==0)res=1;
}
return res;
}
atk_8266_test() 函数
void atk_8266_test(void)
{
u8 key;
while(atk_8266_send_cmd("AT","OK",20))//检查WIFI模块是否在线
{
printf("WIFI_init_fall\n");
atk_8266_quit_trans();//退出透传
printf("AT+CIPMODE=0:");
atk_8266_send_cmd("AT+CIPMODE=0","OK",20); //关闭透传模式
}
printf("-------------------\n");
printf("KEY0:STAAP_MODE\n");
printf("----------\n");
printf("KEY1:STA_MODE\n");
printf("----------\n");
printf("WK_UP:AP_MODE\n");
printf("-------------------\n");
while(1)
{
delay_ms(10);
atk_8266_at_response(1);
key=KEY_Scan(0);
if(key)
{
switch(key)
{
case KEY0_PRES: //这里偷懒没写完 本该是WIFI STA+APmode测试
break;
//-------
case KEY1_PRES:
printf("Selected mode is: STA_mode\n");
atk_8266_wifista_test();//WIFI STA测试
break;
//-------
case WKUP_PRES:
printf("Selected mode is: AP_mode\n");
atk_8266_wifiap_test(); //WIFI AP测试
break;
}
}
}
}
此时我们按下KEY1键,执行atk_8266_wifista_test()
atk_8266_wifista_test()函数
其中WIFI_STA_SSID要自己设置一下,可以设置成手机开启的热点名
WIFI_STA_PASSWORD就是WIFI密码了
但是看下面的代码之前有3个内存的利用函数:
malloc()
p=malloc(sizeof(int)*8);//申请8个int大小的地址,用指针p指向申请到的地址的首地址
sprintf()
sprintf((char*)p," AT+CWJAP= \"%s\" , \"%s\" ",WIFI_STA_SSID,WIFI_STA_PASSWORD);
//将WIFI_STA_SSID和WIFI_STA_PASSWORD 和 AT+CWJAP= 组装起来,放入到p指向的内存中
free()
free(p)//释放P指向的地址
u8 atk_8266_wifista_test(void)
{
unsigned short ano;
u8 key;
u8 *p;
u8 res=0;
u8 ipbuf[16]; //IP缓存
u16 rlen=0;
p=malloc(sizeof(int)*8);//一个int 4B 一共32个B
printf("Set AT+CWMODE=1:");
atk_8266_send_cmd("AT+CWMODE=1","OK",20); //设置WIFI STA模式
atk_8266_send_cmd("AT+RST","OK",20); //DHCP服务器关闭(仅AP模式有效)
delay_ms(1000); //延时3S等待重启成功
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
sprintf((char*)p," AT+CWJAP= \"%s\" , \"%s\" ",WIFI_STA_SSID,WIFI_STA_PASSWORD);
while(!atk_8266_send_cmd(p,"WIFI GOT IP",300))
{break;}
printf("get ip success!\n");
//PRESTA:
printf("-------------------\n");
printf("KEY0:UDP_MODE\n");
printf("-------------------\n");
printf("KEY1:TCP_Client_MODE\n");
printf("-------------------\n");
printf("WK_UP:TCP_Sever_MODE\n");
printf("-------------------\n");
while(1)
{
key=KEY_Scan(0);
if(key)
break;
}
//----------------STA_UDP_MODE---------------------
if(key==KEY0_PRES)
{
key=0;
printf("Current mode is:STA_UDP_MODE\n"); /*偷懒,没写完*/
}
//----------------STA_TCP_CLIENT---------------------
//到这一步就要进行人机互动了
//需要打开手机上的网络调试助手(作为Server),且MCU(作为client)
//MCU正在等待电脑上输入手机端的网络调试助手上的IP地址
else if(key== KEY1_PRES)
{
key=0;
printf("Current mode is:STA_TCP_Client_MODE\n");
printf("Now Input Server IP address:\n");//等待USART1输入网络调试助手的IP地址
ano=!(USART1_RX_STA&0x8000);
while( ano)//MCU的USART1一旦收到IP地址,就配网(这里并没有防止IP地址输入的格式不正确的情况)
{
if(USART1_RX_STA&0x8000)
{
printf("Single Link:");
atk_8266_send_cmd("AT+CIPMUX=0","OK",20); //0:单连接,1:多连接
sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",USART1_RX_BUF,WIFI_SERVER_PORT); //配置目标TCP服务器
USART1_RX_STA=0;
Clear_USART1_RX_BUF();
break;
}
}
printf("Connect to Server state:");
while(atk_8266_send_cmd(p,"OK",200))
{
printf("Fall\n");
key=KEY_Scan(0);
if(key==WKUP_PRES)break;
//goto PRESTA;
}
printf("Turn Transport Mode to 1:");
atk_8266_send_cmd("AT+CIPMODE=1","OK",200); //传输模式为:透传
printf("-------------------\n");
printf("WK_UP:goto main menu\n");
printf("-------------------\n");
USART3_RX_STA=0;
Clear_USART3_RX_BUF();
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
key=0;
atk_8266_quit_trans(); //退出透传
printf("Set AT+CIPMODE=0:\n");
atk_8266_send_cmd("AT+CIPMODE=0","OK",20); //关闭透传模式
atk_8266_send_cmd("AT_RST","OK",20);
printf("WIFI Reset:\n");
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
//goto PRESTA;
printf("-------------------\n");
printf("KEY0:STAandAP_MODE\n");
printf("----------\n");
printf("KEY1:STA_MODE\n");
printf("----------\n");
printf("WK_UP:AP_MODE\n");
printf("-------------------\n");
break;
}
if(USART3_RX_STA&0X8000) //WIFI接收到一次数据了
{
rlen=USART3_RX_STA&0X7FFF; //得到本次接收到的数据长度
USART3_RX_BUF[rlen]=0; //添加结束符
printf("%s",USART3_RX_BUF); //发送到串口
USART3_RX_STA=0;
Clear_USART3_RX_BUF();
}
if(USART1_RX_STA&0X8000) //板子收到数据了接收到一次数据了
{
rlen=USART1_RX_STA&0X7FFF; //得到本次接收到的数据长度
USART1_RX_BUF[rlen]=0; //添加结束符
u3_printf("%s",USART1_RX_BUF); //发送到串口
USART1_RX_STA=0;
Clear_USART1_RX_BUF();
}
}
}
//----------------STA_TCP_SERVER---------------------
else
{
key=0;
printf("Current mode is:STA_TCP_Server_MODE\n");
printf("Single Link:");
atk_8266_send_cmd("AT+CIPMUX=1","OK",20); //0:单连接,1:多连接
sprintf((char*)p,"AT+CIPSERVER=1,%s",WIFI_SERVER_PORT); //开启Server模式(0,关闭;1,打开),端口号为portnum
printf("Server mode open:");
atk_8266_send_cmd(p,"OK",50);
atk_8266_get_wanip(ipbuf);//服务器模式,获取WAN IP
sprintf((char*)p,"IP地址:%s 端口:%s",ipbuf,WIFI_SERVER_PORT);
USART3_RX_STA=0;
}
//-------------------------------------
free(p);
return res;
}
下方是开机的USART1显示的画面
按下 KEY1,且已经连接到了手机热点
按下KEY1,等待输入IP地址
输入IP地址后,手机上的网络调试助手连接成功