STM32外设系列

您所在的位置:网站首页 wifi模块esp8266介绍 STM32外设系列

STM32外设系列

#STM32外设系列| 来源: 网络整理| 查看: 265

文章目录 一、ESP8266简介二、固件库烧录三、常用AT指令四、访问API4.1 获取IP地址4.2 GET天气信息4.3 访问结果展示 五、实战项目5.1 串口配置5.2 检测WIFI模块连接状态5.3 发送配置指令5.4 解析天气信息 六、成果展示

一、ESP8266简介

ESP8266是嵌入式和物联网开发中常用的模块,它可以单独作为MCU使用,也可以作为一个简单的WIFI模块。ESP8266可以利用串口与单片机进行通讯。利用ESP8266可以访问一些API,获取天气信息或者完成网络授时,也可以连接云平台进行开发。

二、固件库烧录

有些新买来的ESP01-S并不能支持AT指令,需要我们手动烧录固件库。虽然烧录固件库有许多教程,但是博主烧录过两次,过程都不是特别顺利,这里专门整理一下烧录步骤,也方便后续使用。固件库和烧录软件可以联系卖家索要,这里就不再放链接了。

首先按照下表连接好引脚

引脚连接3.3V3.3VRST3.3VEN3.3VIO23.3VGNDGNDIO0GNDTXDRXDRXDTXD

打开烧写软件,选择ESP8266

ESP8266

按照下图配置

烧写固件配置图

选择串口,点击“START”,烧写完成后关闭即可。

烧写完成

此时,拔掉IO0的接地,重新上电。打开串口调试助手检查烧录情况。打开串口调试助手,发送“AT”,换行加回车,观察返回信息。如果返回“OK”,说明烧录成功。

烧录成功

三、常用AT指令

下面简单介绍一些WIFI模块常用的AT指令

AT\r\n 检查ESP8266模块连接是否正常AT+CWMODE=1\r\n 配置模块为Sta模式AT+CWJAP=“WIFI名称”,“WIFI密码”\r\n 连接指定WIFIAT+CIPMUX=0\r\n 设置成单连接AT+CIPMODE=1\r\n 开启透传模式AT+CIPSTART=“TCP”,“203.119.175.194”,80\r\n 创建TCP连接 如何获取IP地址,后面会有介绍AT+CIPMODE=1\r\n 进入透传模式 进入到透传模式后AT指令就会失效,需要退出后才能生效AT+CIPSEND\r\n 准备向服务器发送请求,前面都成功的前提下发送完这个指令后会出现一个>,此时输入GET信息即可 四、访问API

下面以访问心知天气API为例,介绍一下利用WIFI模块访问API的流程。关于心知天气API的一些介绍,这里就不再赘述了。在开始下面的操作之前,需要先按照上面介绍的AT指令顺序,配置好WIFI模块。

4.1 获取IP地址

电脑win+R,输入ping api.seniverse.com,点击确定就可以获取到IP。

ping心知天气API的返回信息

其中“116.62.81.138”就是IP地址。

4.2 GET天气信息

按照第三小节常用AT指令的输入顺序,连接WIFI,建立TCP连接。最后获取天气信息。获取天气信息时,输入以下内容

GET https://api.seniverse.com/v3/weather/now.json?key=你的密钥&location=beijing&language=zh-Hans&unit=c 4.3 访问结果展示

利用USB转TTL连接WIFI模块,利用串口调试助手发送AT指令,完成对心知天气API的访问。结果如下

心知天气API返回信息

可以看到,虽然一些是乱码,但是能够接收到天气现象代码和温度。关于天气现象代码,心知天气的API文档里有介绍

天气现象代码

后面还有很多,这里就不再列举了,具体可以去看看文档。

五、实战项目

下面就以利用WIFI模块,搭配STM32,访问心知天气API来获取天气和温度为例,展示一下WIFI的程序设计,仅供参考。该项目有以下功能

串口1与WIFI模块通信,能够检测WIFI连接是否正常利用WIFI模块访问心知天气API,利用串口2将获取到的天气和温度打印到电脑 5.1 串口配置

这里需要用到两个串口。关于串口通信的相关内容这里就不再赘述了,详细可见博主的STM32速成笔记专栏串口通信篇。串口初始化程序如下

/* *============================================================================== *函数名称:uart_init *函数功能:初始化USART *输入参数:UARTx:串口几;bound:波特率 *返回值:无 *备 注:可以修改成输入初始化哪个USART *============================================================================== */ void uart_init(UART_TypeDef UARTx,u32 bound) { // 相关结构体定义 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; switch (UARTx) { case 0: // 使能USART1,GPIOA时钟 RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.9 // USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.10 // Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; // 抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能 NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器 // USART 初始化设置 USART_InitStructure.USART_BaudRate = bound; // 串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验位 // 无硬件数据流控制 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式 USART_Init(USART1, &USART_InitStructure); // 初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收中断 USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 使能空闲中断 USART_Cmd(USART1, ENABLE); // 使能串口1 break; case 1: // 使能USART2,GPIOA时钟 RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE); // USART2_TX GPIOA.2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PA.2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.2 // USART2_RX GPIOA.3初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.3 // Usart2 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; // 抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能 NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器 // USART2 初始化设置 USART_InitStructure.USART_BaudRate = bound; // 串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验位 // 无硬件数据流控制 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式 USART_Init(USART2, &USART_InitStructure); // 初始化串口2 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 开启串口接收中断 USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); // 使能空闲中断 USART_Cmd(USART2, ENABLE); // 使能串口2 break; default: break; } }

值得注意的是,串口2挂载在APB2上,开启串口2时钟时需要注意。博主最开始用错了开启时钟的函数,导致PA2引脚一直输出低电平。

printf用于串口1的输出,需要再定义一个串口发送函数

/* *============================================================================== *函数名称:USART_Send *函数功能:串口发送函数 *输入参数:str:要发送的数据的数组首地址;UARTx:串口几 *返回值:无 *备 注:调用前先将需要发送的内容利用sprintf()函数转换成字符串,再进行发送 *============================================================================== */ void USART_Send (UART_TypeDef UARTx,u8 *str) { u8 index = 0; do { switch (UARTx) { case 0: USART_SendData(USART1,str[index ++]); while (USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); break; case 1: USART_SendData(USART2,str[index ++]); while (USART_GetFlagStatus(USART2,USART_FLAG_TXE) == RESET); break; } } while(str[index] != 0); } 5.2 检测WIFI模块连接状态

检测原理十分简单,只需要利用串口1给WIFI模块发送“AT\r\n”,检测是否接收到“OK”。如果接收到“OK”,说明连接正常。如果没有接收到“OK”,说明连接异常。利用串口2输出连接状态。串口1给WIFI模块发送“AT”程序如下

u8 gOkFlag = 0; // 配置成功标志位 /* *============================================================================== *函数名称:Med_Esp8266_CheckLink *函数功能:检查ESP8266连接状态 *输入参数:无 *返回值:0:未连接;1:连接正常 *备 注:一直发送AT,直到接收到OK *============================================================================== */ u8 Med_Esp8266_CheckLink (void) { while (!gOkFlag) { // 发送AT,检查连接状态 printf ("AT\r\n"); delay_ms(100); return 0; } gOkFlag = 0; // 清零配置成功变量 return 1; }

一直循环发送,直到检测到返回的内容中有“OK”。串口1的接收中断函数和解析函数如下

/* *============================================================================== *函数名称:USART1_IRQHandler *函数功能:USART1中断服务函数 *输入参数:无 *返回值:无 *备 注:无 *============================================================================== */ u32 gReceCount = 0; // 接收计数变量 u32 gClearCount = 0; // 清空接收数组计数变量 u8 gReceFifo[1500]; // 接收数组 u8 gReceEndFlag = 0; // 接收完成标志位 void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到一个字节 { gReceFifo[gReceCount++] = USART_ReceiveData(USART1); } else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET) //接收到一帧数据 { USART1->SR; // 先读SR USART1->DR; // 再读DR gReceEndFlag = 1; // 接收完成标志置1 } } /* *============================================================================== *函数名称:Uart_Rece_Pares *函数功能:解析串口接收内容 *输入参数:无 *返回值:无 *备 注:无 *============================================================================== */ extern u8 gOkFlag; // 配置成功标志位 void Uart_Rece_Pares(void) // 串口接收内容解析函数 { u16 tempVar = 0; // 临时循环变量 if (gReceEndFlag == 1) // 如果接收完成 { // 解析接收内容 for (tempVar = 0;tempVar gOkFlag = 1; // 成功标志位置1 break; } } // 清空接收数组 for (gClearCount = 0;gClearCount checkCunt = checkCunt + 1; // 检测计数变量加1 // 检测接收内容 Uart_Rece_Pares(); // 未连接 if (checkCunt > 1) { sprintf((char*)gString,"ESP8266未连接!\r\n"); USART_Send(UART2,gString); delay_ms(500); } } sprintf((char*)gString,"ESP8266已连接!\r\n"); USART_Send(UART2,gString); 5.3 发送配置指令

这里给出一个发送配置指令的函数,串口1给WIFI模块发送指令,串口2观察发送是否成功。

/* *============================================================================== *函数名称:Med_Esp8266_CheckLink *函数功能:检查ESP8266连接状态 *输入参数:str:要发送的指令 *返回值:无 *备 注:调用前先将需要发送的内容利用sprintf()函数转换成字符串 串口1发送指令,串口2返回信息 *============================================================================== */ u8 gSendCunt = 0; // 记录发送次数 void Med_Esp8266_SendCmd (u8 *str) { u8 string[100]; while (!gOkFlag) { // 发送AT指令 USART_Send(UART1,str); delay_ms(1000); gSendCunt = gSendCunt + 1; // 发送次数加1 // 检测接收内容 Uart_Rece_Pares(); if (gSendCunt > 10) { sprintf((char*)string,"%s指令发送失败!\r\n",str); USART_Send(UART2,string); } } sprintf((char*)string,"%s指令发送成功!\r\n",str); USART_Send(UART2,string); gSendCunt = 0; // 清零发送次数 gOkFlag = 0; // 清零配置成功变量 }

配置步骤如下

// 配置模块为Sta模式 sprintf((char*)gString,"AT+CWMODE=1\r\n"); Med_Esp8266_SendCmd(gString); // 连接指定WIFI sprintf((char*)gString,"AT+CWJAP=\"ertu\",\"ertu201801101102\"\r\n"); Med_Esp8266_SendCmd(gString); // 设置成单连接 sprintf((char*)gString,"AT+CIPMUX=0\r\n"); Med_Esp8266_SendCmd(gString); // 开启透传模式 sprintf((char*)gString,"AT+CIPMODE=1\r\n"); Med_Esp8266_SendCmd(gString); // 创建TCP连接 sprintf((char*)gString,"AT+CIPSTART=\"TCP\",\"116.62.81.138\",80\r\n"); Med_Esp8266_SendCmd(gString); // 进入透传模式 sprintf((char*)gString,"AT+CIPMODE=1\r\n"); Med_Esp8266_SendCmd(gString); // 准备向服务器发送请求 sprintf((char*)gString,"AT+CIPSEND\r\n"); Med_Esp8266_SendCmd(gString); 5.4 解析天气信息

接下来就是向服务器请求天气信息,然后解析。需要修改一下串口接收内容的解析函数,接收到“code”认为天气信息获取成功,解析并返回天气信息。

/* *============================================================================== *函数名称:Uart_Rece_Pares *函数功能:解析串口接收内容 *输入参数:无 *返回值:无 *备 注:无 *============================================================================== */ extern u8 gOkFlag; // 配置成功标志位 void Uart_Rece_Pares(void) // 串口接收内容解析函数 { u16 tempVar = 0; // 临时循环变量 u8 string[100]; // 串口打印数组 if (gReceEndFlag == 1) // 如果接收完成 { // 解析接收内容 for (tempVar = 0;tempVar gOkFlag = 1; // 成功标志位置1 break; } // 接收到API返回结果 // 针对心知天气API if (gReceFifo[tempVar] == 'c' && gReceFifo[tempVar + 1] == 'o' && gReceFifo[tempVar + 2] == 'd' && gReceFifo[tempVar + 3] == 'e') { sprintf((char*)string,"天气信息获取成功\r\n"); USART_Send(UART2,string); // 提取天气信息 sprintf((char*)string,"天气现象代码:%c 温度:%c%c℃\r\n",gReceFifo[tempVar + 7],gReceFifo[tempVar + 25] ,gReceFifo[tempVar + 26]); USART_Send(UART2,string); break; } } // 清空接收数组 for (gClearCount = 0;gClearCount


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3