国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

從零開始制作一個(gè)基于STM32和ESP8266-01S的智能時(shí)鐘(3)ESP8266-01S模塊(上)

這篇具有很好參考價(jià)值的文章主要介紹了從零開始制作一個(gè)基于STM32和ESP8266-01S的智能時(shí)鐘(3)ESP8266-01S模塊(上)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


前言

提示:這里可以添加本文要記錄的大概內(nèi)容:之前在忙著,現(xiàn)在繼續(xù)補(bǔ)充完整,然后這次的ESP-01S的典型應(yīng)用圖是沒有連接RST引腳的,但是我的項(xiàng)目是用到了RST引腳的,所以需要使用跳線連接一下RST引腳。

本項(xiàng)目需要基礎(chǔ)的stm32單片機(jī)知識(shí),這里我推薦
鏈接:https://www.bilibili.com/video/BV1th411z7sn?p=1&vd_source=e9ab6ae9ee7c74bb73c9334f2da0a743
如果不想看那么多,看到4-2 OLED顯示屏就差不多。我使用的是他的OLED基本例程。


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、ESP8266-01S模塊

ESP-01S 是由安信可科技開發(fā)的 Wi-Fi 模塊,該模塊核心處理器 ESP8266 在較小尺寸封裝中集成了業(yè)界領(lǐng)先的 Tensilica L106 超低功耗 32 位微型 MCU,帶有 16 位精簡(jiǎn)模式,主頻支持 80 MHz 和 160 MHz,支持 RTOS,集成 Wi-Fi MAC/ BB/RF/PA/LNA。
ESP-01S Wi-Fi 模塊支持標(biāo)準(zhǔn)的 IEEE802.11 b/g/n 協(xié)議,完整的 TCP/IP 協(xié)議棧。用戶可以使用該模塊為現(xiàn)有的設(shè)備添加聯(lián)網(wǎng)功能,也可以構(gòu)建獨(dú)立的網(wǎng)絡(luò)控制器。
ESP8266 擁有完整的且自成體系的 Wi-Fi 網(wǎng)絡(luò)功能,既能夠獨(dú)立應(yīng)用,也可以作為從機(jī)搭載于其他主機(jī) MCU 運(yùn)行。

這里我截一些規(guī)格書和說明書上面一些圖給大家參考一下。可以去這個(gè)網(wǎng)址找規(guī)格書和說明書:https://docs.ai-thinker.com/esp8266/docs

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

我們可以看到ESP8266-01S模塊是支持UART通信的,通信的波特率默認(rèn)為115200bps。一般來說,EN和RST引腳需要外接一個(gè)上拉電阻,但是看原理圖我們可以發(fā)現(xiàn),ESP-01S內(nèi)部已經(jīng)上拉這兩個(gè)引腳了,不需要我們操心,所以我們按照下面的電路圖將ESP-01S連接到STM32上即可。但是我的代碼中還使用了RST引腳作為復(fù)位引腳,所以還需要連接RST引腳到STM32上。
RST引腳因?yàn)樯侠娮璧淖饔媚J(rèn)高電平,低電平有效,所以我們想要復(fù)位一次的話,只需要使用STM32拉低RST引腳,再將它拉高回到默認(rèn)高電平狀態(tài)。
esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

還有使用說明書上有個(gè)注意事項(xiàng),不清楚這是為什么。但是我測(cè)試的時(shí)候發(fā)現(xiàn)如果接到ESP-01S的3.3V和GND不穩(wěn)定會(huì)出現(xiàn)無法通信的情況,并且ESP-01S會(huì)發(fā)熱變得燙手,所以測(cè)試的過程請(qǐng)隨時(shí)注意ESP-01S的狀態(tài)避免發(fā)生意外,注意、注意、注意(一般是剛上電的時(shí)候)。解決辦法是可以將3.3V和GND重新連接,直到可以通信?;蛘呦朕k法找個(gè)穩(wěn)定的3.3V和GND
esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

二、ESP8266-01S模塊使用方法

1.AT指令

ESP8266 系列模組出廠時(shí)已默認(rèn)內(nèi)置 AT 固件,且默認(rèn)波特率為 115200。我們只需要將ESP8266-01S模塊通過UART連接到STM32上,然后使用STM32發(fā)送AT指令的方式將可以控制ESP8266-01S模塊執(zhí)行各種功能。

我這里就只介紹我用到的AT指令,其他的你們可以去網(wǎng)上找,也可以去看說明書。網(wǎng)址:https://www.cnblogs.com/milton/p/14718010.html
還有AT指令需要加回車符和換行符"\r\n".

  1. AT :測(cè)試AT開發(fā)模式啟動(dòng)
  2. AT+CWMODE=1 :設(shè)置WIFI應(yīng)用模式,1–Station模式,2–AP模式,3–AP兼Station模式。 AP指ESP8266 作為接入點(diǎn),station指ESP8266 作為客戶端
  3. AT+CWJAP=“WIFI名字”,“WIFI密碼” :設(shè)置 ESP8266 Station 需連接的 AP。
  4. AT+CIPSTART=“TCP”,“59.82.34.102”,80 :ESP8266 設(shè)備作為 TCP client 連接到服務(wù)器,這里高德地圖的遠(yuǎn)端 IP 地址為59.82.34.102,遠(yuǎn)端端口號(hào)為 80。
  5. AT+CIPMODE=1 :設(shè)置透?jìng)髂J剑纯梢砸恢卑l(fā)送。透?jìng)髂J絺鬏敃r(shí),如果連接斷開,ESP8266 會(huì)不停嘗試重連,此時(shí)單獨(dú)輸? +++【不用加回車換行符】 退出透?jìng)?,則停?重連;普通傳輸模式則不會(huì)重連,提示連接斷開。)(一般來說普通傳輸模式交換一次數(shù)據(jù)后就會(huì)斷開TCP連接,如果想要繼續(xù)通信需要重新進(jìn)行TCP連接,所以為了方便一直獲取天氣和時(shí)間信息,這里選擇透?jìng)髂J剑?/li>
  6. AT+CIPSEND : ESP8266 設(shè)備向服務(wù)器發(fā)送數(shù)據(jù),在透?jìng)髂J綍r(shí),進(jìn)?透?jìng)髂J桨l(fā)送數(shù)據(jù),每包最大 2048 字節(jié),或者每包數(shù)據(jù)以 20 ms 間隔區(qū)分。(進(jìn)入發(fā)送數(shù)據(jù)模式后,AT指令無效,如需退出發(fā)送數(shù)據(jù)模式,發(fā)送 +++【不用加回車換行符】,然后就可以使用AT指令)。

2.代碼分析

首先是串口外設(shè)初始化函數(shù)和串口發(fā)送功能函數(shù),這里使用重定義print函數(shù)的方法實(shí)現(xiàn)串口print函數(shù)打印,但是實(shí)際測(cè)試過程發(fā)現(xiàn)UsartPrintf()發(fā)送大量數(shù)據(jù)時(shí),會(huì)出現(xiàn)數(shù)據(jù)丟失的情況,(應(yīng)該是因?yàn)閁sartPrintfBuf[296]設(shè)置的數(shù)組長度不夠,如果想要發(fā)送大量數(shù)據(jù)可以試著修改一下這個(gè)數(shù)組長度),所以發(fā)送大量字符串?dāng)?shù)據(jù)時(shí)可以使用Usart_SendString()函數(shù)。然后本項(xiàng)目使用串口1進(jìn)行調(diào)試,所以需要對(duì)串口1進(jìn)行初始化,但是串口1并不進(jìn)行接收數(shù)據(jù)操作,所以可以注釋掉串口1的接收中斷使能和接收中斷函數(shù),效果不會(huì)改變。項(xiàng)目使用串口2和ESP-01S連接通信,使用串口2發(fā)送AT指令和接收ESP-01S返回的數(shù)據(jù),為了方便這里將串口2的接收中斷函數(shù)放到ESP-01S操作文件中。

/*
************************************************************
*	函數(shù)名稱:	UsartPrintf
*
*	函數(shù)功能:	格式化打印
*
*	入口參數(shù):	USARTx:串口組
*				fmt:不定長參
*
*	返回參數(shù):	無
*
*	說明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{

	unsigned char UsartPrintfBuf[296];		/*接收輸入變量數(shù)組,如果數(shù)組不夠大,可以修改一下*/
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	{
		USART_SendData(USARTx, *pStr++);
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
	}

}
/*
************************************************************
*	函數(shù)名稱:	Usart_SendString
*
*	函數(shù)功能:	串口數(shù)據(jù)發(fā)送
*
*	入口參數(shù):	USARTx:串口組
*				str:要發(fā)送的數(shù)據(jù)
*				len:數(shù)據(jù)長度
*
*	返回參數(shù):	無
*
*	說明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//發(fā)送數(shù)據(jù)
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待發(fā)送完成
	}

}

還有介紹一下USART_FLAG_TXE標(biāo)志位,USART_FLAG_TXE是數(shù)據(jù)寄存器空標(biāo)志位。串口發(fā)送數(shù)據(jù)的方式是數(shù)據(jù)先從MCU內(nèi)部的CPU到數(shù)據(jù)寄存器,再到移位寄存器,然后由移位寄存器發(fā)送到TX線上。而使用USART_SendData()函數(shù)就是將數(shù)據(jù)從CPU轉(zhuǎn)移到數(shù)據(jù)寄存器,這個(gè)過程是非常迅速的,而數(shù)據(jù)從數(shù)據(jù)寄存器到移位寄存器的過程相對(duì)比較緩慢,因?yàn)橐莆患拇嫫饕晃晃坏匕l(fā)送數(shù)據(jù),而數(shù)據(jù)寄存器需要等移位寄存器變空才能發(fā)送數(shù)據(jù)到移位寄存器,所以為了避免數(shù)據(jù)從CPU轉(zhuǎn)移到數(shù)據(jù)寄存器的過程太快而導(dǎo)致數(shù)據(jù)覆蓋產(chǎn)生數(shù)據(jù)丟失的問題,需要設(shè)置一個(gè)while循環(huán)等USART_FLAG_TXE變?yōu)?,即數(shù)據(jù)寄存器變空。

esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

經(jīng)過這個(gè)項(xiàng)目,我對(duì)于串口中斷有不一樣的理解。我一開始以為串口接收到一幀數(shù)據(jù)(指多bit數(shù)據(jù))會(huì)一直處于接收中斷函數(shù)中,不會(huì)中途跳回主函數(shù)中。但經(jīng)過測(cè)試,事實(shí)上,串口接收到一幀數(shù)據(jù)時(shí)當(dāng)然會(huì)先進(jìn)入中斷函數(shù)接收1bit數(shù)據(jù),然而就算后面還有幾bit數(shù)據(jù)沒接收完,它還是會(huì)跳回主函數(shù)執(zhí)行一小段時(shí)間,然后再回到中斷函數(shù)接收下一bit數(shù)據(jù),循環(huán)這個(gè)過程,直到接收完成。
esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

所以如果接收不定長數(shù)據(jù)并且沒有特定結(jié)束符,我們無法在主函數(shù)中直接判斷什么時(shí)候接收完成。但是有位大佬使用了一個(gè)嘆為觀止的方法實(shí)現(xiàn)了判斷接收不定長數(shù)據(jù)的完成。就是程序中的ESP8266_WaitRecive()函數(shù),調(diào)用函數(shù)時(shí)會(huì)比較上一次接收到的數(shù)據(jù)量和這一次接收到的數(shù)據(jù)量進(jìn)行比較。如果不相同,證明程序進(jìn)入了接收中斷函數(shù)使得接收到的數(shù)據(jù)量發(fā)生了變化,然后將發(fā)生變化后的數(shù)據(jù)量賦值給上一次接收到的數(shù)據(jù)量。如果相同,證明程序沒有再進(jìn)入中斷函數(shù),即已經(jīng)接收完成。我們只需要循環(huán)調(diào)用這個(gè)函數(shù)即可判斷這一幀數(shù)據(jù)是否接收完成。

#define REV_OK		0	//接收完成標(biāo)志
#define REV_WAIT	1	//接收未完成標(biāo)志

unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;		/*esp8266_cnt為當(dāng)前接收到的數(shù)據(jù)數(shù)量,esp8266_cntPre為上一次接收到的數(shù)據(jù)數(shù)量*/

//==========================================================
//	函數(shù)名稱:	ESP8266_WaitRecive
//
//	函數(shù)功能:	判斷是否接收完成
//
//	入口參數(shù):	無
//
//	返回參數(shù):	REV_OK-接收完成		REV_WAIT-接收超時(shí)未完成
//
//	說明:		循環(huán)調(diào)用檢測(cè)是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收計(jì)數(shù)為0 則說明沒有處于接收數(shù)據(jù)中,所以直接跳出,結(jié)束函數(shù)
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和這次相同,則說明接收完畢
	{
//		esp8266_cnt = 0;							//清0接收計(jì)數(shù),注釋掉是為了接收幾幀數(shù)據(jù)
		
		return REV_OK;								//返回接收完成標(biāo)志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置為相同
	
	return REV_WAIT;								//返回接收未完成標(biāo)志

}

ESP8266_SendCmd()函數(shù)就使用到了上面提到的判斷一幀數(shù)據(jù)的方法。這個(gè)函數(shù)是用來發(fā)送AT指令給ESP8266的,并且通過串口1返回ESP8266的響應(yīng)數(shù)據(jù),通過這個(gè)數(shù)據(jù)即可判斷和調(diào)試ESP8266是否正確執(zhí)行指令。

串口1的返回如下:
esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

ESP8266的實(shí)際返回如下:
esp8266-01s wifi時(shí)鐘,stm32,單片機(jī),嵌入式硬件

其實(shí)ESP8266實(shí)際返回的數(shù)據(jù)中有幾個(gè)數(shù)據(jù)返回是幾幀數(shù)據(jù)返回的,如圖中的

[15:51:47.291]收←◆AT+CWJAP=“DSKrurudo”,“12359680” WIFI DISCONNECT

[15:51:47.510]收←◆WIFI CONNECTED

[15:51:48.525]收←◆WIFI GOT IP
OK

這是連接wifi完成后返回的幾幀數(shù)據(jù),而ESP8266_SendCmd()函數(shù)里面通過ESP8266_WaitRecive()判斷一幀數(shù)據(jù)接收完后,繼續(xù)通過判斷響應(yīng)數(shù)據(jù)中的"OK"判斷響應(yīng)數(shù)據(jù)包是否接收完,即接收幾幀的數(shù)據(jù)包,就可以將響應(yīng)數(shù)據(jù)包接收完整,然后通過串口1打印出來。

//==========================================================
//	函數(shù)名稱:	ESP8266_SendCmd
//
//	函數(shù)功能:	發(fā)送命令
//
//	入口參數(shù):	cmd:命令
//				res:需要檢查的返回指令
//
//	返回參數(shù):	0-成功	1-失敗
//
//	說明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到1幀數(shù)據(jù)
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果檢索到關(guān)鍵詞
			{
				UsartPrintf(USART_DEBUG, "%s", esp8266_buf);		//通過調(diào)試串口將接收到的返回指令顯示出來以便判斷
				ESP8266_Clear();									//清空緩存
				
				return 0;		//數(shù)據(jù)包接收完成跳出循環(huán)
			}
		}
		Delay_ms(10);		//通過延時(shí)循環(huán)等待數(shù)據(jù)包接收完成
	}
	
	return 1;
}

3.完整代碼

usart.h

#ifndef _USART_H_
#define _USART_H_


#include "stm32f10x.h"


#define USART_DEBUG		USART1		//調(diào)試打印所使用的串口組


void Usart1_Init(unsigned int baud);

void Usart2_Init(unsigned int baud);

void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len);

void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...);

#endif

usart.c

//硬件驅(qū)動(dòng)
#include "usart.h"
#include "delay.h"

//C庫
#include <stdarg.h>
#include <string.h>
#include <stdio.h>


/*
************************************************************
*	函數(shù)名稱:	Usart1_Init
*
*	函數(shù)功能:	串口1初始化
*
*	入口參數(shù):	baud:設(shè)定的波特率
*
*	返回參數(shù):	無
*
*	說明:		TX-PA9		RX-PA10
************************************************************
*/
void Usart1_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
//	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	//PA9	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_9;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA10	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_10;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//無硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和發(fā)送
	usartInitStruct.USART_Parity = USART_Parity_No;									//無校驗(yàn)
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位數(shù)據(jù)位
	USART_Init(USART1, &usartInitStruct);
	
	USART_Cmd(USART1, ENABLE);														//使能串口
	
//	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);									//使能接收中斷
//	
//	nvicInitStruct.NVIC_IRQChannel = USART1_IRQn;
//	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
//	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
//	nvicInitStruct.NVIC_IRQChannelSubPriority = 2;
//	NVIC_Init(&nvicInitStruct);

}

/*
************************************************************
*	函數(shù)名稱:	Usart2_Init
*
*	函數(shù)功能:	串口2初始化
*
*	入口參數(shù):	baud:設(shè)定的波特率
*
*	返回參數(shù):	無
*
*	說明:		TX-PA2		RX-PA3
************************************************************
*/
void Usart2_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//PA2	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA3	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//無硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和發(fā)送
	usartInitStruct.USART_Parity = USART_Parity_No;									//無校驗(yàn)
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位數(shù)據(jù)位
	USART_Init(USART2, &usartInitStruct);
	
	USART_Cmd(USART2, ENABLE);														//使能串口
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中斷
	
	nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvicInitStruct);

}

/*
************************************************************
*	函數(shù)名稱:	Usart_SendString
*
*	函數(shù)功能:	串口數(shù)據(jù)發(fā)送
*
*	入口參數(shù):	USARTx:串口組
*				str:要發(fā)送的數(shù)據(jù)
*				len:數(shù)據(jù)長度
*
*	返回參數(shù):	無
*
*	說明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//發(fā)送數(shù)據(jù)
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待發(fā)送完成
	}

}

/*
************************************************************
*	函數(shù)名稱:	UsartPrintf
*
*	函數(shù)功能:	格式化打印
*
*	入口參數(shù):	USARTx:串口組
*				fmt:不定長參
*
*	返回參數(shù):	無
*
*	說明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{

	unsigned char UsartPrintfBuf[296];		/*接收輸入變量數(shù)組,如果數(shù)組不夠大,可以修改一下*/
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	{
		USART_SendData(USARTx, *pStr++);
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
	}

}

///*
//************************************************************
//*	函數(shù)名稱:	USART1_IRQHandler
//*
//*	函數(shù)功能:	串口1收發(fā)中斷
//*
//*	入口參數(shù):	無
//*
//*	返回參數(shù):	無
//*
//*	說明:		
//************************************************************
//*/
//void USART1_IRQHandler(void)
//{

//	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷
//	{
//		USART_ClearFlag(USART1, USART_FLAG_RXNE);
//	}

//}

esp8266.h

#ifndef _ESP8266_H_
#define _ESP8266_H_





#define REV_OK		0	//接收完成標(biāo)志
#define REV_WAIT	1	//接收未完成標(biāo)志


void ESP8266_Init(void);

void ESP8266_Clear(void);

void ESP8266_SendData(unsigned char *data, unsigned short len);

unsigned char *ESP8266_GetIPD(unsigned short timeOut);
_Bool ESP8266_SendCmd(char *cmd, char *res);
_Bool ESP8266_WaitRecive(void);


#endif

esp8266.c

//單片機(jī)頭文件
#include "stm32f10x.h"

//網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)
#include "esp8266.h"

//硬件驅(qū)動(dòng)
#include "Delay.h"
#include "usart.h"

//C庫
#include <string.h>
#include <stdio.h>



#define ESP8266_WIFI_INFO		"AT+CWJAP=\"DSKrurudo\",\"12359680\"\r\n"			/*連接wifi的AT指令*/

//#define ESP8266_ONENET_INFO		"AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n"

#define ESP8266_TIANQI_INFO		"AT+CIPSTART=\"TCP\",\"59.82.34.102\",80\r\n"		/*連接高德地圖TCP的AT指令*/

unsigned char esp8266_buf[360];			/*接收ESP-01s的返回?cái)?shù)據(jù)數(shù)組*/
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;		/*esp8266_cnt為當(dāng)前接收到的數(shù)據(jù)數(shù)量,esp8266_cntPre為上一次接收到的數(shù)據(jù)數(shù)量*/

//unsigned char send_data[]="GET\r\n";

//==========================================================
//	函數(shù)名稱:	ESP8266_Clear
//
//	函數(shù)功能:	清空緩存
//
//	入口參數(shù):	無
//
//	返回參數(shù):	無
//
//	說明:		
//==========================================================
void ESP8266_Clear(void)
{

	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;

}

//==========================================================
//	函數(shù)名稱:	ESP8266_WaitRecive
//
//	函數(shù)功能:	判斷是否接收完成
//
//	入口參數(shù):	無
//
//	返回參數(shù):	REV_OK-接收完成		REV_WAIT-接收超時(shí)未完成
//
//	說明:		循環(huán)調(diào)用檢測(cè)是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收計(jì)數(shù)為0 則說明沒有處于接收數(shù)據(jù)中,所以直接跳出,結(jié)束函數(shù)
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和這次相同,則說明接收完畢
	{
//		esp8266_cnt = 0;							//清0接收計(jì)數(shù),注釋掉是為了接收幾幀數(shù)據(jù)
		
		return REV_OK;								//返回接收完成標(biāo)志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置為相同
	
	return REV_WAIT;								//返回接收未完成標(biāo)志

}

//==========================================================
//	函數(shù)名稱:	ESP8266_SendCmd
//
//	函數(shù)功能:	發(fā)送命令
//
//	入口參數(shù):	cmd:命令
//				res:需要檢查的返回指令
//
//	返回參數(shù):	0-成功	1-失敗
//
//	說明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到數(shù)據(jù)
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果檢索到關(guān)鍵詞
			{
				UsartPrintf(USART_DEBUG, "%s", esp8266_buf);		//通過調(diào)試串口將接收到的返回指令顯示出來以便判斷
				ESP8266_Clear();									//清空緩存
				
				return 0;
			}
			
		}
		
		Delay_ms(10);
		
	}
	
	return 1;

}

//==========================================================
//	函數(shù)名稱:	ESP8266_SendData
//
//	函數(shù)功能:	發(fā)送數(shù)據(jù)
//
//	入口參數(shù):	data:數(shù)據(jù)
//				len:長度
//
//	返回參數(shù):	無
//
//	說明:		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{

	char cmdBuf[32];
	
	ESP8266_Clear();								//清空接收緩存
	sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//發(fā)送命令
	if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’時(shí)可以發(fā)送數(shù)據(jù)
	{
		UsartPrintf(USART_DEBUG, "you are real");
		Usart_SendString(USART2, data, len);		//發(fā)送設(shè)備連接請(qǐng)求數(shù)據(jù)
	}

}

//==========================================================
//	函數(shù)名稱:	ESP8266_GetIPD
//
//	函數(shù)功能:	獲取平臺(tái)返回的數(shù)據(jù)
//
//	入口參數(shù):	等待的時(shí)間(乘以10ms)
//
//	返回參數(shù):	平臺(tái)返回的原始數(shù)據(jù)
//
//	說明:		不同網(wǎng)絡(luò)設(shè)備返回的格式不同,需要去調(diào)試
//				如ESP8266的返回格式為	"+IPD,x:yyy"	x代表數(shù)據(jù)長度,yyy是數(shù)據(jù)內(nèi)容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{

	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		{
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”頭
			if(ptrIPD == NULL)											//如果沒找到,可能是IPD頭的延遲,還是需要等待一會(huì),但不會(huì)超過設(shè)定的時(shí)間
			{
				UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");
			}
			else
			{
				ptrIPD = strchr(ptrIPD, ':');							//找到':'
				if(ptrIPD != NULL)
				{
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				}
				else
					return NULL;
				
			}
		}
		
		Delay_ms(5);													//延時(shí)等待
	} while(timeOut--);
	
	return NULL;														//超時(shí)還未找到,返回空指針

}

//==========================================================
//	函數(shù)名稱:	ESP8266_Init
//
//	函數(shù)功能:	初始化ESP8266
//
//	入口參數(shù):	無
//
//	返回參數(shù):	無
//
//	說明:		
//==========================================================
void ESP8266_Init(void)
{
	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

	//ESP8266復(fù)位引腳
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_14;					//GPIOC14-復(fù)位
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);		//拉低GPIOC14使能RST引腳
	Delay_ms(500);
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);			//拉高GPIOC14回到默認(rèn)狀態(tài)
	Delay_ms(500);
	
	ESP8266_Clear();		//清空上一次的接收緩存
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "0. AT\r\n");
	ESP8266_SendCmd(" AT\r\n", "OK");		//測(cè)試AT
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "1. RST0\r\n");
//	ESP8266_SendCmd("AT+RST\r\n", "OK");
//	UsartPrintf(USART_DEBUG, "1. RST1\r\n");
//		Delay_ms(500);
//	ESP8266_SendCmd("AT+CIPCLOSE\r\n", "OK");
//	UsartPrintf(USART_DEBUG, "1. RST2\r\n");
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "1. CWMODE\r\n");
	ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK");		//設(shè)置ESP8266作為客戶端
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");
//	ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK");
//		Delay_ms(500);
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "2. CWJAP\r\n");
	ESP8266_SendCmd(ESP8266_WIFI_INFO, "OK");		//連接wifi
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "5. CIPSTART\r\n");
//	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "3. CIPSTART\r\n");
	ESP8266_SendCmd(ESP8266_TIANQI_INFO, "OK");		//連接到服務(wù)器
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "4. AT+CIPMODE=1\r\n");
	ESP8266_SendCmd("AT+CIPMODE=1\r\n", "OK");		//設(shè)置透?jìng)髂J?/span>
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "5. AT+CIPSEND\r\n");
	ESP8266_SendCmd("AT+CIPSEND\r\n", ">");		//開啟數(shù)據(jù)傳輸模式
	Delay_ms(500);

//	UsartPrintf(USART_DEBUG, "6.AT+CIPSEND=5\r\n");
//	ESP8266_SendCmd("AT+CIPSEND=6\r\n", ">");
//		Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "8. GET\r\n");
//	ESP8266_SendData(send_data, 6);

	
//	if(ESP8266_GetIPD(0) != NULL)
//	{
//		UsartPrintf(USART_DEBUG, "noNULL\r\n");
//	}

}

//==========================================================
//	函數(shù)名稱:	USART2_IRQHandler

//	函數(shù)功能:	串口2收發(fā)中斷

//	入口參數(shù):	無

//	返回參數(shù):	無

//	說明:		
//==========================================================
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //串口2接收中斷
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆,如果接收超過了接收數(shù)組的容量,從第一位開始覆蓋接收數(shù)組
		esp8266_buf[esp8266_cnt++] = USART_ReceiveData(USART2);		//將接收到的數(shù)據(jù)放到接收數(shù)組里
		USART_ClearFlag(USART2, USART_FLAG_RXNE);			//清除中斷標(biāo)志位
	}

}

總結(jié)

這次介紹了一下ESP8266的使用方法和注意事項(xiàng),還有我對(duì)串口中斷的了解。因?yàn)樘L了,所以獲取和處理天氣、時(shí)間信息就放在下一文章中。文章來源地址http://www.zghlxwxcb.cn/news/detail-780578.html

到了這里,關(guān)于從零開始制作一個(gè)基于STM32和ESP8266-01S的智能時(shí)鐘(3)ESP8266-01S模塊(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包