7 WIFI
- 1、ESP8266模块
- 2、烧写固件
- 3、调试工具
- 4、使用库函数实现wifi
- 4.1 实现串口3和DMA的初始化
- 4.2 利用串口3实现wifi
1、ESP8266模块
- ESP8266系列无线模块是安信可科技自主研发设计的一系列高性价比WIFI SOC模组。该系列模块支持标准的IEEE802.11 b/g/n协议,内置完整的TCP/IP协议栈。用户可以使用该系列模块为现有的设备添加联网功能,也可以构建独立的网络控制器。
- 安信可科技为客户提供完整的硬件、软件参考方案,以便缩短您的产品研发周期,为您节省成本投入。
2、烧写固件
1:将USB转TTL模块上位机USB口
2:运行\ESP烧录工具\ESP_TOOLS\ESPFlashDownloadTool_v3.4.1.exe
1.选中烧写的固件文件,路径位于:ESP烧录工具\Ai-Thinker_ESP8266_DOUT_8Mbit_v1.5.4.1-a_20171130.bin
2.指定USB转TTL模块端口号,到设备管理器查看,并且指定波特率115200
3.最后点击”START”按钮烧写即可,烧写固件完毕,按USB转TLL调试小板的复位键,复位模块
3、调试工具
1:启动:ESP调试工具\AiThinker Serial Tool V1.2.3.exe调试工具,并且配置串口工作参数并且打开USB转TTL模块
2.启动上位机网络调试助手,启动一个TCP Server
3:ESP8266连接Server
在命令输入框中分别输入以下AT指令:
AT+CWMODE=1//设置为STA模式
AT+CWAUTOCONN=0//上电不自动连接
AT+CWJAP= “tarena” , “959948ye”//连接WIFI路由
AT+CIPSTA?//查看分配的IP地址
AT+CIPMODE=1//设置为透传模式
AT+CIPMUX=0//设置单连接
AT+CIPSTART= “TCP” , “192.168.0.7” ,8080//连接服务器
AT+CIPSEND//启动发
输入发送的数据给服务器
当然服务器也可以发送数据给8266模块,通过串口工具显示信息
4、使用库函数实现wifi
4.1 实现串口3和DMA的初始化
在system目录下的USART目录,打开keil工程,新建uart3.c和uart3.h文件,实现串口3的配置和dma的使用
#ifndef __UART3_H_
#define __UART3_H_
#include "stm32f10x.h"
// 定义接收/发送缓存区大小
#define UART3_RXBUFF_SIZE 2048
#define UART3_TXBUFF_SIZE 2048
typedef struct{
// 声明发送/接收缓冲区
u8 UART3_RxBUFF[UART3_RXBUFF_SIZE];
u8 UART3_TxBUFF[UART3_TXBUFF_SIZE];
int UART3_RxCounter;// 串口3接收数据计数
int Rx_Flag; // 接收标志位
int Tx_Flag; // 发送标志位
} UART3_DATA;
extern UART3_DATA uart3_data;
void UART3_Init(void); // 串口3初始化
void UART3_Puts(char* fmt,...); // 可变参函数
#endif
编辑uart3.c文件
#include "uart3.h"
#include "string.h" // va_list va_start va_end
#include "stdarg.h"
#include "stdio.h"
// 定义
UART3_DATA uart3_data={{0},{0},0,0,0};
void UART3_Init(void){
// 1、打开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 打开GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);// 打开串口3的时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);// 打开dma的时钟
// 配置GPIOB10 PB11
GPIO_InitTypeDef GPIO_Config;
GPIO_Config.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Config.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB,&GPIO_Config); // PB10 TX
GPIO_Config.GPIO_Pin = GPIO_Pin_11;
GPIO_Config.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_Config); // PB11 RX
// 配置串口3
USART_InitTypeDef USART_Config;
USART_Config.USART_BaudRate = 115200;
USART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Config.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_Config.USART_Parity = USART_Parity_No;
USART_Config.USART_StopBits = USART_StopBits_1;
USART_Config.USART_WordLength = USART_WordLength_8b;
USART_Init(USART3,&USART_Config);
// 配置串口3的rx和tx的dma
USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);
USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE);
// 使能串口3
USART_Cmd(USART3,ENABLE);
// 中断配置 总线空闲中断
USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);
// 配置发送的DMA DMA1通道2的tx
DMA_InitTypeDef DMA_Config;
DMA_Config.DMA_BufferSize = UART3_TXBUFF_SIZE;
DMA_Config.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_Config.DMA_M2M = DMA_M2M_Disable;
DMA_Config.DMA_MemoryBaseAddr = (u32)uart3_data.UART3_TxBUFF;
DMA_Config.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_Config.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_Config.DMA_Mode = DMA_Mode_Normal;
DMA_Config.DMA_PeripheralBaseAddr = (u32) (&(USART3->DR));
DMA_Config.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_Config.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_Config.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel2,&DMA_Config);
// 配置接收的DMA DMA1通道3 rx
DMA_Config.DMA_BufferSize = UART3_RXBUFF_SIZE;
DMA_Config.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_Config.DMA_M2M = DMA_M2M_Disable;
DMA_Config.DMA_MemoryBaseAddr = (u32)uart3_data.UART3_RxBUFF;
DMA_Config.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_Config.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_Config.DMA_Mode = DMA_Mode_Normal;
DMA_Config.DMA_PeripheralBaseAddr = (u32) (&(USART3->DR));
DMA_Config.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_Config.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_Config.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel3,&DMA_Config);
// 使能接收的通道
DMA_Cmd(DMA1_Channel3,ENABLE);
// 配置dma的发送中断
NVIC_InitTypeDef NVIC_Config;
NVIC_Config.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_Config.NVIC_IRQChannelCmd = ENABLE;
NVIC_Config.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_Config.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_Config);
DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);
// 配置串口3的接收中断
NVIC_Config.NVIC_IRQChannel = USART3_IRQn;
NVIC_Init(&NVIC_Config);
}
// 串口3的接收中断
void USART3_IRQHandler(void){
if(USART_GetITStatus(USART3,USART_IT_IDLE) == SET){
// 清除中断标志位
USART3->SR;
USART3->DR;
// 获取接收数据的长度
uart3_data.UART3_RxCounter = UART3_RXBUFF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel3);
// 关闭dma
DMA_Cmd(DMA1_Channel3,DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel3,UART3_RXBUFF_SIZE);
// 打开dma
DMA_Cmd(DMA1_Channel3,ENABLE);
// 接收标志位置1
uart3_data.Rx_Flag =1;
}
}
// dma1 通道2 的发送中断
void DMA1_Channel2_IRQHandler(void){
if(DMA_GetITStatus(DMA1_IT_TC2) == SET){
// 清除标志
DMA_ClearITPendingBit(DMA1_IT_TC2);
uart3_data.Tx_Flag = 1;
DMA_Cmd(DMA1_Channel2,DISABLE);
}
}
// 定义串口3发送可变参数函数
void UART3_Puts(char* fmt,...){
// 清空发送缓冲区
memset(uart3_data.UART3_TxBUFF,0,UART3_TXBUFF_SIZE);
// 构造得到的字符串发送到缓冲区
va_list ap;
va_start(ap,fmt);
vsprintf((char*)uart3_data.UART3_TxBUFF,fmt,ap);
va_end(ap);
uart3_data.Tx_Flag=0;
// 设置发送字节长度
DMA_SetCurrDataCounter(DMA1_Channel2,UART3_TXBUFF_SIZE);
// 使能
DMA_Cmd(DMA1_Channel2,ENABLE);
}
4.2 利用串口3实现wifi
在system目录下,新建的ESP8266目录,打开keil工程,新建esp8266.c和esp8266.h文件
编辑esp8266.h
#ifndef __ESP8266_H_
#define __ESP8266_H_
#include "stm32f10x.h"
#include "uart3.h"
#include "system.h"
#define WIFI_RESET PAout(15) // 指定ESP8266复位引脚
#define WIFI_Printf UART3_Puts // 指定WIFI发送数据使用串口3
#define WIFI_RxCounter uart3_data.UART3_RxCounter // 指定WIFI接收数据个数
#define WIFI_RxBuff uart3_data.UART3_RxBUFF // 指定wifi接收缓冲区
#define WIFI_RXBUFF_SIZE UART3_RXBUFF_SIZE // 指定wifi接收缓冲区大小
#define SSID "zpyl" // wifi 路由名字
#define PASSWD "12345678" // wifi路由密码
#define ServerIP "192.168.43.214" // 服务器IP地址
#define ServerPort 8090 // 服务器端口号
// 函数声明
void WIFI_ResetIO_Init(void);//WIFI复位引脚初始化函数
int WIFI_SendCmd(u8* cmd, u32 timeout);//发送AT指令
int WIFI_Reset(u32 timeout);//复位函数
int WIFI_JoinAP(u32 timeout);//连接路由器函数
int WIFI_Connect_Server(u32 timeout);//连接服务器函数
int WIFI_Connect_IOTServer(void);//连接服务器总函数
void WIFI_Connect(void);//连接服务器测试函数
void WIFI_Send_Data(void);//发送数据测试函数
#endif
编辑esp8266.c
#include "esp8266.h"
#include "systick.h"
#include "stdio.h"
#include "string.h"
void WIFI_ResetIO_Init(void){//WIFI复位引脚初始化函数
// 1、打开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// 打开GPIOA时钟
// 解除PA15的JTAG功能,将其作为普通io功能 坑点
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
// 配置GPIOA15
GPIO_InitTypeDef GPIO_Config;
GPIO_Config.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Config.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOA,&GPIO_Config); // PA15
// 默认将其拉高,后续拉低实现复位
WIFI_RESET = 1;
}
// 实现wifi复位 成功返回0 失败返回-1
int WIFI_Reset(u32 timeout){
WIFI_RESET = 0;
delay_ms(500);// 复位 + 固件加载 + 初始化
WIFI_RESET = 1;
while(--timeout){
delay_ms(100);
if(strstr((char*)WIFI_RxBuff,"ready")){// 跳出循环
printf("复位成功\r\n");
break;
}
}
if(timeout <= 0){
return -1;// 超时,复位失败
}
return 0;// 复位成功
}
// 发送指令给wifi路由 cmd:要发送的指令 timeout 超时时间
// 通过判断ESP8266回复的字符串中寻找OK,找到则返回0 ,没找到则返回-1
int WIFI_SendCmd(u8* cmd,u32 timeout){
// 清空接收缓冲区清空
WIFI_RxCounter =0; // 接收到wifi的数据个数
// 从wifi接收缓冲区首地址开始的WIFI_RXBUFF_SIZE 个字节设置为0
memset(WIFI_RxBuff,0,WIFI_RXBUFF_SIZE);
// 发送指令给8266
WIFI_Printf("%s\r\n",cmd);
printf("%s",cmd);
while(--timeout){
delay_ms(100);
if(strstr((char*)WIFI_RxBuff,"OK")){// 跳出循环
break;
}
}
if(timeout <= 0){
printf("发送失败 \r\n");
return -1;// 失败
}else{
printf("发送成功 \r\n");
return 0;// 成功
}
}
// 定义连接WIFI路由的函数
int WIFI_JoinAP(u32 timeout){
// 清空接收缓冲区清空
WIFI_RxCounter =0; // 接收到wifi的数据个数
// 从wifi接收缓冲区首地址开始的WIFI_RXBUFF_SIZE 个字节设置为0
memset(WIFI_RxBuff,0,WIFI_RXBUFF_SIZE);
// 发送连接wifi的指令
WIFI_Printf("AT+CWJAP=\"%s\",\"%s\"\r\n",SSID,PASSWD);
printf("AT+CWJAP=\"%s\",\"%s\"",SSID,PASSWD);
int flag =0;
while(--timeout){
delay_ms(100);
if(strstr((char*)WIFI_RxBuff,"WIFI GOT IP") && flag == 0){// 连接上路由
flag =1;
}
if(strstr((char*)WIFI_RxBuff,"OK") && flag == 1){// 配置完成ip
break;
}
}
if(timeout <= 0){
printf("发送失败 \r\n");
return -1;// 失败
}else{
printf("发送成功 \r\n");
return 0;// 成功
}
}
// 定义连接服务器的函数
int WIFI_Connect_Server(u32 timeout){
// 清空接收缓冲区清空
WIFI_RxCounter =0; // 接收到wifi的数据个数
// 从wifi接收缓冲区首地址开始的WIFI_RXBUFF_SIZE 个字节设置为0
memset(WIFI_RxBuff,0,WIFI_RXBUFF_SIZE);
// 发送连接服务器的指令
WIFI_Printf("AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",ServerIP,ServerPort);
printf("AT+CIPSTART=\"TCP\",\"%s\",%d",ServerIP,ServerPort);
u32 timeout1 = timeout;
while(--timeout1){
delay_ms(100);
if(strstr((char*)WIFI_RxBuff,"CONNECT")){// 跳出循环
break;
}
if(strstr((char*)WIFI_RxBuff,"CLOSED")){// 跳出循环
printf("发送成功\r\n");
return 1;
}
}
if(timeout1<=0){
printf("发送失败\r\n");
return -1;// 失败
}else{
printf("发送成功\r\n");
delay_ms(1000);
delay_ms(1000);
// 连接服务器成功,后续和服务器通信,AT+CIPSEND指令
WIFI_RxCounter =0; // 接收到wifi的数据个数
memset(WIFI_RxBuff,0,WIFI_RXBUFF_SIZE);
WIFI_Printf("AT+CIPSEND\r\n");
printf("AT+CIPSEND");
while(--timeout){
delay_ms(100);
printf("WIFI_RxBuff: %s\r\n",WIFI_RxBuff);
if(strstr((char*)WIFI_RxBuff,"OK")){// 跳出循环
break;
}
}
if(timeout<=0){
printf("发送失败\r\n");
return -1; // 超时
}else{
printf("发送成功\r\n");
return 0;// 成功
}
}
}
// 利用WiFi模块连接服务器总函数
int WIFI_Connect_IOTServer(void){
// 1.复位
if(WIFI_Reset(50) == -1){
printf("RESET FAILED\r\n");
return 1;
}
printf("WIFI RESET SUCCESS\r\n");
// 2.设置为STA模式
if(WIFI_SendCmd("AT+CWMODE=1", 200)){
printf("set wifi sta FAILED\r\n");
return 2;
}
printf("set wifi sta SUCCESS\r\n");
delay_ms(500);
// 3.上电不自动连接
if(WIFI_SendCmd("AT+CWAUTOCONN=0", 200)){
printf("cancel auto conn FAILED\r\n");
return 3;
}
printf("cancel auto conn SUCCESS\r\n");
delay_ms(500);
// 4.连接路由器
if(WIFI_JoinAP(200)){
printf("connect router FAILED\r\n");
return 4;
}
printf("connect router SUCCESS\r\n");
// 5.设置透传模式
if(WIFI_SendCmd("AT+CIPMODE=1", 200)){
printf("set direct mode FAILED\r\n");
return 5;
}
printf("set direct mode SUCCESS\r\n");
delay_ms(500);
// 6.设置单连接
if(WIFI_SendCmd("AT+CIPMUX=0", 200)){
printf("set single mode FAILED\r\n");
return 6;
}
printf("set single mode SUCCESS\r\n");
delay_ms(500);
// 7.连接服务器+发送数据
if(WIFI_Connect_Server(200)){
printf("connect server FAILED\r\n");
return 7;
}
printf("connect server SUCCESS\r\n");
return 0;
}
//连接服务器测试函数
void WIFI_Connect(void){
if(WIFI_Connect_IOTServer())
WIFI_Connect();
}
//发送数据的测试函数
void WIFI_Send_Data(void){
char* msg = "hello, wifi, esp8266\r\n";
WIFI_Printf("%s", msg);
}