STM32驱动esp8266wife模块毗连TCP服务器(极其详细的教程)
这次我要讲一下怎样使用STM32进行驱动esp8266模块去毗连TCP服务器进行通讯。后面我打算写一篇使用MQTTfx毗连阿里云的教程,然后再写一篇使用STM32进行驱动esp8266使用mqtt毗连阿里云,并实现智能云APP控制单片机,单片机控制智能云APP的教程。一:硬件准备
准备好STM32f407单片机和esp8266模块。esp8266模块如图:
https://i-blog.csdnimg.cn/direct/ceea8dab89b24723b102118325f7923a.jpeg
拍的不太好,请见谅。
二:软件准备
准备串口调试助手软件和网络调试助手软件。串口调试助手是使用来观察运行情况,将毗连情况展示出来。网络调试助手是用来以你电脑来搭一个小型服务器以供esp8266毗连。(这两个软件我都放在我的资源里面去了,自己去下就可以了)
串口调试助手软件如图:
https://i-blog.csdnimg.cn/direct/5d4cfa972f7840d8831bbf328c8fbd72.png
网络调试助手软件如图:
https://i-blog.csdnimg.cn/direct/1f7996dcac1948b4aff6632f7441272b.png
三:准备esp8266所需指令
硬件和软件准备好后,我们还需要准备esp8266所需相干下令,和具体步骤。
1:起首我们要确认esp8266模块有没有坏,使用测试指令AT来测试模块是否能正常响应
2:使用AT+CWMODE=1指令设置ESP8266,进入station模式,使其能链接电脑、手机、 路由器热点
3: 使用 AT+CWJAP_CUR="账号名","密码"指令来链接电脑、手机、 路由器热点。(指令样式为:AT+CWJAP_CUR="cx","12345678")不要用希奇字符和中文。
4:使用 AT+CIPMUX=0指令设置ESP8266毗连服务器的模式为单链接模式(同一个时候只能链接一个服务器)
5:使用 AT+CIPMODE=1指令设置ESP8266的数据传输模式-透传模式(发送数据的时候不需要指定命据长度)
6:使用 AT+CIPSTART="服务器类型",“服务器IP”,服务器端标语 指令设置ESP8266链接服务器服务器类型: TCP/UDP/SSL(指令样式为:AT+CIPSTART="TCP",“192.168.53.12”,8080)端标语那里没有双引号。到这里你就已经连上服务器了。但需要与服务器通讯还需要几步。
7:使用 AT+CIPSEND指令设置ESP8266进入数据透传模式(使用这个指令后,你在发消息就都会传个服务器)
8: 如果不需要与服务器通讯,可以使用+++指令(该指令不需要发送换行)退出数据透传模式
以上除了+++指令都需要换行后发送才有效。全部指令如果实行乐成,esp8266都会传送OK回来,出了+++。
另有一些其他的指令如:AT+CWQAP(断开热点),AT+CIPCLOSE(断开服务器)。
步骤图如图:
https://i-blog.csdnimg.cn/direct/f39ea804a0d14e38bf3cc634ad940672.png
四:写代码
如今我们已经把全部要准备的东西都准备好了,只差写代码了。起首整理一下思路,我们要初始化esp8266,所以我们要写指令给esp8266,且我们还要检查esp8266是否返回了OK。要完成这些,我们起首要能向esp8266接发信息,所以我们需要一个串口来接发信息,这里我选择的是USART3串口。然后我们先来写底子的接收和发送信息函数。
发送信息函数:
我们发送信息根本都是发字符串,所以我们要写一个发送字符串函数。代码如下:
void USART_Sendstr(USART_TypeDef* USARTx,char *str)
{
char *i=str;
while((*i)!='\0')
{
USART_SendData( USARTx, *i++);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET);
}
}https://blog.csdn.net/data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==因为字符串的末尾是 \0 符,所以我们可以检测*i是否为\0来确认是否传输完毕,再通过while循环和*i++来实现指针 i 指向的位置不断向字符串末尾移动,直到字符串全部传输完毕。(USART_SendData函数是库自带的传输数据函数,只能一字节一字节的传输)
接收函数:
我们需要在接受到信息的时候再去处理,我们不大概时时候刻都去检查信息有没有传过来,所以我需要使用串口制止函数进行接收函数。代码如图:
void USART3_IRQHandler(void)
{
uint8_t ch=0;
//判断一下,触发中断服务函数的中断类型是否为接受中断
if(USART_GetITStatus(USART3,USART_IT_RXNE))
{
ch=USART_ReceiveData(USART3);//接收数据
usart3_recev_data=ch;//将接收到的数据放在数组里
if((usart3_recev_data_index>=USART3_RX_SIZE-2))
{
usart3_recev_flag=1;//接收信息标志位
usart3_recev_data_index=0;//接收信息数组的下标
}
//清空中断触发
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
}https://blog.csdn.net/data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== usart3_recev_data[]数组是专门存放串口3接收的数据的,usart3_recev_flag是是否接收完数据的的标记位,接收完数据或数组满了后置一。 usart3_recev_data_index是数组的下标,它代表你接收的数据大小为几字节。USART3_RX_SIZE是我宏界说的数组大小。
写指令函数:
我们可以通过发送字符串函数将指令发给esp8266,但光发送可不行,我们还需要检查esp8266有没有返回数据,返回的数据有没有OK字符。
既然我们知道只要esp8266实行乐成,那它返回的数据里就肯定会有OK,那我们就可以通过strstr函数来检测数据里有没有OK字符。可以通过while(strstr(usart3_recev_data,"OK")==NULL)来不绝不断检测数据,检测到再实行后面的代码。但我们也不能不绝卡在这里,如果esp8266实行失败了,返回的数据没有OK怎么办?我们可以while((strstr(usart3_recev_data,"OK")==NULL)&&timeout){timeout--;delayms(1)}。这样就算esp8266实行失败了,返回的数据没有OK,我们也可以在肯定时间后跳出循环。具体代码如下:
uint32_t ESP8266_send_cmd(char *cmd,char *rtdata,int timeout)
{
//清空
ESP8266_rxbuf_clear();
//串口3发送数据
USART_Sendstr(USART3,cmd);
/* 查找接收数据包中的字符串 */
while((strstr((const char*)usart3_recev_data,(const char*)rtdata)==NULL)&&timeout)//等待串口接收完毕或超时退出
{
timeout--;
delay_ms(1);
}
printf("返回%s\n",usart3_recev_data);
if(timeout)
{
return 0;//找到匹配的响应字符串, 返回0
}
else
{
printf("超时\n");
return 1;//没有找到匹配的字符串
}
}https://blog.csdn.net/data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==ESP8266_rxbuf_clear函数是清空数组用的,在代码里我们通过判断timeout的值是否大于0来判断是时间耗尽退出循环还是找到匹配的字符退出循环。
配置函数:
有了上面三个函数,我们就可以正式写配置esp8266的函数了。代码如下:
void ESP8266_rxbuf_clear(void){ memset((void*)usart3_recev_data,0,4096); usart3_recev_data_index=0; usart3_recev_flag=0;}uint32_t ESP8266_send_cmd(char *cmd,char *rtdata,int timeout)
{
//清空
ESP8266_rxbuf_clear();
//串口3发送数据
USART_Sendstr(USART3,cmd);
/* 查找接收数据包中的字符串 */
while((strstr((const char*)usart3_recev_data,(const char*)rtdata)==NULL)&&timeout)//等待串口接收完毕或超时退出
{
timeout--;
delay_ms(1);
}
printf("返回%s\n",usart3_recev_data);
if(timeout)
{
return 0;//找到匹配的响应字符串, 返回0
}
else
{
printf("超时\n");
return 1;//没有找到匹配的字符串
}
}uint32_t ESP8266_test(void){ if(ESP8266_send_cmd("AT\r\n","OK",3000)==0) { printf("测试正常\n"); return 0; } else { printf("测试失败\n"); return 1; }}uint32_t ESP8266_set_station(void){ if(ESP8266_send_cmd("AT+CWMODE=1\r\n","OK",3000)==0) { printf("设置station乐成\n"); return 0; } else { printf("设置station失败\n"); return 1; }}uint32_t ESP8266_connect_wife(char *name,char *password){ char buf={0}; sprintf(buf,"AT+CWJAP_CUR=\"%s\",\"%s\"\r\n",name,password); if(ESP8266_send_cmd(buf,"OK",10000)==0) { printf("毗连热点乐成\n"); return 0; } else { printf("毗连热点失败\n"); return 1; }}uint32_t ESP8266_disconnect_wife(void){ if(ESP8266_send_cmd("AT+CWQAP\r\n","OK",3000)==0) { printf("断开热点乐成\n"); return 0; } else { printf("断开热点失败\n"); return 1; }}uint32_t ESP8266_set_connectmode(char *s){ char buf={0}; sprintf(buf,"AT+CIPMUX=%s\r\n",s); if(ESP8266_send_cmd(buf,"OK",3000)==0) { printf("设置毗连模式乐成\n"); return 0; } else { printf("设置毗连模式失败\n"); return 1; }}uint32_t ESP8266_set_transparentmode(char *s){ char buf={0}; sprintf(buf,"AT+CIPMODE=%s\r\n",s); if(ESP8266_send_cmd(buf,"OK",3000)==0) { printf("设置传输模式乐成\n"); return 0; } else { printf("设置传输模式失败\n"); return 1; }}uint32_t ESP8266_connect_server(char *ip,char *port){ char buf={0}; sprintf(buf,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",ip,port); if(ESP8266_send_cmd(buf,"OK",10000)==0) { printf("毗连服务器乐成\n"); return 0; } else { printf("毗连服务器失败\n"); return 1; }}uint32_t ESP8266_disconnect_server(void){ if(ESP8266_send_cmd("AT+CIPCLOSE\r\n","OK",4000)==0) { printf("断开服务器乐成\n"); return 0; } else { printf("断开服务器失败\n"); return 1; }}uint32_t ESP8266_set_transparent_transmission(void){ if(ESP8266_send_cmd("AT+CIPSEND\r\n","OK",3000)==0) { printf("设置透传模式乐成\n"); return 0; } else { printf("设置透传模式失败\n"); return 1; }}uint32_t ESP8266_exit_transparent_transmission(void){ USART_Sendstr(USART3,"+++"); delay_ms(1000); ESP8266_send_cmd("+++","+++",100); delay_ms(2000); return 0; }uint32_t esp8266_reset(void){ if(ESP8266_send_cmd("AT+RST\r\n","OK",10000)==0) { printf("复位乐成\n"); return 0; } else { printf("复位失败\n"); return 1; } }/* 回显打开或关闭 */int32_t esp8266_enable_echo(uint32_t b){ if(b) {if(ESP8266_send_cmd("ATE1\r\n","OK",5000)!=0) {printf("回显打开失败\n"); }} else {if(ESP8266_send_cmd("ATE0\r\n","OK",5000)!=0) { printf("回显关闭失败\n"); }} return 0;} 这些配置函数都只是调用写指令函数,换一换输入的下令字符而已。
怎样判断数据接收完毕:
我们可以初始化一个定时器,使它200ms触发一次定时制止,在制止函数内对 usart3_recev_data_index进行比较,如果usart3_recev_data_index>0且与上一次制止函数的它一样大,那么就说明接收了数据且已经接收完毕。如果不一样大,则大概其还在接收数据,如果=0,则代表且没接收数据。代码如下:
void TIM6_DAC_IRQHandler()
{
IWDG_ReloadCounter();
static uint32_t usart3_recev_data_preindex=0;
if(TIM_GetITStatus(TIM6,TIM_IT_Update))//判断是否是TIM6的中断
{
if(usart3_recev_data_index==0)
{
}
else if(usart3_recev_data_index==usart3_recev_data_preindex)
{
usart3_recev_flag=1;
}
usart3_recev_data_preindex=usart3_recev_data_index;
//清除中断标志位
TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
}
}
main函数:
代码如下:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
USART3_Init(115200);
USART1_PA9_10(9600);
ESP8266_exit_transparent_transmission();
delay_ms(2000);
esp8266_reset();
delay_ms(2000);
esp8266_enable_echo(0);
delay_s(2);
ESP8266_set_station();
ESP8266_connect_wife("Redmicx","123456qwe");
delay_ms(2000);
ESP8266_set_transparentmode("1");
//连接服务器
delay_s(3);
ESP8266_connect_server(192.168.184.1,"8080");
delay_ms(2000);
ESP8266_set_transparent_transmission();
TIM6_Init();
while(1)
{
if((usart3_recev_flag)
{
ESP8266_rxbuf_clear();
GPIO_ToggleBits( GPIOE, GPIO_Pin_14);
}
delay_ms(100);
} 五:结果视频
WeChat_20250223225924
六:一些留意点
如果你连不上电脑的热点,那你有大概是因为电脑的网络波段不对,调成2.4GHZ就行了。如果服务器连不上,你可以看一下电脑的ip地点,网络调试助手的地点调成你电脑的ip地点就行了。这些信息去网络和Internet里面的设置里看。发下令没反应的话,可以把esp8266拔了重插,或者看一下你发的下令有带换行吗。另有大概是因为你没退出透传模式,stm32下载程序的时候并没有完全断电,所以esp8266大概没有被重置。
另有什么不懂得话,可以在评论区问我。如果文章哪里写的不太好,不太对可以指正我一下,究竟我才写博客没多久,欢迎指正。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]