【stm32】wifi ESP8266的透传 实验二(HAL库开发)

您所在的位置:网站首页 hc25wifi模块能连接blynk 【stm32】wifi ESP8266的透传 实验二(HAL库开发)

【stm32】wifi ESP8266的透传 实验二(HAL库开发)

2024-05-25 22:58| 来源: 网络整理| 查看: 265

一、

总算完成了透传,感觉没几行代码,就是在昨天的基础上,对ESP8266的AT指令进行了封装,什么选择工作模式(STA 还是 AP),查询附近WIFI热点,连接WIFi,见解服务器的IP和端口,开启透传......

我的代码的缺点:1.有点简单粗暴,逻辑程序,接收到串口的数据这类的操作没有一部处理,直接把串口1接收到的(电脑上位机再串口工具上发送的数据)同步转给串口3(ESP8266),没有用一个全局数组将数据保存下,之后改进吧。

缺点2:发送指令的函数接口中,直接用HAL_Delay() 延时去做的,我想这样的坏处就是...简陋,这里同样应该改成异步的,并且应该知道每个命令的结果是什么,如果某中间的AT指令执行不成功,应该不往下执行或者重启之类的,嗯 后续改进。

 

二、代码

esp8266.h

#ifndef ESP8266_H #define ESP8266_H #include "stm32f1xx.h" #include /*******************************************STA模式下*******************************/ //选择要连接的热点名称和密码 #define ESP8266_JOIN_AP_NAME "HonorNote10" #define ESP8266_JOIN_AP_PASSWORD "zdw123456" //选择要连接的服务器和IP 端口 #define ESP8266_CONNECT_TCPSERVER_IP "192.168.43.13" #define ESP8266_CONNECT_TCPSERVER_PORT "8000" /*******************************************STA模式下*******************************/ /*******************************************AP模式下*******************************/ //创建wifi热点:名称 密码 加密方式 #define ESP8266_BUILD_AP_NAME "ZDW_STM32F103" #define ESP8266_BUILD_AP_PASSWORD "zdw123456" #define ESP8266_BUILD_AP_FUNCTION OPEN //wifi热点的IP 端口 #define ESP8266_TcpServer_IP "192.168.1.1" #define ESP8266_TcpServer_Port "8080" #define ESP8266_TcpServer_OverTime "1800" //秒 /*******************************************AP模式下*******************************/ /* ESP8266 IO STM32 IO URXD PB10(tx) UTXD PB11 (rx) CH-PD PB8 RST PB9 */ /******* ESP8266 pins *************/ //8266 CH_PD引脚 #define ESP8266_CH_PD_PORT GPIOB #define ESP8266_CH_PD_PIN GPIO_PIN_8 #define ESP8266_CH_PD_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() //8266 RST引脚 #define ESP8266_RST_PORT GPIOB #define ESP8266_RST_PIN GPIO_PIN_9 #define ESP8266_RST_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() #define ESP8266_CH_PD_ENABLE() HAL_GPIO_WritePin(ESP8266_CH_PD_PORT,ESP8266_CH_PD_PIN,GPIO_PIN_SET) #define ESP8266_RST_ENABLE() HAL_GPIO_WritePin(ESP8266_RST_PORT,ESP8266_RST_PIN,GPIO_PIN_SET) extern UART_HandleTypeDef WifiUartHandle; //工作模式 typedef enum { AP, STA, STA_AP }Net_ModeTypeDef; //wifi创建热点 加密方式 typedef enum { OPEN = 0, WEP = 1, WPA_PSK = 2, WPA2_PSK = 3, WPA_WPA2_PSK = 4, }ENUM_AP_PsdMode_TypeDef; //网络协议 typedef enum{ enumTCP, enumUDP, } ENUM_NetPro_TypeDef; //模块连接服务器ID typedef enum{ Multiple_ID_0 = 0, Multiple_ID_1 = 1, Multiple_ID_2 = 2, Multiple_ID_3 = 3, Multiple_ID_4 = 4, Single_ID_0 = 5, } ENUM_ID_NO_TypeDef; //ESP8266GPIO初始化 void ESP8266_GPIO_Config(void); //ESP8266模块初始化 void ESP8266_Init(void); //发送AT指令到ESP8266 void ESP8266_Cmd(uint8_t *cmd); //查找附近wifi void ESP8266_Find_Wifi(void); //测试AT指令 void ESP8266_AT_Test(void); //测试透传模式 void ESP8266_PassThrough_Test(void); //ESP8266工作模式选择 void ESP8266_Net_Mode(Net_ModeTypeDef enum_mode); //连接外部wifi热点 void ESP8266_JoinAP(char *name,char * password); //ESP8266模块创建WiFi热点:wifi名 wifi密码 wifi加密方式 void ESP8266_BuildAP(char *name,char *password,ENUM_AP_PsdMode_TypeDef enunPsdMode); //ESP8266模块启动多连接 void ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx ); //Wifi模块连接外部服务器:网络协议 IP 端口 模块连接服务器ID void ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * port, ENUM_ID_NO_TypeDef id); //ESP8266模块开启或关闭服务器模式:enumMode(开启/关闭) pPortNum,服务器端口号字符串 pTimeOver服务器超时时间字符串,单位:秒 void ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver ); //获取 WF-ESP8266 的连接状态,较适合单端口时使用 uint8_t ESP8266_Get_LinkStatus ( void ); //获取 F-ESP8266 的 AP IP :pApIp,存放 AP IP 的数组的首地址 ucArrayLength,存放 AP IP 的数组的长度 uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength ); //ESP8266模块进入透传发送 void ESP8266_UnvarnishSend ( void ); #endif

esp8266.c

#include "esp8266.h" #include "bsp_usart.h" //CH-PD 和RST 引脚配置 void ESP8266_GPIO_Config() { //GPIO结构体 GPIO_InitTypeDef GPIO_InitStruct; //开启外设时钟 ESP8266_CH_PD_CLK_ENABLE(); ESP8266_RST_CLK_ENABLE(); GPIO_InitStruct.Pin = ESP8266_CH_PD_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(ESP8266_CH_PD_PORT,&GPIO_InitStruct); GPIO_InitStruct.Pin = ESP8266_RST_PIN; HAL_GPIO_Init(ESP8266_RST_PORT,&GPIO_InitStruct); } //esp8266初始化 main调用 void ESP8266_Init(void) { ESP8266_GPIO_Config(); WIFI_USART_Config(); //CHPD RST 初始化为高电平 ESP8266_CH_PD_ENABLE(); ESP8266_RST_ENABLE(); } //发送AT指令 void ESP8266_Cmd(uint8_t *cmd) { uint8_t data[2] = {'\r','\n'}; Usart_SendString(&WifiUartHandle,cmd); Usart_SendString(&WifiUartHandle,data); } //测试AT指令 main调用 测试成功 void ESP8266_AT_Test(void) { ESP8266_Cmd("AT"); HAL_Delay(2000); //ESP8266_Cmd("AT+CWLAP"); //HAL_Delay(2000); //ESP8266_JoinAP("HonorNote10","zdw123456"); //HAL_Delay(2000); } //查找附近wifi void ESP8266_Find_Wifi(void) { ESP8266_Cmd("AT+CWLAP"); } //ESP8266工作模式选择 void ESP8266_Net_Mode(Net_ModeTypeDef enum_mode) { switch(enum_mode) { case AP: ESP8266_Cmd("AT+CWMODE=2"); case STA: ESP8266_Cmd("AT+CWMODE=1"); case STA_AP: ESP8266_Cmd("AT+CWMODE=3"); default : break; } } //连接外部wifi热点 void ESP8266_JoinAP(char *name,char * password) { char cCmd [120]; sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", name, password ); ESP8266_Cmd((uint8_t*)cCmd); } //ESP8266模块创建WiFi热点:wifi名 wifi密码 wifi加密方式 void ESP8266_BuildAP(char* name,char* password,ENUM_AP_PsdMode_TypeDef enunPsdMode) { char cCmd [120]; sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", name, password, enunPsdMode ); ESP8266_Cmd ( (uint8_t*)cCmd ); } //ESP8266模块启动多连接 void ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx ) { char cStr [20]; sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) ); ESP8266_Cmd ( (uint8_t*)cStr); } //Wifi模块连接外部服务器:网络协议 IP 端口 模块连接服务器ID void ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * port, ENUM_ID_NO_TypeDef id) { char cStr [100] = { 0 }, cCmd [120]; switch ( enumE ) { case enumTCP: sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, port ); break; case enumUDP: sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, port ); break; default: break; } if ( id < 5 ) sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr); else sprintf ( cCmd, "AT+CIPSTART=%s", cStr ); ESP8266_Cmd ( (uint8_t*)cCmd ); HAL_Delay(3000); } //ESP8266模块开启或关闭服务器模式:enumMode(开启/关闭) pPortNum,服务器端口号字符串 pTimeOver服务器超时时间字符串,单位:秒 void ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver ) { char cCmd1 [120], cCmd2 [120]; if ( enumMode ) { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum ); sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver ); ESP8266_Cmd ( (uint8_t*)cCmd1 ); ESP8266_Cmd ( (uint8_t*)cCmd2 ); } else { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum ); ESP8266_Cmd ( (uint8_t*)cCmd1 ); } } //获取 WF-ESP8266 的连接状态,较适合单端口时使用 uint8_t ESP8266_Get_LinkStatus ( void ) { ESP8266_Cmd ( "AT+CIPSTATUS" ); //这里要解决:读取ESP返回的数据 //当前处理的方法是 将ESP的数据直接转uart1 打印到上位机 /*if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) ) return 2; //获得ip else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) ) return 3;//建立连接 else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) ) return 4;//失去连接 */ return 0;//0,获取状态失败 } //获取 F-ESP8266 的 AP IP :pApIp,存放 AP IP 的数组的首地址 ucArrayLength,存放 AP IP 的数组的长度 uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength ) { char uc; char * pCh; ESP8266_Cmd ( "AT+CIFSR" ); //获取ESP8266结果 放内存中 /* pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" ); if ( pCh ) pCh += 6; else return 0; for ( uc = 0; uc < ucArrayLength; uc ++ ) { pApIp [ uc ] = * ( pCh + uc); if ( pApIp [ uc ] == '\"' ) { pApIp [ uc ] = '\0'; break; } } */ return 1; } //ESP8266模块进入透传发送 void ESP8266_UnvarnishSend ( void ) { ESP8266_Cmd ( "AT+CIPMODE=1" ); HAL_Delay(2000); ESP8266_Cmd ( "AT+CIPSEND"); } //ESP8266模块退出透传模式 void ESP8266_ExitUnvarnishSend ( void ) { HAL_Delay(500); Usart_SendString (&WifiUartHandle ,"+++" ); HAL_Delay ( 500 ); } /* * 函数名:ESP8266_SendString * 描述 :WF-ESP8266模块发送字符串 * 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式 * :pStr,要发送的字符串 * :ulStrLength,要发送的字符串的字节数 * :ucId,哪个ID发送的字符串 * 返回 : 1,发送成功 * 0,发送失败 * 调用 :被外部调用 */ /* bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId ) { char cStr [20]; bool bRet = false; if ( enumEnUnvarnishTx ) { macESP8266_Usart ( "%s", pStr ); bRet = true; } else { if ( ucId < 5 ) sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 ); else sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 ); ESP8266_Cmd ( cStr, "> ", 0, 1000 ); bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 ); } return bRet; }*/ /* * 函数名:ESP8266_ReceiveString * 描述 :WF-ESP8266模块接收字符串 * 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式 * 返回 : 接收到的字符串首地址 * 调用 :被外部调用 */ /* char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx ) { char * pRecStr = 0; strEsp8266_Fram_Record .InfBit .FramLength = 0; strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0; while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag ); strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0'; if ( enumEnUnvarnishTx ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; else { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; } return pRecStr; }*/ //测试透传模式 void ESP8266_PassThrough_Test(void) { ESP8266_AT_Test(); //工作模式选择 sta ESP8266_Net_Mode(STA); HAL_Delay(3000); //连接热点 ESP8266_JoinAP(ESP8266_JOIN_AP_NAME,ESP8266_JOIN_AP_PASSWORD); HAL_Delay(5000); //不启动多连接 ESP8266_Enable_MultipleId ( DISABLE ); HAL_Delay(5000); //连接服务器 TCP IP PORT ESP8266_Link_Server(enumTCP,ESP8266_CONNECT_TCPSERVER_IP,ESP8266_CONNECT_TCPSERVER_PORT,Single_ID_0); HAL_Delay(5000); //进入透传发送 ESP8266_UnvarnishSend(); printf("set ESP8266 OK,now go into PassThrough Mode!\n"); }

stm32f1xx_it.c

在中断中处理串口接收到的数据,串口1接收到上位机的数据,就把数据直接转给串口3,相当于发送给esp8266.

同样的,进入透传模式后,服务器将数据发送给esp8266,8266接收到数据交给串口3,刺客对于stm32来说是串口3接收到数据,接收到数据后将数据直接写在串口1中,电脑上位机会把数据打印出来....

好晕啊 ... 

//串口1中断函数:stm32接收到上位机的数据 void DEBUG_USART_IRQHandler(void) { uint8_t ch = 1; if (__HAL_UART_GET_FLAG( &DebugUartHandle, UART_FLAG_RXNE ) != RESET) { //读寄存器 ch=( uint16_t)READ_REG(DebugUartHandle.Instance->DR); //将串口1的数据 写入串口3(串口3将数据 -> esp8266) WRITE_REG ( WifiUartHandle.Instance->DR,ch); } } //串口3中断函数:stm32接收到esp8266的数据 void WIFI_USART_IRQHandle(void) { uint8_t ch = 1; if (__HAL_UART_GET_FLAG( &WifiUartHandle, UART_FLAG_RXNE ) != RESET) { ch=( uint16_t)READ_REG(WifiUartHandle.Instance->DR); //给串口1 :串口1发送到上位机(显示出log) WRITE_REG ( DebugUartHandle.Instance->DR,ch); } }

main.c

初始化好esp8266的硬件后,调用透传测试接口就OK了!

int main(void) { HAL_Init(); /* 系统时钟初始化成72 MHz */ SystemClock_Config(); /* LED 端口初始化 */ LED_GPIO_Config(); //按键中断初始化 EXTI_Key_Config(); //初始化串口1 DEBUG_USART_Config(); printf("zdw is testing Wifi.....\n\n"); //初始化esp8266 ESP8266_Init(); HAL_Delay(3000); //透传任务测试:之后加入FreeRTOS后,开启一个wifi任务 ESP8266_PassThrough_Test(); while (1) { HAL_Delay(3000); //ESP8266_AT_Test(); //test_uart1(); } }

三、效果图

现在我的开发板和笔记本都连接着手机wifi热点,他俩在同一局域网下。

电脑端打开网络调试助手,设置自己的TCPServer的IP和端口8000,笔记本通过网络调试助手发送数据后,板子的wif模块接收到数据,将数据透传给stm32,stm32接收到数据将数据打印到上位机(也就是我的主机电脑)。

 

四、总结

透传做完了,感觉ESP8266的内容其实就完了。之后就去改进:加入FreeRTOS,专门给WIFI开一个任务,串口的接收也做一个任务,根据接收到的数据去完成相应动作比如点灯之类的。

可以看MQTT了,之后要做的就是:移植mqtt,阿里云物联网创建账号。

对这个现在一点不清楚该怎么做,不知道难不难.... 加油

完整工程代码:

https://download.csdn.net/download/zDavid_2018/12800241



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3