STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)

使用stm32通过串口连接esp8266,再使用AT指令来连接mqtt,话不多说,直接上干货

固件烧录

使用安信可的esp8266AT固件

下载地址

docs.ai-thinker.com

使用说明

https://docs.espressif.com/projects/esp-at/zh_CN/latest/esp32/AT_Command_Set/index.htmlicon-default.png?t=N7T8https://docs.espressif.com/projects/esp-at/zh_CN/latest/esp32/AT_Command_Set/index.html

STM32配置

为esp8266配置串口,并初始化波特率为115200;并开启中断

hal库直接cubeMX生成代码;

标准库初始化如下;

void Usart3_Init(u32 baud)   //串口初始化
 {  
GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, 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;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	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);


 }

void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)//串口发送数据
{
 
	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待发送完成
	}



//记得加上main里中断分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

esp8266初始化

HAL库

该代码使用tcp透传的方式连接mqtt

#define WIFI_SSID        "wif名"
#define WIFI_PASSWD      "WiFi密码"

#define MQTT_CONNECT_ID     "emqx_MzgzMT"


#define MQTT_CONNECT_IP     "MQTT服务器IP"         

#define MQTT_USER          "MQTT用户账号"                
#define MQTT_PASSWD        "MQTT用户密码"                 

unsigned char receive_buf[512];	  //串口2接收缓存数组
unsigned char receive_start = 0;	//串口2接收开始标志位
uint16_t receive_count = 0;	      //串口2接收数据计数器
uint16_t receive_finish = 0;	    //串口2接收结束标志位 

typedef struct {
    int connection_id;
    int data_length;
    char data_content[512]; // Adjust the size as needed
} ParsedData;


 void USART4_SendByte(uint8_t ch)
{	
	HAL_UART_Transmit(&huart4,&ch,1,100);	
	
}

uint8_t esp8266_ClientServer(void)
{
	__HAL_UART_ENABLE_IT(&huart4,UART_IT_RXNE);  //打开串口2接收中断

uint16_t sendbuff[256];
	
	printf("1.SETTING STATION MODE\r\n");

	while(esp8266_send_cmd((uint8_t *)"AT+CWMODE=1\r\n",strlen("AT+CWMODE=1\r\n"),"OK")!=0)
	{
		HAL_Delay(1000);
	}
	printf("2.CLOSE ESP8266 ECHO\r\n");

	while(esp8266_send_cmd((uint8_t *)"ATE0\r\n",strlen("ATE0\r\n"),"OK")!=0)
	{
		HAL_Delay(1000);
	}
	printf("3.NO AUTO CONNECT WIFI\r\n"); 

	while(esp8266_send_cmd((uint8_t *)"AT+CWAUTOCONN=0\r\n",strlen("AT+CWAUTOCONN=0\r\n"),"OK")!=0)
	{
		HAL_Delay(1000);
	}
	printf("4.RESET ESP8266\r\n");

	while(esp8266_reset() != 0)
	{
		HAL_Delay(1000);
	}
	printf("5.CONFIG WIFI NETWORK\r\n");

	while(esp8266_config_network() != 0)
	{
		HAL_Delay(2000);
	}
   printf("6.TCP CONNECT  MUX \r\n");
	
	 while(esp8266_send_cmd((uint8_t *)"AT+CIPMUX=0\r\n",strlen("AT+CIPMUX=0\r\n"),"OK")!=0)
{
	  HAL_Delay(2000);
}

    
  printf("Esp8266 CONNECT IP: \r\n");
	
	 while(esp8266_send_cmd((uint8_t *)"AT+CIFSR\r\n",strlen("AT+CIFSR\r\n"),"")!=0)
{
	  HAL_Delay(2000);
}


    sprintf((char*)sendbuff,"AT+CIPSTART=\"TCP\",\"%s\",1883\r\n",MQTT_CONNECT_IP);
      printf("连接TCP:%s",(char*)sendbuff);
   printf("7.TCP CONNECT IP\r\n");
	 while(esp8266_send_cmd((uint8_t *)sendbuff,strlen((const  char*)sendbuff),"OK")!=0)
{
	  HAL_Delay(2000);
}
	printf("8.TCP CONNECT MODE \r\n");
	
	 while(esp8266_send_cmd((uint8_t *)"AT+CIPMODE=1\r\n",strlen("AT+CIPMODE=1\r\n"),"OK")!=0)
{
	  HAL_Delay(2000);
} 

while(esp8266_send_cmd((uint8_t *)"AT+CIPSEND\r\n",strlen("AT+CIPSEND\r\n"),"OK")!=0)
{
	  HAL_Delay(2000);
}
	printf("9.ESP8266  CONNECT Server OK!!!\r\n");


 esp_connect_ok = ESP_STA_CONNECTED;



return 0;

}


uint8_t esp8266_send_cmd(unsigned char *cmd,unsigned char len,char *rec_data)	
{
  unsigned char retval =0;
  unsigned int count = 0;

  HAL_UART_Transmit(&huart4, cmd, len, 1000);	                                   
  while((receive_start == 0)&&(count<1000))
  {
    count++;
    HAL_Delay(1);
  }

  if(count >= 1000)	
  {
    retval = 1;	
  }
  else	
  {
    do
    {
      receive_finish++;
      HAL_Delay(1);
    }
    while(receive_finish < 500);
    retval = 2;
    if(strstr((const char*)receive_buf, rec_data))	
    {
            printf("%s",receive_buf);
        
            retval = 0;	
    }
  }
  uart4_receiver_clear(receive_count);
  return retval;
}

void uart4_receiver_clear(uint16_t len)	
{
	memset(receive_buf,0x00,len);
	receive_count = 0;
	receive_start = 0;
	receive_finish = 0;
}

void USART4_Send_Poll(uint8_t *buff, uint16_t Size) 
{
	uint16_t i;
		printf("USART4_SendByte\r\n");
	for(i = 0; i < Size; i++)
	{
		USART4_SendByte(*buff++);
	}
}
void ESP_Send(uint8_t *buff, uint16_t len)
{
	USART4_Send_Poll(buff,len);
	printf("ESP_Send\r\n");
}

标准库

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志
#define INIT_FINSH  1    //连接置0,连接完成置1



#define MQTT_TOPIC_SEND     "attributes"
#define MQTT_TOPIC_RECV     "attributes/push"
#define MQTT_CLIENT_ID 		  "1234kkk"
 
 
//需要更改
#define ESP8266_WIFI_INFO		"AT+CWJAP=\"WiFi名\",\"WiFi密码\"\r\n"
#define ESP8266_ONENET_INFO		"AT+MQTTCONN=0,\"mqttip地址\",1883,1\r\n"  //MQTT接入地址
#define MQTT_USERNAME  			"mqtt账号"  //账号      
#define MQTT_PASSWORD  			"mqtt密码"        //密码



unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;

u8 init_finish = 1;

void ESP8266_Clear(void)
{
 
	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;
 
}



void ESP8266_Init(void)
{
	char str123[100]={0};

	init_finish = 0;
	delay_ms(1000);
	

	
	ESP8266_Clear();
	
	printf("\r\n0. 检查WiFi模块\r\n");
	while(ESP8266_SendCmd("AT\r\n", "OK"))
		delay_ms(500);
	
	printf("\r\n1. 重置wifi模块\r\n");
	ESP8266_SendCmd("AT+RST\r\n","");
	delay_ms(500);
 
	printf("\r\n2. 设置模块为STA模式\r\n");
	while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
		delay_ms(500);
	
	printf("\r\n3. 连接wifi\r\n");
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
		delay_ms(500);
	
	printf("\r\n4. 设置时区为:中国早上八点\r\n");
	while(ESP8266_SendCmd("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n", ""))
		delay_ms(500);
	
	printf("\r\n5. 设置MQTT用户名和密码\r\n");
	sprintf(str123, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD);
	while(ESP8266_SendCmd(str123, "OK"))
		delay_ms(500);
	
	printf("\r\n6. 设置MQTT接入地址\r\n");
	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "OK"))
		delay_ms(500);
	
	printf("\r\n7. 订阅平台消息\r\n");
	memset(str123,0,100);
	sprintf(str123, "AT+MQTTSUB=0,\"%s\",1\r\n",MQTT_TOPIC_RECV);
	while(ESP8266_SendCmd(str123, "OK"))
		delay_ms(500);
	
	printf("\r\n8. ESP8266初始化完成\r\n");
	
	init_finish = 1;
 
}
 
//判断是否接收完成
_Bool ESP8266_WaitRecive(void)
{
 
	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	{
		esp8266_cnt = 0;							//清0接收计数
			
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志
 
}
 
//发送命令
_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)							//如果收到数据
		{
			
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				printf("%s\r\n",esp8266_buf); 
				ESP8266_Clear();									//清空缓存
				return 0;
			}
		}
		
		delay_ms(30);
	}
	
	return 1;
 
}
 
//上传消息
void ESP8266_SendData_Float(char *property,float val)
{
	char *buf = malloc(100 * sizeof(char));
	memset(buf,0,100);
	sprintf(buf,"AT+MQTTPUB=0,\"%s\",\"{\\\"%s\\\":%.1f}\",0,0\r\n",MQTT_TOPIC_SEND,property,val);
		
	Usart_SendString(USART2, (u8 *)buf,strlen(buf));
	delay_ms(500);
	free(buf);
}



void ESP8266_SendData_Int(char *property,int val)
{
	char *buf = malloc(100 * sizeof(char));
	memset(buf,0,100);
	sprintf(buf,"AT+MQTTPUB=0,\"%s\",\"{\\\"%s\\\":%d}\",0,0\r\n",MQTT_TOPIC_SEND,property,val);
		
	Usart_SendString(USART2, (u8 *)buf,strlen(buf));
	delay_ms(500);
	free(buf);
}

void ESP8266_SendData_Bool(char *property,char* val)
{
	char *buf = malloc(100 * sizeof(char));
	memset(buf,0,100);
	sprintf(buf,"AT+MQTTPUB=0,\"%s\",\"{\\\"%s\\\":%s}\",0,0\r\n",MQTT_TOPIC_SEND,property,val);
		
	Usart_SendString(USART2, (u8 *)buf,strlen(buf));
	delay_ms(500);
	free(buf);
}
 




void Usart2_Init(u32 baud)   
 {  
     

GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, 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;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	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);


 }
 
 
 
 void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{
 
	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待发送完成
	}
 
}




void USART2_IRQHandler(void)
{
	if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) 
	{
		u8 t = USART2 -> DR;
		esp8266_buf[esp8266_cnt++] =t;
		
		if(init_finish)
		{
			if(t == '\n' && esp8266_buf[esp8266_cnt-2] == '\r')
			{
				esp8266_buf[esp8266_cnt] = '\0';
				printf("%s",esp8266_buf);
				esp8266_cnt = 0;
				
			}
			
		}
	}
 
}




ThingCluod

ThingCluod简介

ThingsCloud 在设备和用户之间建立开箱即用的云平台和云应用,实现数据采集、实时控制、数据可视化、零代码应用开发、开放 API,构建灵活强大的物联网应用。

ThingCluod配置

注册账号,创建设备,看说明操作

将这些加在代码中

订阅主题

以下主题用于 设备向云平台发布消息

消息类型主题
设备上报属性值attributes
设备获取当前属性值attributes/get/<id>
设备上报事件event/report/<id>
设备回复命令command/reply/<id>
设备自定义数据上报data/<identifier>

以下主题用于 设备接收云平台下发的消息

消息类型主题
接收属性上报的响应attributes/response
接收属性获取的响应attributes/get/response/+
接收下发的属性attributes/push
接收事件上报的响应event/response/+
接收下发的命令command/send/+
接收命令回复的响应command/reply/response/+
接收自定义数据下发data/<identifier>/set

一般使用attributes作为设备上报,使用attributes/push,来接受云平台下发

注意传输格式的json,需要注意格式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值