STM32F103C8T6+ESP8266+OneNet(仅连接,不涉及数据传输)

本文详细描述了如何在STM32单片机上配置USART与ESP8266通信,包括连接步骤、串口初始化、AT指令发送以及遇到的问题和解决方案。重点介绍了串口配置和处理AT+RST指令的注意事项。
摘要由CSDN通过智能技术生成

一、准备工作

准备工作见下文第三节:ESP8266+OneNet使用物模型实现数据的收发(仅为连接单片机前的调试工作,本章不涉及单片机)-CSDN博客

二、单片机引脚连接  

        在使用单片机发送相关AT指令时需要用到单片机的串口功能,下面使用库函数对串口进行配置。小编对USART1和USART3进行了配置,使用串口1连接ESP8266,使用串口3连接USB-TTL(便于将串口1接收到的缓冲通过串口3发送至串口助手观察)。单片机、ESP8266、ST-LINK、USB-TTL引脚连接如下(下图均为引脚名称):

        2.1单片机与ST-LINK连接

STM32F103ST-LINK
SWCLKSWCLK
SWDIO(或SWIO)SWDIO
GNDGND
3V3(或3.3)3V3

        2.2单片机与ESP8266

STM32F103ESP8266
PA9RX
PA10TX
GNDG
3V3(或3.3)3V

        2.3单片机与USB-TTL

STM32F103USB-TTL
PB10RXD

        由于小编仅使用串口3的TXD,因此不将串口3的RXD与下载器的TXD相连,在下面进行串口配置时小编也不会对串口3的RXD功能进行配置。

三、串口配置

        小编使用库函数进行串口的配置,具体见下述代码:

//Serial.c
#include "stm32f10x.h"              

uint8_t Serial_RxBuff[300];  //定义接收数据的存放区域
uint16_t RxCount;			  //定义接收到数据的个数

/**
  * @brief  串口1配置
  * @param  无
  * @retval 无
  */
void Serial_Init(void)
{
	GPIO_InitTypeDef 	GPIO_InitStructure;
	USART_InitTypeDef	USART_InitStructure;
	NVIC_InitTypeDef	NVIC_InitStructure;				  //定义结构体变量
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //打开USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //打开GPIOA的时钟
	
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);               //初始化PA9引脚为服用推完输出,即TXD
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);				 //初始化PA10引脚为上拉输入,即RXD
	
	USART_InitStructure.USART_BaudRate = 115200;		 //波特率,可调
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送和接收模式
	USART_InitStructure.USART_Parity = USART_Parity_No;				//无校验
	USART_InitStructure.USART_StopBits = USART_StopBits_1;			//1位停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//字长8位
	USART_Init(USART1,&USART_InitStructure);						//将结构体参数赋值,配置串口1
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);        //开启串口1接收数据的中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		//配置NVIC分组2,2位抢占优先级,2位响应优先级
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	//选择配置NVIC的串口线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //配置抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	//配置响应优先级为1
	NVIC_Init(&NVIC_InitStructure);						//将结构体参数赋值,配置中断
	
	USART_Cmd(USART1,ENABLE);							//使能串口1,串口开始运行
}

/**
  * @brief  串口3配置
  * @param  无
  * @retval 无
  */
void Serial3_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef	USART_InitStructure;				//定义结构体变量
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);	//打开USART3的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	//打开GPIOB的时钟
	
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);					//初始化PB10引脚为服用推完输出,即TXD
	
	
	USART_InitStructure.USART_BaudRate = 115200;			//波特率,可调
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Tx;			//发送模式
	USART_InitStructure.USART_Parity = USART_Parity_No;		//无校验
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//1位停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//字长8位
	USART_Init(USART3,&USART_InitStructure);				//将结构体参数赋值,配置串口3

	
	USART_Cmd(USART3,ENABLE);								//使能串口3,串口开始运行
}

/**
  * @brief  串口1发送一个字节
  * @param  Byte,串口发送的一个字节
  * @retval 无
  */
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1,Byte);	//将字节写入数据寄存器,写入后自动发送
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);	//等待发送完成,发送完成自动清除标志位
}

/**
  * @brief  串口1发送一个字符串
  * @param  String,发送字符串的首地址
  * @retval 
  */
void Serial_SendString(char *String)
{
	uint8_t i;
	for(i = 0;String[i] != '\0';i++)	//遍历字符数组,遇到结束标志停止
	{
		Serial_SendByte(String[i]);		//调用发送一个字节发送数据
	}
}

/**
  * @brief  串口3发送一个字节
  * @param  Byte,串口发送的一个字节
  * @retval 无
  */
void Serial3_SendByte(uint8_t Byte)
{
	USART_SendData(USART3,Byte);		//将字节写入数据寄存器,写入后自动发送
	while(USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);	//等待发送完成,发送完成自动清除标志位
}

/**
  * @brief  串口1发送一个字符串
  * @param  String,发送字符串的首地址
  * @retval 
  */
void Serial3_SendString(char *String)
{
	uint8_t i;
	for(i = 0;String[i] != '\0';i++)	//遍历字符数组,遇到结束标志停止
	{
		Serial3_SendByte(String[i]);	//调用发送一个字节发送数据
	}
}
/**
  * @brief  清除数据缓冲区
  * @param  无
  * @retval 无
  */
void Clear_Buffer(void)
{
	uint16_t i;
	for(i=0;i<RxCount;i++)           	//将0写入缓冲区,直到大于缓冲区接收到的字符数量
	{
		Serial_RxBuff[i]=0;//缓存
	}
	RxCount=0;							//重新计数,等待下一次接收
}

/**
  * @brief  串口1中断函数
  * @param  无
  * @retval 无
  */
void USART1_IRQHandler(void)
{
	uint8_t data;							//定义临时变量存放串口接收的一个字节
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //判断是否是串口1的接收事件触发中断
	{
			
			data = USART_ReceiveData(USART1);			   //读取数据寄存器,存放在临时变量
			if(data != '\r' || data != '\n' )			   //判断接收数据不是结束标志
			{
				Serial_RxBuff[RxCount++] = data;		   //不是结束标志,将数据存放在缓存区
			}
			if(data == '\n')							   //判断接收数据是结束标志
			{
				Serial_RxBuff[RxCount] = '\0';			   //是结束标志,给缓存区的最后一位添加结束标志
			}
		
	USART_ClearITPendingBit(USART1,USART_IT_RXNE);	//清除标志位
	}
}



//Serial.h
#ifndef __SERIAL__H_
#define __SERIAL__H_

extern char Serial_RxBuff[];

void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendString(char *String);
void Clear_Buffer(void);
void Serial3_Init(void);
void Serial3_SendByte(uint8_t Byte);
void Serial3_SendString(char *String);

#endif
//main.c
#include "stm32f10x.h"                  // Device header
#include "serial.h"
#include "delay.h"

char CWJAP[] = "AT+CWJAP=\"@PHICOMM_60\",\"lzj123456lzj\"\r\n";
char MQTTUSERCFG[] = "AT+MQTTUSERCFG=0,1,\"esp8266\",\"OWA8D1n1ES\",\"version=2018-10-31&res=products%2FOWA8D1n1ES%2Fdevices%2Fesp8266&et=1745287964&method=md5&sign=VBufe7exEABGp0ub0ezEUQ%3D%3D\",0,0,\"\"\r\n";
char MQTTCONN[] = "AT+MQTTCONN=0,\"mqtts.heclouds.com\",1883,0\r\n";
	
int main()
{
	Serial_Init();
    Serial3_Init();

	Serial_SendString("AT+RST\r\n");
	Delay_ms(500);
	Serial3_SendString(Serial_RxBuff);
	Clear_Buffer();
	Serial_SendString("AT+CWMODE=1\r\n");
	Delay_ms(500);
	Serial3_SendString(Serial_RxBuff);
	Clear_Buffer();
	Serial_SendString(CWJAP);
	Delay_ms(3000);
	Serial3_SendString(Serial_RxBuff);
	Clear_Buffer();
	Serial_SendString(MQTTUSERCFG);
	Delay_ms(500);
	Serial3_SendString(Serial_RxBuff);
	Clear_Buffer();
	Serial_SendString(MQTTCONN);
	Delay_ms(500);
	Serial3_SendString(Serial_RxBuff);
	Clear_Buffer();
	while(1)
	{
		
	
	}
}

        在main.c中这里发送的参数就不进行介绍,可以参考本文第一节的准备工作。在这里需要特别注意在发送AT+RST时,正确情况下我们应该接收到ready才判断其复位成功,但在实际操作中小编发现无法完整的将串口1接收到的缓冲通过串口3发送出来。小编猜测在ESP8266的回传数据中有的存在因此无法将其保存在缓冲区(有知道的小伙伴可以分享一下),但所幸并影响后续的操作。其次,还要注意Serial_SendString(CWJAP);需要的时间间隔较长,小编尝试了500ms、1000ms、2000ms在执行后续过程时会返回busy从而导致后续执行出错,知道小编尝试3000ms才成功,因此大家在操作中需要密切注意这一步。

        失败:

         成功:

        同时设备上线 

         同时再补充一点,如果通过esp8266连接上云平台后,如果再次发送AT+MQTTUSERCFG和AT+MQTTCONN的指令时是会返回ERROE的,必须复位后执行才能正常连接。

代码如下:

【免费】STM32+ESP8266+OneNet(仅连接,不涉及数据的上下行)资源-CSDN文库

补充:将Serial.c的

uint8_t Serial_RxBuff[300];  //定义接收数据的存放区域
uint16_t RxCount;			  //定义接收到数据的个数

改为

uint8_t Serial_RxBuff[250];  //定义接收数据的存放区域
uint8_t RxCount;			  //定义接收到数据的个数

可以接收到正常发送AT+RST的回传内容,但会接收到多次

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值