ESP8266的使用

本次博客知识来自于韦东山老师的7天物联网课程。

一、预期功能

运用ESP8266模块,使单片机与手机微信的小程序进行通信,实现手机控制LED的亮灭。并且,单片机可以远程控制微信小程序中模拟的门铃开启和关闭。

二、硬件设置

本次实验采用STM32F103C8T6,用到了以下单片机的以下功能。

GPIO_PA0,用作外部中断0,并且连接一个按键,使用按键向手机发送数据。

GPIO_PA1,连接LED灯,手机APP控制LED的亮灭。

USART2,使用串口2与ESP8266模块连接,并启用串口中断,当接收到ESP8266的信息(手机的信息)时,发送串口中断。

因为要开启调试模式,所以在SYS中要把Debug设置为Serial Wire。

三、发送程序编写

所有函数记得声明

1、定义静态变量

static uint8_t rx_data = 0;            //接收的字符
static uint8_t rx_len = 0;             //接收的长度
static uint8_t usart_rx_buf[200] = {0};//保存接收的数据

2、调用HAL库接收函数,等待接收数据,这样可以在程序一开始就启用接受中断。每次接受一个字节大小的数据。在usart.c中编写。

void USART_StartRx(void)
{
	HAL_UART_Receive_IT(&huart2, (uint8_t*)&rx_data, 1);
}

3、USART中断回调函数,保存接收的数据并启动下一次接收。每接收到一个字节的数据,发送一次中断,调用一次中断回调函数,把接受的一个字节的数据存储到usart_rx_buf[]中。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	usart_rx_buf[rx_len%200]= rx_data;
	rx_len++;
	HAL_UART_Receive_IT(&huart2, (uint8_t*)&rx_data, 1);
}

4、获取接收的数据。可以调用这个函数获取接受的数据。

uint8_t USART2_Receive(uint8_t *rx_data)
{
	memcpy(rx_data, (uint8_t*)usart_rx_buf, rx_len);
	return rx_len;
}

5、UASRT2发送数据。这里调用的时HEL库的函数。

void USART2_Transmit(uint8_t *pdata, uint16_t len, uint16_t tt)
{
    HAL_UART_Transmit(&huart2, pdata, len, tt);
}

6、清除接收的数据,运用memset把usart_rx_buf[]清空。

void USART2_ClearBuf(void)
{
    rx_len = 0;
    memset((uint8_t*)usart_rx_buf, 0, 200);
}

7、向ESP8266发送数据,要向每个命令加入换行符才能执行。

uint8_t ESP8266_SendCommand(char *cmd, char *reply, uint16_t timeout)
{
	//1.保存传入的指令
	char buf[256] = {0};
	strcat(buf, cmd); //strcpy 
	
	//2.处理AT指令(添加换行)
	if (strstr(buf, "\r\n") == 0)
	{
		strcat(buf, "\r\n");
	}
	
	//3.清理前面接收的buf
	USART2_ClearBuf();   
	
	//4.发送数据
	USART2_Transmit((uint8_t *)buf, strlen(buf), 500);
	
	//5.接收数据
	memset(buf, 0, 256); //buf清空
	while(timeout != 0)  //超时控制
	{
		if (USART2_Receive((uint8_t *)buf)) //接收数据
		{
			//检查结果
			if (strstr(buf, reply)) 
			{
				printf("%s Send ok!\r\n", cmd);//发送成功
				return 0;
			}
			else
			{
				timeout--;
				HAL_Delay(1);
			}
		}	
	}

	printf("%s Send error!\r\n", cmd);//发送失败
	return 1;
}

8、获取ESP8266的IP,因为返回的结果不一样,所以这里要重新写一个接受IP的函数。

uint8_t ESP8266_GetIP(void)
{
	uint16_t timeout = 500;
	
	//1.准备发送的指令 AT+CIFSR
	char buf[256] = {0};
	strcat(buf, "AT+CIFSR\r\n");
	
	//2.清理前面接收的buf
	USART2_ClearBuf();   
	
	//4.发送数据
	USART2_Transmit((uint8_t *)buf, strlen(buf), 500);
	
	//5.接收数据
	memset(buf, 0, 256); //buf清空
	
	while(timeout != 0)  //超时控制
	{
		if (USART2_Receive((uint8_t *)buf)) //接收数据
		{
			//检查结果
			if (strstr(buf, "OK")) 
			{
				printf("%s", buf); //打印IP
				return 0;
			}
			else
			{
				timeout--;
				HAL_Delay(1);
			}
		}	
	}
	
	printf("Get IP Failed! \r\n"); //获取失败
	return 1;
}

9、ESP8266发送UDP数据,这里使用ESP8266的UDP传输。因为发送的数据是变量,所以要重新写一个函数。

uint8_t ESP8266_Send_UDP(char *data)
{
	//1.准备发送的指令 AT+CIPSEND=len
	char buf[256] = {0};
	uint8_t len = strlen(data);
	sprintf(buf, "AT+CIPSEND=%d\r\n", len); //把格式化的数据写入字符串
	if (ESP8266_SendCommand(buf, "OK", 500) == 0) //发送指令
	{
		ESP8266_SendCommand(data, "SEND OK", 1000); //发送数据
		return 0;
	}
	return 1;
}

四、按键标志位程序编写

//在gpio.c中

static uint8_t key_flag = 0;

uint8_t Key_GetFlag(void)
{
	if(key_flag)
	{
		key_flag = 0;
		return 1;
	}
	else
		return 0;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY_Pin)
	{
		key_flag = 1;
	}
}

五、主函数编写

1、定义全局变量

  uint8_t rx_data[200] = {0};        // 保存接收数据
  uint8_t tx_data[200] = "AT\r\n";   // 保存发送数据

2、启动ESP8266模块

  USART_StartRx();   //启动开始接收数据
  ESP8266_SendCommand("AT+RST", "OK", 500);
  HAL_Delay(800);
  ESP8266_SendCommand("AT+CWMODE=1", "OK", 500);
  ESP8266_SendCommand("AT+CWJAP=\"wife名称\",\"wife密码\"", "OK", 5000);
  ESP8266_SendCommand("AT+CIPSTART=\"UDP\",\"192.168.50.230\",9999,9999,2", "OK", 500);
  ESP8266_GetIP();

3、实现按键按下操作手机微信小程序。实现手机微信小程序控制LED灯的亮灭。

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	 //按键按下
	 if (Key_GetFlag()) 
	 {
		ESP8266_Send_UDP("{\"data\":\"doorbell\",\"status\":\"1\"}");
	 }
	 
	 //收到UDP数据
	 if (USART2_Receive(rx_data))
	 {
		 //printf("%s\r\n", rx_data);
		 if (strstr((char *)rx_data, "\"dev\":\"led\",\"status\":\"0\"")) 
		 {
			printf("led off\r\n");
            printf("%s\r\n",rx_data); 
			HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
		    USART2_ClearBuf(); 
			//memset(rx_data, 0, 200);
		 }
		 else if (strstr((char *)rx_data, "\"dev\":\"led\",\"status\":\"1\""))
		 {
			printf("led on\r\n");
            printf("%s\r\n",rx_data); 
			HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
			USART2_ClearBuf(); 
			//memset(rx_data, 0, 200);			 
		 }
	 }
	  
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值