STM32CubeMX新建STM32HAL库控制ESP8266WIFI模块点亮LED灯。速成,简单一步到位

引言:最近做完比赛后看到一个esp8266wifi模块,闲来无事就想利用它做点儿东西。但是找资料的过程中发现了一件很棘手的问题:我想直接利用网上esp8266wifi模块的能用的代码来做事情,但是网上找的代码要么是用的标准库,要么是用的爆改的hal库,就导致我想用hal库来弄的话,得重新改一堆函数。没有找到新手速成的文章,所以我解决完了后立马发个csdn来记录一下。

摘要:用的是esp8266wifi模块的AP(Access Point)模式:模块建立wifi热点,手机连接,利用“TCP连接”这个软件给wifi模块发送数据,wifi模块又给STM32发送串口数据,进而控制点灯与否。

目录

1.新建HAL库

2.复制函数直接用

3.手机端控制


ps(这是一篇速成文章,建议新手esp8266入门使用)

1.新建HAL库

我用的是F103RCT6,像F103C8T6和F103ZET6等等F1系列的开发板也通用,只是开头选择的芯片不一样罢了。

1.1 找芯片

1.2  高速时钟选择外部8Mhz的晶振

 1.3 选择串口

 ps(我选的是串口二,就像图示一样配置,其他的都默认)

1.4 选择LED

 1.5 开启debug调试功能

1.6 时钟树

1.7选择MDK_ARM编译器

 1.8生成文件库的选择

   弄好了之后generate code。

2.复制函数直接用

2.1.添加wifi模块.h和.c的文件,储存在Core文件夹里面

弄好了后 别忘了加入.c文件

2.2 wifi模块.c文件中添加代码

#include "My_esp8266.h"
#include "string.h"
#include "usart.h"

void u2_printf(char* fmt);
char esp8266_send_cmd(char *cmd,char *ack,u16 waittime); 


void esp8266_test(void)//测试
{
if(esp8266_send_cmd("AT","OK",50));

}

char esp8266_send_cmd(char *cmd,char *ack,u16 waittime)//发送指令和检查接收
{

u2_printf(cmd);
	
if(ack&&waittime)		
	{
		while(--waittime)	
		{
			HAL_Delay(10);
		if(strstr((const char*)RxBuffer,(const char*)ack)) //输入on,LED0亮
		{
			Uart2_Rx_Cnt=0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组	
    return 1;

    }
		}

	}

	return 0;
}


void esp8266_start_trans(void)//ESP8266初始化
{
	
	esp8266_send_cmd("AT+CWMODE=2","OK",50);//设置为AP模式
 
	esp8266_send_cmd("AT+RST","ready",20);//重启
	
	HAL_Delay(1000);       
	HAL_Delay(1000);
	HAL_Delay(1000);
	HAL_Delay(1000);
	
	esp8266_send_cmd("AT+CWSAP=\"ESP8266\",\"12345678\",1,4","OK",200);//设置WiFi名称、密码,模式
	esp8266_send_cmd("AT+CIPMUX=1","OK",20);//进入透传模式
	esp8266_send_cmd("AT+CIPSERVER=1,8080","OK",200);//设置端口8080
	esp8266_send_cmd("AT+CIPSEND","OK",50);//开始发送数据
}

uint8_t esp8266_quit_trans(void)//退出透传模式
{
	uint8_t result=1;
	u2_printf("+++");
	HAL_Delay(1000);					
	result=esp8266_send_cmd("AT","OK",20);
	return result;

}


void u2_printf(char* fmt)  
{  

	uint8_t num=0;
  char my_ch[50]={0};
	while(*fmt!=0)
	my_ch[num++]=*fmt++;
	
	my_ch[num++]='\r';
	my_ch[num++]='\n';
	
	HAL_UART_Transmit(&huart2, (uint8_t *)my_ch,num, 0xffff);
   while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX);

}



2.3 wifi模块.h文件中添加代码

#ifndef __My_esp8266_H__
#define __My_esp8266_H__

#include "main.h"

typedef uint16_t u16  ;


extern void esp8266_test(void);
extern void u2_printf(char* fmt);
extern char esp8266_send_cmd(char *cmd,char *ack,u16 waittime); 
extern void esp8266_start_trans(void);

#endif




2.4 main.h的Exported types中添加代码

/* USER CODE BEGIN ET */
extern char RxBuffer[256];
extern uint8_t Uart2_Rx_Cnt;
/* USER CODE END ET */

2.5  main.c的Private includes中添加代码

/* USER CODE BEGIN Includes */
#include <string.h>
#include "My_esp8266.h"
/* USER CODE END Includes */

2.6  main.c的Private variables中添加代码

/* USER CODE BEGIN PV */
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart2_Rx_Cnt = 0;		//接收缓冲计数
uint8_t my_test_v = 0 ;
char my_order[15]={0};
char receive_flag=0;
/* USER CODE END PV */

2.7 main.c主函数下面的USER CODE BEGIN 4下面添加中断回调函数,如下

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart2_Rx_Cnt >= 255)  //溢出判断
	{
		Uart2_Rx_Cnt = 0;
		memset(RxBuffer,0x00,sizeof(RxBuffer));	        
	}
	else
	{
		static uint8_t Uart2_count=0;
		
		RxBuffer[Uart2_Rx_Cnt] = aRxBuffer;   //接收数据转存
		if(receive_flag==0)
		{
		if(RxBuffer[Uart2_Rx_Cnt-Uart2_count]=='<')
		{	
			Uart2_count++;
		if((RxBuffer[Uart2_Rx_Cnt]=='>')||Uart2_count>=14)
		{
			uint8_t My_i=0;
		for(int i=Uart2_Rx_Cnt-Uart2_count+1;i<Uart2_Rx_Cnt+1;i++)
			my_order[My_i++]=RxBuffer[i];
			receive_flag=1;
			Uart2_count=0;
		}
	}
	}
		Uart2_Rx_Cnt++;
	}
	
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

2.8 最后主函数代码

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET );
HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
esp8266_start_trans();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 //     HAL_Delay(20);
		if(receive_flag)
	{
		receive_flag=0;
		if(strstr((const char*)my_order,(const char*)"<on>")) //输入on,LED0亮
		{
			Uart2_Rx_Cnt=0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组	
			memset(RxBuffer,0x00,sizeof(my_order)); //清空数组	
			my_test_v=1;
		}
		else if(strstr((const char*)my_order,(const char*)"<off>"))
		{
					Uart2_Rx_Cnt=0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组	
			memset(RxBuffer,0x00,sizeof(my_order)); //清空数组	
		  my_test_v=0;
		}
		else
			{
			Uart2_Rx_Cnt=0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组	
			memset(RxBuffer,0x00,sizeof(my_order)); //清空数组	
		
		}
			
 	}
		if(my_test_v==1)	
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET );
		else
	  	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET );
			
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

做完之后直接编译下载就ok。

3.手机端控制

        3.1 esp8266和核心板的连接只需要四个引脚,vcc(3.7—5v的稳定电源,不稳定的话会不断重启),gnd,rx,tx。其中,模块的rx接核心板的tx,tx接核心板的rx。

        3.2 初始化(4s)后,模块就会发出名字为esp8266的热点,密码为12345678。

 

        3.3 手机接入后打开“tcp连接”app(这个热点没有网络,有些手机连接后一会儿后自动就断开了,所以要设置下,我是直接把数据流量关了就行了)

 (随便一个网络调试助手都行,只要是支持TCP连接的就行,主要要能发字符串的,有些助手只能发16进制数据)

        3.4 连接(IP地址一般是192.168.4.1不正确的话需要用串口助手给wifi模块发送AT指令查看连接设备的地址,当然也可以程序上发送后在线调试看数组)

         3.5 发送数据,记住要加英文输入法的“<>”,就能看到灯的亮灭了。

 

        In addition:

    1.需要注意的是,esp8266wifi模块相当于一个下好程序的核心板,你只需要通过给它发送串口的AT指令来进行控制它的各种动作。初始化也不是对引脚初始化,是通过串口对它发送AT指令。所以初始化后如果不给esp8266断电的话是不用再次初始化的,因为每次初始化后重启会话4s的时间,所以想不断下程序来调试的话,可以把初始化函数(esp8266_start_trans();)注释了,就不用每次都额外等4s的时间了。

    2.我的stm32用的是串口接受中断来接受的指令,弄完这个后可以改进为串口DMA加IDLE中断的方法接收串口数据。

cubumx串口学习icon-default.png?t=M85Bhttps://blog.csdn.net/as480133937/article/details/99073783

我的程序

https://pan.baidu.com/s/1pgkcq4Y4q_rJX1B2OvvlPw?pwd=1234

  提取码:1234

  • 21
    点赞
  • 181
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
好的,下面是基于STM32CubeMX生成的代码实现的示例,用来控制ESP8266模块,从而控制LED的亮灭。 首先,在STM32CubeMX中进行如下配置: 1. 配置GPIO口控制LED的亮灭。例如,假设LED连接在PB1口上,需要将PB1口配置为GPIO输出口。 2. 配置USART1接口用来与ESP8266模块进行通信。例如,将PA9口配置为USART1_TX,将PA10口配置为USART1_RX。 3. 在USART1的配置中,选择对应的波特率、数据位、停止位等参数,例如波特率为115200。 然后,使用STM32CubeMX生成代码,并将生成的代码导入到Keil或其他编译器中,进行编译和下载到STM32F051K8U6芯片中。 下面是示例代码,其中部分代码需要根据实际情况进行修改: ```c #include "main.h" #include "stdio.h" #include "string.h" UART_HandleTypeDef huart1; GPIO_InitTypeDef GPIO_InitStruct; void LED_Control(uint8_t state) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, state); } void USART1_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } void MX_GPIO_Init(void) { GPIO_InitStruct.Pin = LED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct); } void AT_SendCommand(char *cmd, char *response) { uint8_t buffer_rx[100]; uint8_t buffer_tx[100]; memset(buffer_rx, 0, sizeof(buffer_rx)); memset(buffer_tx, 0, sizeof(buffer_tx)); sprintf((char *)buffer_tx, "%s\r\n", cmd); HAL_UART_Transmit(&huart1, buffer_tx, strlen((char *)buffer_tx), 1000); HAL_UART_Receive(&huart1, buffer_rx, sizeof(buffer_rx), 5000); if (strstr((char *)buffer_rx, response) == NULL) { printf("AT Command Failed: %s", response); } } int main(void) { HAL_Init(); USART1_Init(); MX_GPIO_Init(); char buffer_rx[100]; memset(buffer_rx, 0, sizeof(buffer_rx)); AT_SendCommand("AT", "OK"); AT_SendCommand("AT+CWMODE=1", "OK"); AT_SendCommand("AT+CWJAP=\"ssid\",\"password\"", "OK"); while (1) { AT_SendCommand("AT+CIPSTART=\"TCP\",\"server_ip\",80", "OK"); AT_SendCommand("AT+CIPSEND=4", ">"); AT_SendCommand("test", "SEND OK"); HAL_Delay(1000); } } ``` 在示例代码中,需要注意以下几点: 1. 在AT_SendCommand函数中,将需要发送的AT指令通过串口发送给ESP8266模块,并且等待ESP8266模块返回的信息。如果接收到的信息中包含了“OK”字样,则表示AT指令执行成功。 2. 在主函数中,根据需要,调用不同的AT指令,控制ESP8266模块发送数据或接收数据,并且根据接收到的数据来判断控制LED的状态,进而调用LED_Control函数来实现LED的亮灭控制。这里的示例代码中,每隔一秒钟就向一个IP为server_ip的TCP服务器发送一个字符串“test”。 3. 在示例代码中,需要根据实际情况修改ssid、password、server_ip等参数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值