基于stm32控制的ESP8266在设备模式下通讯

一、文章中要用的指令

指令作用
AT+UART=115200,8,1,0,0之前的51通讯是9600,这里的321用的是115200,需要改一下波特率
AT+CWMODE=XX是1代表station(设备)模式 ,X是2代表AP(路由)模式 ,X是3.代表双模模式(工作模式在串口助手里已经设置为双模,掉电后自动保存,因此程序中并未体现配置工作模式,这个配置模式的指令写与不写均可以
AT+CWJAP="PEI","jmgcyjs."第一个引号里的是wifi的名称,第二个是WiFi密码,要注意的是,使用的时候一定要确保你的电脑和wifi模块连接的是一个wifi,否则无法成功。
AT+CIPSTART="TCP","192.168.1.112",8880

连接服务器,TCP代表客户端模式,电脑连接无线网地址192.168.1.112,8880代表端口号

AT+CIPMODE=1透传指令,不用受发送次数还有发送字节大小限制
AT+CIPSEND开始发送
AT+RST重启指令

有关esp8266的烧录我在之前说过,有兴趣的可以看一看,http://t.csdnimg.cn/J3Sid

二、代码部分

#include "main.h"
#include "usart.h"
#include "gpio.h"

#include <string.h>
#include <stdio.h>

uint8_t buf=0;//串口接收缓存(1字节)
#define UART1_REC_LEN 200//定义最大接收字节数 200,可根据需求调整
uint8_t UART1_RX_Buffer[UART1_REC_LEN];// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint16_t UART1_RX_STA=0;//  接收状态
//  bit15,      接收完成标志
//  bit14,      接收到0x0d
//  bit13~0,    接收到的有效字节数目

void SystemClock_Config(void);

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	// 判断中断是由哪个串口触发的
	if(huart->Instance == USART1)
	{
		// 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
		if((UART1_RX_STA & 0x8000) == 0)
		{
			// 如果已经收到了 0x0d (回车),
			if(UART1_RX_STA & 0x4000)
			{
				// 则接着判断是否收到 0x0a (换行)
				if(buf == 0x0a)
				{	// 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
					UART1_RX_STA |= 0x8000;
					if(!strcmp((const char*)UART1_RX_Buffer,"WIFI GOT IP"))
					AT_Connect_Net_Flag = 1;	
					
					if(!strcmp((const char*)UART1_RX_Buffer,"OK"))
						AT_OK_Flag = 1;
					
					if(!strcmp((const char*)UART1_RX_Buffer,"L1"))
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
					if(!strcmp((const char*)UART1_RX_Buffer,"L0"))
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
					
					if(!strcmp((const char*)UART1_RX_Buffer,"FALL"))//连接网络不成功就会给单片机返回FALL
					{
						int i=0;
						for(i=0;i<5;i++)
						{
						HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
							HAL_Delay(1000);
						}
					}
					memset(UART1_RX_Buffer,0,UART1_REC_LEN);
						UART1_RX_STA=0;
				}
				else
					// 否则认为接收错误,重新开始
					UART1_RX_STA = 0;
			}
			else	// 如果没有收到了 0x0d (回车)
			{
				//则先判断收到的这个字符是否是 0x0d (回车)
				if(buf == 0x0d)
				{
					// 是的话则将 bit14 位置为1
					UART1_RX_STA |= 0x4000;
				}
				else
				{
					// 否则将接收到的数据保存在缓存数组里
					UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
					UART1_RX_STA++;
					
					// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
					if(UART1_RX_STA > UART1_REC_LEN - 1)
						UART1_RX_STA = 0;
				}
			}
		}
		// 重新开启中断
		HAL_UART_Receive_IT(&huart1, &buf, 1);
	}
}

int fputc(int ch, FILE *f)
{      
	unsigned char temp[1]={ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);  
	return ch;
}

int main(void)
{
HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
HAL_UART_Receive_IT(&huart1, &buf, 1);//系统滴答定时器,防止死机
HAL_UART_Transmit(&huart2,"let's go\r\n",strlen("let's go\r\n"),100);
printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");//入网指令
while(!AT_OK_Flag)
	HAL_Delay(50);
HAL_UART_Transmit(&huart2,"333\r\n",strlen("333\r\n"),100);
	AT_OK_Flag = 0;
	//发送连服务器指令并等待成功
	printf("AT+CIPSTART=\"TCP\",\"192.168.1.105\",8880\r\n"); //连接服务器指令
	while(!AT_OK_Flag)
		HAL_Delay(100);
	HAL_UART_Transmit(&huart2,"433\r\n",strlen("433\r\n"),100);
	AT_OK_Flag = 0;
	//发送透传模式指令并等待成功
	printf("AT+CIPMODE=1\r\n"); //透传指令
	while(!AT_OK_Flag)
		HAL_Delay(50);
	HAL_UART_Transmit(&huart2,"533\r\n",strlen("533\r\n"),100);
	AT_OK_Flag = 0;
	//发送数据传输指令并等待成功
	printf("AT+CIPSEND\r\n");//数据传输开始指令
	while(!AT_OK_Flag)
		HAL_Delay(50);
	HAL_UART_Transmit(&huart2,"633\r\n",strlen("633\r\n"),100);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_UART_Transmit(&huart2,"666\r\n",strlen("666\r\n"),100);
		HAL_Delay(1000);

  }
  /* USER CODE END 3 */
}

三、思路分析

        这里的思路和51哪里的差不多。都是通过串口将单片机中的指令发给ESP8266.但是与51不同是,51在调试中用的是一个串口单向的调试,而32的是用的双向两个串口调试。

51测试的思路

        32的具体的思路是这样的,基于上一篇文章的串口基础上,每当执行到UART1_RX_STA |= 0x8000时,代表着单片机的接收寄存器已经完全收到了来自单片机内部printf重映射的指令或是网络调试助手的指令。

        接着从头说起,上电之后首先要输入入网指令

        printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");

         输入完成后进入中断回调函数,如果你的网络名称和密码都没问题,ESP8266会通过串口1给单片机回复对应的内容

WIFI CONNECTED
WIFI GOT IP

OK

如图所示

        UART1_RX_STA |= 0x8000;下面的第一个if将会判断成功,将WIFI GOT IP返回值的标志位AT_Connect_Net_Flag 变为1,接着是ESP8266返回OK指令,就可以让OK返回值的标志位变为1,同时在main函数里在printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n")下面有while循环标志位的判断来确保每一步的进行都是正确的。每当OK返回值的标志位使用完后,就把OK返回值的标志位AT_OK_Flag变为0。等到下一次ESP8266回复给单片机OK时,就进入中断将AT_OK_Flag变为1,程序可以继续正常运行。

      思路就是这这样一个思路。

接着就是

 连接服务器指令是否成功,  透传指令是否成功 ,数据传输开始指令是否成功 ,如果成功ESP8266就都会返回OK.如果在哪一步不成功,就会卡到哪里一直死循环。

当然了,这里还是要细说一下,失败也是分情况的。第一种失败是入网指令的失败,这个时候如果你失败,ESP8266会给单片机返回FALL,这时候我们的LED1会亮灭5次。如果你是入网成功后的失败,那你就是会一直陷入死循环。

四、其它

    1.关于while后面加延时,你可以不加,只要不死机。每个while的条件后面不是直接跟;而是跟的延时函数,这样可以避免死机。

     2.HAL_NVIC_SetPriority(SysTick_IRQn,0,0);滴答定时器优先级提高,中断中加入了延时函数,如果不把滴答定时器优先级提高,也会死机。

      3.全部成功后,进入网络助手后拾取指令完成后,一定记得要带上回车再点击发送,因为我们的串口输入判断\r\n是一个重要的依据,不能不带上回车。

      4.按照51的写法,把指令写成数组

char LJWL[]  = "AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n"; //入网指令
char LJFWQ[] = "AT+CIPSTART=\"TCP\",\" 192.168.10.206\",8880\r\n"; //连接服务器指令
char TCMS[]  = "AT+CIPMODE=1\r\n";  //透传指令
char SJCS[]  = "AT+CIPSEND\r\n";    //数据传输开始指令
char CQMK[] = "AT+RST\r\n";        //重启模块指令

      你可以写成printf(LJWL)的形式,意思就是这个就是把数组名为LJWL的数组里的内容发出去,也就是发送入网指令。前提是你要把你的wifi模块的波特率改过来才行。你也可以像我一样使用printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");,二选一。使用printf(LJWL)记得把这5个字符串写入数组。

   5.还有一点我要补充一下,不知道大家有没有注意到一个小细节

在第一章里,入网指令写的是AT+CWJAP="PEI","jmgcyjs."但是到了printf里我写的是printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");。\"PEI\",\"jmgcyjs.\"\r\n和"PEI","jmgcyjs."一样吗?确实不一样。使用的场景不一样AT+CWJAP="PEI","jmgcyjs."是在串口助手里使用。写完这条指令后,点击发送新行就相当于回车换行的/r/n,而"AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n"是在单片机内部使用,\"使用的是转义字符,简单里说就是让“不要有别的意思,就让它是个引号。大家也可以自己查一下关于转义字符的使用,我就不多说了。    

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值