零、前言
任务:这一周,想学习esp8266wifi模块的使用个驱动,学习mqtt,学会阿里云物联网的服务器使用,将自己的智能设备挂载到阿里云上,服务器可以发送指令给我的开发板,开发板完成相应功能。
而这第一步就是:先能把wifi模块驱动起来,我开发板的wifi模块是ESP8266,实验一:开发板发送AT,能够收到回复OK。就这么简单。参考的野火的资料,用的是标准固件库,而我想用HAL库开发,所以需要改一下下。
完成了程序之后,才理解了一些资料。
总结下来就是:我使用的方法就是AT指令,ESP8266烧写好固件,不需要我写wifi固件了,这里不像蓝牙芯片,之前写蓝牙芯片的程序需要考虑透传协议等等之类的,而ESP8266芯片内部集成了很多例如lwip协议等很多,很多事情不需要做,只需要给ESP8266上电,配置好串口,使能一些引脚(RST、CH_PD),最后通过串口给esp8266发送 AT指令就好了。8266会自己去解析AT指令并将结果返回给stm32.
嗯 ,听起来是不很简单,就是这么简单的一个AT指令测试程序我写了好久,卡在了好几个地方。
卡的第一个:是板载的模块上有个EN引脚要接3.3V,我是真的不知道要接,一直驱动不起来,看了下原理图查了查资料才发现这里要给它供电。然后去实验室用电烙铁直接上锡,简单粗暴。
卡的第二个:写程序的时候,没将esp8266的串口引脚和stm32的串口3引脚接正确,程序里配置错uart的tx和rx了,导致串口3驱动不起来,程序运行不出结果。
卡的第三个:串口3的波特率,tmd忘了配置了,哎我真的是!这种问题找了好久好久。。。
一、ESP8266的一些资料
二、程序代码:
bsp_uart.h
#ifndef BSP_USART_H
#define BSP_USART_H
#include "stm32f1xx.h"
#include <stdio.h>
//串口波特率
#define DEBUG_USART_BAUDRATE 115200
#define WIFI_USART_BAUDRATE 115200
/*******************************************************/ /*********************************************************/
//引脚定义 串口1
#define DEBUG_USART USART1
#define DEBUG_USART_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define DEBUG_USART_RX_PIN GPIO_PIN_10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define DEBUG_USART_TX_PIN GPIO_PIN_9
#define DEBUG_USART_IRQHandler USART1_IRQHandler
#define DEBUG_USART_IRQ USART1_IRQn
void Usart_SendString(UART_HandleTypeDef *usarthandle ,uint8_t *str);
void DEBUG_USART_Config(void);
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
extern UART_HandleTypeDef DebugUartHandle;
extern UART_HandleTypeDef WifiUartHandle;
/*********************************************************/ /*********************************************************/
//引脚定义:串口3
#define WIFI_USART USART3
#define WIFI_USART_CLK_ENABLE() __HAL_RCC_USART3_CLK_ENABLE()
#define WIFI_USART_RX_GPIO_PORT GPIOB
#define WIFI_USART_RX_GPIO_PIN GPIO_PIN_11 //PB11(UART RXD) <--> ESP8266 UTXD
#define WIFI_USART_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define WIFI_USART_TX_GPIO_PORT GPIOB
#define WIFI_USART_TX_GPIO_PIN GPIO_PIN_10 //PB10(UART TXD) <--> ESP8266 URXD
#define WIFI_USART_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define WIFI_USART_IRQHandle USART3_IRQHandler
#define WIFI_UASRT_IRQ USART3_IRQn
void WIFI_USART_Config(void);
#endif
bsp_uart.c
#include "bsp_usart.h"
//DebugUartHandle管理串口所有配置
UART_HandleTypeDef DebugUartHandle;
//WifiUart
UART_HandleTypeDef WifiUartHandle;
//配置与硬件底层无关内容:如串口协议,其中包括波特率,奇偶校验,停止位
void DEBUG_USART_Config()
{
DebugUartHandle.Instance = DEBUG_USART;
//波特率,8位字长,1停止位,无奇偶校验,无硬件控制,收发模式
DebugUartHandle.Init.BaudRate = DEBUG_USART_BAUDRATE;
DebugUartHandle.Init.WordLength = UART_WORDLENGTH_8B;
DebugUartHandle.Init.StopBits = UART_STOPBITS_1;//stm32f1xx_hal_uart.h
DebugUartHandle.Init.Parity = UART_PARITY_NONE;
DebugUartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
DebugUartHandle.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&DebugUartHandle);
//使能串口接收
__HAL_UART_ENABLE_IT(&DebugUartHandle,UART_IT_RXNE);
}
//配置WiFi的通信的uart3
void WIFI_USART_Config()
{
WifiUartHandle.Instance = WIFI_USART;
WifiUartHandle.Init.BaudRate = DEBUG_USART_BAUDRATE;
WifiUartHandle.Init.WordLength = UART_WORDLENGTH_8B;
WifiUartHandle.Init.StopBits = UART_STOPBITS_1;//stm32f1xx_hal_uart.h
WifiUartHandle.Init.Parity = UART_PARITY_NONE;
WifiUartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
WifiUartHandle.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&WifiUartHandle);
//使能串口接收
__HAL_UART_ENABLE_IT(&WifiUartHandle,UART_IT_RXNE);
}
// mcu 底层硬件相关的配置如引脚、时钟、DMA、中断
//实际被HAL_UART_Init(stm32f1xx_hal_uart.c)该函数调用
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
GPIO_InitTypeDef GPIO_Init1;
//串口1时钟 GPIO时钟
DEBUG_USART_CLK_ENABLE();
DEBUG_USART_RX_GPIO_CLK_ENABLE();
DEBUG_USART_TX_GPIO_CLK_ENABLE();
//配置引脚复用功能 TX
GPIO_Init1.Pin = DEBUG_USART_TX_PIN;
GPIO_Init1.Mode = GPIO_MODE_AF_PP;
GPIO_Init1.Pull = GPIO_PULLUP;
GPIO_Init1.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_Init1);
//配置Rx
GPIO_Init1.Pin = DEBUG_USART_RX_PIN;
GPIO_Init1.Mode = GPIO_MODE_AF_INPUT;//复用输入模式
HAL_GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_Init1);
HAL_NVIC_SetPriority(DEBUG_USART_IRQ ,0,1); //抢占优先级0,子优先级1
HAL_NVIC_EnableIRQ(DEBUG_USART_IRQ ); //使能USART1中断通道
}
if(huart->Instance == USART3)
{
//串口3的配置
GPIO_InitTypeDef GPIO_Init3;
WIFI_USART_CLK_ENABLE();
WIFI_USART_RX_GPIO_CLK_ENABLE();
WIFI_USART_TX_GPIO_CLK_ENABLE();
//配置Tx引脚复用功能
GPIO_Init3.Pin = WIFI_USART_TX_GPIO_PIN;
GPIO_Init3.Mode = GPIO_MODE_AF_PP;
GPIO_Init3.Pull = GPIO_PULLUP;
GPIO_Init3.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(WIFI_USART_TX_GPIO_PORT, &GPIO_Init3);
//配置Rx
GPIO_Init3.Pin = WIFI_USART_RX_GPIO_PIN;
GPIO_Init3.Mode = GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(WIFI_USART_RX_GPIO_PORT, &GPIO_Init3);
HAL_NVIC_SetPriority(WIFI_UASRT_IRQ ,0,1); //抢占优先级0,子优先级1
HAL_NVIC_EnableIRQ(WIFI_UASRT_IRQ ); //使能USART3中断通道
}
}
/***************** 发送字符串 **********************/
/* HAL_UART_Transmit 函数(这是一个阻塞的发送函数,无需重复判断串口是否发送完成)
发送每个字符,直到遇到
空字符才停止发送。*/
void Usart_SendString(UART_HandleTypeDef *usarthandle,uint8_t *str)
{
unsigned int k=0;
do
{
HAL_UART_Transmit(usarthandle,(uint8_t *)(str + k) ,1,1000);
k++;
} while(*(str + k)!='\0');
}
//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
HAL_UART_Transmit(&DebugUartHandle, (uint8_t *)&ch, 1, 1000);
return (ch);
}
//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
int ch;
HAL_UART_Receive(&DebugUartHandle, (uint8_t *)&ch, 1, 1000);
return (ch);
}
esp8266.h
#ifndef ESP8266_H
#define ESP8266_H
#include "stm32f1xx.h"
#include <stdio.h>
/*
ESP8266 IO <------> STM32 IO
URXD PB10(tx)
UTXD PB11 (rx)
CH-PD PB8
RST PB9
*/
/******* ESP8266 pins *************/
//8266 CH_PD引脚
#define ESP8266_CH_PD_PORT GPIOB
#define ESP8266_CH_PD_PIN GPIO_PIN_8
#define ESP8266_CH_PD_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
//8266 RST引脚
#define ESP8266_RST_PORT GPIOB
#define ESP8266_RST_PIN GPIO_PIN_9
#define ESP8266_RST_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define ESP8266_CH_PD_ENABLE() HAL_GPIO_WritePin(ESP8266_CH_PD_PORT,ESP8266_CH_PD_PIN,GPIO_PIN_SET)
#define ESP8266_RST_ENABLE() HAL_GPIO_WritePin(ESP8266_RST_PORT,ESP8266_RST_PIN,GPIO_PIN_SET)
//functions
extern UART_HandleTypeDef WifiUartHandle;
void ESP8266_GPIO_Config(void);
void ESP8266_Init(void);
#endif
esp8266.c
#include "esp8266.h"
#include "bsp_usart.h"
//CH-PD 和RST 引脚配置
void ESP8266_GPIO_Config()
{
//GPIO结构体
GPIO_InitTypeDef GPIO_InitStruct;
//开启外设时钟
ESP8266_CH_PD_CLK_ENABLE();
ESP8266_RST_CLK_ENABLE();
GPIO_InitStruct.Pin = ESP8266_CH_PD_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ESP8266_CH_PD_PORT,&GPIO_InitStruct);
GPIO_InitStruct.Pin = ESP8266_RST_PIN;
HAL_GPIO_Init(ESP8266_RST_PORT,&GPIO_InitStruct);
}
//esp8266初始化 main调用
void ESP8266_Init(void)
{
ESP8266_GPIO_Config();
WIFI_USART_Config();
//CHPD RST 初始化为高电平
ESP8266_CH_PD_ENABLE();
ESP8266_RST_ENABLE();
}
stm32f1xx_it.c
//串口1中断函数:stm32接收到上位机的数据
void DEBUG_USART_IRQHandler(void)
{
uint8_t ch = 1;
if (__HAL_UART_GET_FLAG( &DebugUartHandle, UART_FLAG_RXNE ) != RESET)
{
//读寄存器
ch=( uint16_t)READ_REG(DebugUartHandle.Instance->DR);
//将串口1的数据 写入串口3(串口3将数据 -> esp8266)
WRITE_REG ( WifiUartHandle.Instance->DR,ch);
}
}
//串口3中断函数:stm32接收到esp8266的数据
void WIFI_USART_IRQHandle(void)
{
uint8_t ch = 1;
if (__HAL_UART_GET_FLAG( &WifiUartHandle, UART_FLAG_RXNE ) != RESET)
{
ch=( uint16_t)READ_REG(WifiUartHandle.Instance->DR);
//给串口1
WRITE_REG ( DebugUartHandle.Instance->DR,ch);
}
}
main函数
int main(void)
{
HAL_Init();
/* 系统时钟初始化成72 MHz */
SystemClock_Config();
/* LED 端口初始化 */
LED_GPIO_Config();
//按键中断初始化
EXTI_Key_Config();
//初始化串口1
DEBUG_USART_Config();
printf("zdw is testing Wifi.....\n\n");
//初始化esp8266
ESP8266_Init();
HAL_Delay(3000);
while (1)
{
HAL_Delay(1000);
}
}
三、实验结果:
能够正确相应AT指令,之后就可以调用AT指令,让wifi模块工作啦。
[20:17:33.756]收←◆zdw is testing Wifi.....
sl\0l湊s宐鉵?€l?p寍巸熿p挒帓滌?p宲騨瀄0lnn?bbp寧cl`rlp騨鄠淺0儚lbo忖ol??b寍~騨?l寧\0l`?nnl`nr彃焥bl`p髇鄠淺0r寽挏?bo忖o鞆煂弍寍騨?l`?onl`nr彃焥倻鉲`p騨鄠淺0s寽挏囔€co忏n巶?p寍~髇颸0l`?nnl?rlnr彃焥bl`r挓sbl`rl寣o淺0宲~騨焅0専鉩rnnn?\0l宐`宲弆bl\0靗€搇靗€搾??\0巰lll~rl\0靗€搶lln??\0l拰髄l\0靗€拰寪psn靗bc挏\0?\0弿co瀝ll挒r?寍掆ol瀼挏?l`rl
[20:17:33.884]收←◆?諄MEM CHECK FAIL!!!
[20:17:34.103]收←◆鋜l??
ready
[20:19:26.041]发→◇AT
□
[20:19:26.045]收←◆AT
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
OK
[20:19:31.767]收←◆
[20:19:45.765]发→◇AT+CWMODE=1
□
[20:19:45.772]收←◆AT+CWMODE=1
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
OK
[20:19:53.749]发→◇AT+CWLAP
□
[20:19:53.755]收←◆AT+CWLAP
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
busy p...
[20:19:55.885]收←◆+CWLAP:(3,"HUAWEI Mate 30 Pro 5G",-77,"46:45:84:e6:66:5c",1)
+CWLAP:(0,"HelloBike",-75,"7c:57:3c:db:a9:40",1)
+CWLAP:(0,"HelloBike-Guest",-77,"7c:57:3c:db:a9:41",1)
+CWLAP:(0,"HelloBike",-67,"48:4a:e9:5a:b9:a0",1)
+CWLAP:(0,"HelloBike-Guest",-67,"48:4a:e9:5a:b9:a1",1)
+CWLAP:(0,"ESP_1C5CE0",-78,"ca:2b:96:1c:5c:e0",1)
+CWLAP:(0,"HelloBike",-61,"48:4a:e9:5a:a9:00",6)
+CWLAP:(0,"HelloBike-Guest",-61,"48:4a:e9:5a:a9:01",6)
+CWLAP:(4,"MastermindWorld",-91,"30:0d:9e:b9:cb:b1",6)
+CWLAP:(3,"qianruan",-69,"20:76:93:40:f6:54",6)
+CWLAP:(3,"DIRECT-1GWINDOWS-9ESQKK9msGW",-80,"c2:b6:f9:3e:b2:73",6)
+CWLAP:(0,"HelloBike",-82,"48:4a:e9:5a:b4:a0",11)
+CWLAP:(0,"HelloBike-Guest",-80,"48:4a:e9:5a:b4:a1",11)
+CWLAP:(0,"HelloBike",-91,"48:4a:e9:5a:ae:00",11)
+CWLAP:(0,"HelloBike-Guest",-91,"48:4a:e9:5a:ae:01",11)
+CWLAP:(0,"HelloBike",-81,"48:4a:e9:5a:ab:20",11)
+CWLAP:(0,"HelloBike",-83,"48:4a:e9:5a:b4:00",11)
+CWLAP:(0,"HelloBike-Guest",-84,"48:4a:e9:5a:b4:01",11)
OK
四、总结
所谓万事开头难,这篇博客就只是一个wifi学习的开头,只是正确配置了wifi模块的串口,正确使能了相应的引脚,能让wifi模块工作。只是能给WiFi发送AT,esp8266回复OK。后面的实验,要把esp8266的功能函数(AT指令)封装好,发送字符串、透传模式、连接热点、使用指定协议(TCP/UDP)连接到服务器、主动和服务器断开连接、mqtt协议实现...........