STM32CubeMX新建STM32HAL库控制ESP8266WIFI模块点亮LED灯。速成,简单一步到位
引言:最近做完比赛后看到一个esp8266wifi模块,闲来无事就想利用它做点儿东西。但是找资料的过程中发现了一件很棘手的问题:我想直接利用网上esp8266wifi模块的能用的代码来做事情,但是网上找的代码要么是用的标准库,要么是用的爆改的hal库,就导致我想用hal库来弄的话,得重新改一堆函数。没有找到新手速成的文章,所以我解决完了后立马发个csdn来记录一下。
摘要:用的是esp8266wifi模块的AP(Access Point)模式:模块建立wifi热点,手机连接,利用“TCP连接”这个软件给wifi模块发送数据,wifi模块又给STM32发送串口数据,进而控制点灯与否。
目录
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串口学习https://blog.csdn.net/as480133937/article/details/99073783
我的程序
https://pan.baidu.com/s/1pgkcq4Y4q_rJX1B2OvvlPw?pwd=1234
提取码:1234