菜鸟江涛带你学最小物联网系统之模块篇(02)——STM32通过串口发送AT指令控制ESP模块连接服务器

本文主要是介绍菜鸟江涛带你学最小物联网系统之模块篇(02)——STM32通过串口发送AT指令控制ESP模块连接服务器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(1)菜鸟江涛带你学最小物联网系统之模块篇(01)—— WIFI模块ESP12F初次亲密接触
 


接着上一篇继续,这篇博客我将带大家使用STM32的串口来发送AT指令给ESP模块连接服务器。当然目前测试使用的是局域网,自己的电脑当服务器使用。使用TCP连接服务器,STM32通过ESP12F模块透传上传温湿度数据到服务器。看下效果图片

好了,看下主要的实现代码:

#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "bmp.h"
#include "dth11.h"
#include "usart.h"
#include "esp_at_cmd.h"
#include "string.h"unsigned char buffer[5];
unsigned int hum , temp ;
unsigned char t1[5];
unsigned char t2[5];char tx1[] = "TEMP:";
char tx2[] = "HUM:";/************* [ESP8266_SendCmd 发送命令到ESP8266]* @param  cmd   [需要发送的AT指令]* @param  reply [期望模块回显的内容]* @param  wait  [等待的时间(ms)]* @return       [期望内容等于实际回显内容返回1,否则0]*************/
int ESP8266_SendCmd(u8* cmd, char* reply, int wait) 
{USART1_Send_String(cmd);		// 发送指令,等待回显接收DelayMs(wait);							// 等待接收回显内容if(strcmp(reply , "") == 0) return 0 ; // 不进入回显判断if((USART_RX_STA&0x8000) == 1) 					// 接收完成{USART_RX_STA = 0 ;							// 重置标志位if(strstr((char*)USART_RX_BUF , reply))			// 如果返回的字符串中包含有期望的返回值{return 1 ;}}return 0 ;
}/*************** 初始化*************/
int Esp_mode() 
{int res = 0 ;res = ESP8266_SendCmd(AT_INIT , "OK" , 500);	// 初始化return res ;}/*************** 连接WIFI*************/
int Esp_joinAp() 
{int res = 0 ;res = ESP8266_SendCmd(AT_WIFI , "WIFI CONNECTED" , 5000);	// 连接WIFIreturn res ;}/*************** 连接TCP*************/
int Esp_connectTcp() 
{int res = 0 ;res = ESP8266_SendCmd(AT_TCP , "CONNECT" , 5000);	// 连接TCPreturn res ;}/*************** 设置透传模式*************/
int Esp_sendMode() 
{int res = 0 ;res = ESP8266_SendCmd(AT_MODE , "OK" , 500);	// 设置模块的透传模式return res ;}/*************** 启动发送*************/
int Esp_sendStart() 
{int res = 0 ;res = ESP8266_SendCmd(AT_START , "OK" , 500);	// 启动发送return res ;}/*************** 退出*************/
void Esp_exit() 
{ESP8266_SendCmd(AT_EXIT , "" , 500);	// 关闭
}int ESP_Init()
{if(Esp_mode())									// 初始化成功{if(Esp_joinAp())							// 连接WIFI成功{if(Esp_connectTcp())				// 连接TCP服务器{if(Esp_sendMode())				// 设置透传模式{if(Esp_sendStart())			// 启动发送{return 1 ;						// 所有初始化成功之后返回1}}}}	}return 0;	
}int main(void)
{u8 count = 0 ;DelayInit();OLED_Init();			//初始化OLED  OLED_Clear()  	; uart_init(115200);    // 一定要注意使用115200波特率DelayMs(100);ESP_Init();			// 初始化ESPwhile(1){GPIO_WriteBit(GPIOD,GPIO_Pin_2,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_2)));    //IO的电平翻转if (dht11_read_data(buffer) == 0){hum = buffer[0]*10 + buffer[1];temp = buffer[2]*10 + buffer[3];t1[0] = hum/100 + '0';t1[1] = hum%100/10 + '0';t1[2] = 0x2e;t1[3] = hum%10 + '0';t2[0] = temp/100 + '0';t2[1] = temp%100/10 + '0';t2[2] = 0x2e;t2[3] = temp%10 + '0';OLED_ShowString(0,2,(u8*)"hum: ");OLED_ShowString(8*6,2,t1);OLED_ShowString(0,4,(u8*)"temp: ");OLED_ShowString(8*6,4,t2);}DelayS(2);count ++ ;if(count == 5)		// 计时10秒钟发送一次数据{count = 0 ;USART1_Send_String((u8*)tx1);USART1_Send_String(t1);USART1_Send_String((u8*)" -- ");USART1_Send_String((u8*)tx2);USART1_Send_String(t2);}}}

再贴下串口的 .c文件和 .h文件

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "stm32f10x.h"#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	void uart_init(u32 bound);				// 初始化串口
void USART1_Send_Byte(u8 Data);		// 发送一个字节	
void USART1_Send_String(u8 *Data);			// 发送字符串#endif
#include "usart.h"	  //
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ int handle; }; FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
}
#endif /*使用microLib的方法*//* 
int fputc(int ch, FILE *f)
{USART_SendData(USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	return ch;
}
int GetKey (void)  { while (!(USART1->SR & USART_FLAG_RXNE));return ((int)(USART1->DR & 0x1FF));
}
*/#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);	//使能USART1,GPIOA时钟以及复用功能时钟//USART1_TX   PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//USART1_RX	  PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);  //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;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); //初始化串口USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断USART_Cmd(USART1, ENABLE);                    //使能串口 }void USART1_Send_Byte(u8 Data) 								//发送一个字节;
{USART_SendData(USART1,Data);while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );
}void USART1_Send_String(u8 *Data) 						//发送字符串;
{while(*Data)USART1_Send_Byte(*Data++);
}void USART1_IRQHandler(void)                	//串口1中断服务程序
{u8 Res;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始else USART_RX_STA|=0x8000;	//接收完成了 }else //还没收到0X0D{	if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  }		 }}   		 } } 
#endif	

我使用的是dth11温湿度传感器来测量温湿度的,使用OLED来显示,这部分不是最重要的,所以就不贴出来占篇幅了,大家有需要的可以留言,看到我会发你的。


参考文章:STM32--ESP8266--AT指令使用例程


新补充内容:命令的头文件

#ifndef __ESP_AT_CMD_H
#define __ESP_AT_CMD_H#include "stm32f10x.h"u8 * AT_INIT = "AT+CWMODE=1\r\n" ;
u8 * AT_WIFI = "AT+CWJAP_DEF=\"xxxxx\",\"******\"\r\n" ;
u8 * AT_TCP  = "AT+CIPSTART=\"TCP\",\"192.168.3.5\",7996\r\n" ;
u8 * AT_MODE = "AT+CIPMODE=1\r\n" ;
u8 * AT_START = "AT+CIPSEND\r\n";
u8 * AT_EXIT = "+++" ;u8 * AT_OK = "OK\r\n" ;#endif

上面的头文件中AT+CWJAP_DEF为连接wifi的指令,xxxx表示WiFi名称,******代表的是WiFi的密码。注意双引号要加转义符。

这篇关于菜鸟江涛带你学最小物联网系统之模块篇(02)——STM32通过串口发送AT指令控制ESP模块连接服务器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/999255

相关文章

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Python手搓邮件发送客户端

《Python手搓邮件发送客户端》这篇文章主要为大家详细介绍了如何使用Python手搓邮件发送客户端,支持发送邮件,附件,定时发送以及个性化邮件正文,感兴趣的可以了解下... 目录1. 简介2.主要功能2.1.邮件发送功能2.2.个性签名功能2.3.定时发送功能2. 4.附件管理2.5.配置加载功能2.6.

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作