stm32与esp8266WIFI模块

硬件介绍

WIFI模块ESP-01S

使用AT指令控制1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客

项目需求

通过ESP-01SWIFI模块控制LED状态模拟插座

串口1用于与ESP8266通讯,串口2连接PC,用于打印log,查看系统状态

项目接线

WIFI模块TXRX分别接到单片机的RX1和TX1

CH340TXDRXD分别接到单片机的RX2和TX2

项目注意事项 

1. 在这个项目里,烧写完单片机之后,不光要点击复位,还要重启单片机电源,以确保WIFI模块重新启动

2. 在以后的工作中一般不直接在中断服务函数里处理数据,而是在收到数据后直接丢给队列,再处理数据

3. 在中断服务函数里尽量减少使用延时函数及打印函数

4. 2,3条在本项目中并没有实现,因为还没有学到Linux的队列概念,只是先留个印象

5. 由于之前的WIFI模块波特率改成了9600,所以现在连接CH340修改回 115200(使用AT指令修改)

 AP模式下控制的实现(透传)

CubeMX

1. 惯例配置(时钟,gpio,系统时钟)

2. 打开两个串口(uart1和uart2),并在WIFI模块对应的串口1打开中断

 3. 由于在中断处理函数中使用了Delay函数,得调整中断的优先级(非必要不使用,容易造成未知错误)

4. 惯例配置,导出工程(路径,编程软件)

Keil

要在魔术棒中将MiroLIB勾选,使得可以重写printf

代码:

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

//串口接收缓存(1字节)
uint8_t buf=0;

//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200

// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];

//  接收状态
//  bit15,      接收完成标志
//  bit14,      接收到0x0d
//  bit13~0,    接收到的有效字节数目
uint16_t UART1_RX_STA=0;

char buffer[12];

char connect_net[]       = "AT+CWJAP=\"bbb\",\"56893233\"\r\n";              //入网指令   \r\n新行
char connect_servere[]   = "AT+CIPSTART=\"TCP\",\"192.168.93.248\",8880\r\n";//连接服务器指令


char Transparent_mode[]  = "AT+CIPMODE=1\r\n";     //透传模式指令
char data_transmission[] = "AT+CIPSEND\r\n";       //数据传输开始指令                //数据传输
char reset[]             = "AT+RST\r\n";           //重启模块指令
char AT_OK_flag = 0;			    //OK返回值的标志位
char AT_Connect_Net_Flag = 0;		//WIFI GOT IP返回值的标志位


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;
				
				//程序运行到此处,代表数据已经完整接收,可以开始判断//
				
					//查看是否收到WIFI GOT IP
					if(strcmp(UART1_RX_Buffer,"WIFI GOT IP") == 0){
						HAL_UART_Transmit(&huart2, "111\r\n",strlen("111\r\n"), 100);
						AT_Connect_Net_Flag = 1;
					}
					//查看是否收到OK
					if(strcmp(UART1_RX_Buffer,"OK") == 0){
						HAL_UART_Transmit(&huart2, "222\r\n",strlen("222\r\n"), 100);
						AT_OK_flag = 1;
					}
					
					
					//灯控指令
					if(strcmp(UART1_RX_Buffer,"open") == 0){
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
					}
					if(strcmp(UART1_RX_Buffer,"close") == 0){
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
					}
					
					
					//如果联网失败,收到FAIL
					if(!strcmp(UART1_RX_Buffer,"FAIL")){
						HAL_UART_Transmit(&huart2, "error\r\n",strlen("error\r\n"), 100);
						int i;
						for(i = 0;i <5;i++){
							HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
							HAL_Delay(1000);}
							printf(reset);
						}
					
					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)
{//注意,printf的重写是针对串口1的,也就是wifi的,对于串口2的数据发送不能用printf 
	unsigned char temp[1]={ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);  
	return ch;
}


int main(void)
{

	HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
	// 开启接收中断
	
	HAL_UART_Receive_IT(&huart1, &buf, 1);
	HAL_UART_Transmit(&huart2, "START\r\n",strlen("START\r\n"), 100);
	
	printf(connect_net); //发送联网AT指令并等待成功
	
	while(!AT_Connect_Net_Flag)  HAL_Delay(50);//此处这个delay必须得加,不然程序会卡死
	while(!AT_OK_flag)  HAL_Delay(50);//此处这个delay必须得加,不然程序会卡死
	HAL_UART_Transmit(&huart2, "5555\r\n",strlen("5555\r\n"), 100);
	AT_OK_flag = 0;
	
	
	//发送连服务器指令并等待成功
	printf(connect_servere);
	while(!AT_OK_flag)  HAL_Delay(50);
	HAL_UART_Transmit(&huart2, "6665\r\n",strlen("6665\r\n"), 100);
	AT_OK_flag = 0;
	
	//发送透传模式指令并等待成功
	printf(Transparent_mode);
	while(!AT_OK_flag)	HAL_Delay(50);
	HAL_UART_Transmit(&huart2, "7775\r\n",strlen("7775\r\n"), 100);
	AT_OK_flag = 0;
	
	
	//发送数据传输指令并等待成功
	printf(data_transmission);
	while(!AT_OK_flag)	HAL_Delay(50);

  while (1)
  {

		printf("hhhhhhhhhhhhaaaaaaaaaa");
		HAL_UART_Transmit(&huart2, "hello shion\r\n",strlen("hello shion\r\n"), 100);

		HAL_Delay(3000);
  }

}




实验效果: 

注意!要记得将服务器打开,不然一直连接不上(以至于折磨了我好长时间调试)


在电脑串口和网络调试助手可以看到不断发来的心跳包。

同时,串口1作为单片机和WIFI的通信,而串口2作为日志发回电脑的串口助手,串口1每发送并成功接收了回应,串口2就会返回电脑成功的信息,这样用户就可以可视化的看到连接进行到了哪一步,这算是用两路串口实现了以前白盒测试和黑盒测试的效果。

 当在网络助手发送“open”加上回车时,继电器会打开;反之输入“close”加上回车,继电器会闭合

STA模式下控制的实现

在这种模式下,ESP作为路由器,由电脑连接ESP的WIFI,作为Client来接收和发送。

以下是之前学习WIFI模块时总结的,关于ESP作为STA模式下的相关命令

 

CubeMX

同上

Keil

通过白盒测试可知:在ESP作为STA的模式下,WIFI助手发送的数据在串口中显示的是有特定格式的:

如果发送“open”加回车,那么显示的是:+IPD,0,6:open

如果发送“close”加回车,那么显示的是:+IPD,0,7:close

因此,在KEIL中的代码中,字符串的比较不能直接和open close比较,而是和以上两个字符串进行比较!!!

代码

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

//串口接收缓存(1字节)
uint8_t buf=0;

//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200

// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];

//  接收状态
//  bit15,      接收完成标志
//  bit14,      接收到0x0d
//  bit13~0,    接收到的有效字节数目
uint16_t UART1_RX_STA=0;

char buffer[12];

char connect_net[]       = "AT+CWJAP=\"bbb\",\"56893233\"\r\n";              //入网指令   \r\n新行

char mode[]    = "AT+CWMODE=2\r\n";    //路由器模式指令
char mul_con[] = "AT+CIPMUX=1\r\n";    //使能多链接
char server[]  = "AT+CIPSERVER=1\r\n"; //建立TCPServer   default port = 333
char send[]    = "AT+CIPSEND=0,5\r\n"; //发送数据
char end[]     = "AT+CIPCLOSE=0\r\n";  //断开连接

char AT_Connect_Net_Flag = 0;		//WIFI GOT IP返回值的标志位

char AT_OK_flag = 0;              //OK返回值的标志位
char Client_Connent_Flag = 0;     //客户端接入返回值标志位

// 接收完成回调函数,收到一个数据后,在这里处理
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;
				
					
					
					
				//程序运行到此处,代表数据已经完整接收,可以开始判断//
				
					//查看是否收到WIFI GOT IP
					if(strcmp(UART1_RX_Buffer,"WIFI GOT IP") == 0){
						HAL_UART_Transmit(&huart2, "111\r\n",strlen("111\r\n"), 100);
						AT_Connect_Net_Flag = 1;
					}
					//查看是否收到OK
					if(strcmp(UART1_RX_Buffer,"OK") == 0){
						HAL_UART_Transmit(&huart2, "222\r\n",strlen("222\r\n"), 100);
						AT_OK_flag = 1;
					}
					
					
					//灯控指令
					if(strcmp(UART1_RX_Buffer,"+IPD,0,6:open") == 0){
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
					}
					if(strcmp(UART1_RX_Buffer,"+IPD,0,7:close") == 0){
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
					}
					
					
					//如果联网失败,收到FAIL
					if(!strcmp(UART1_RX_Buffer,"0,CONNECT")){
						Client_Connent_Flag = 1;
						}
					
					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)
{//注意,printf的重写是针对串口1的,也就是wifi的,对于串口2的数据发送不能用printf 
	unsigned char temp[1]={ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);  
	return ch;
}


int main(void)
{

	HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
	// 开启接收中断
	
	HAL_UART_Receive_IT(&huart1, &buf, 1);
	HAL_UART_Transmit(&huart2, "START\r\n",strlen("START\r\n"), 100);
	
	
	
	printf(mode);//发送客户端模式指令并等待成功
	while(!AT_OK_flag)	HAL_Delay(50);
	AT_OK_flag = 0;
	HAL_UART_Transmit(&huart1, "mode set success\r\n", strlen("mode set success\r\n"), 100);
	
	printf(mul_con);
	while(!AT_OK_flag)	HAL_Delay(50);
	AT_OK_flag = 0;
	
	printf(server);
	while(!Client_Connent_Flag)	HAL_Delay(50);
	AT_OK_flag = 0;
	
	if(Client_Connent_Flag){
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
	}

  while (1)
  {

		printf(send);//发送数据
		HAL_Delay(2000);
		printf("wdnmd");//发给串口1的,共2个字节
		HAL_Delay(2000);
  }

}


 

实现效果

打开单片机点击复位,使得电脑连上”esp8266“的WIFI,然后在网络助手中输入相关信息之后点击连接:(要提前连好wifi的情况)1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客STA模式具体连接再次参考这个

当在网络助手发送“open”加上回车时,LED1会打开;反之输入“close”加上回车,LED1会关闭

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-09 06:32:03       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-09 06:32:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-09 06:32:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-09 06:32:03       18 阅读

热门阅读

  1. springboot设置RestTemplate支持http&https

    2024-04-09 06:32:03       10 阅读
  2. Qt-线程2-moveToThread

    2024-04-09 06:32:03       13 阅读
  3. Rust---解构(Destructuring)

    2024-04-09 06:32:03       13 阅读
  4. Junit

    Junit

    2024-04-09 06:32:03      11 阅读
  5. 中国移动运营商网络码大全-2024

    2024-04-09 06:32:03       19 阅读
  6. arm-none-eabi-addr2line和arm-none-eabi-objdump使用笔记

    2024-04-09 06:32:03       12 阅读
  7. 18、Lua 错误处理

    2024-04-09 06:32:03       14 阅读
  8. VUE实现增删改查功能

    2024-04-09 06:32:03       10 阅读