STM32F103C8T6+ESP-01S+MQTT server realizes data upload and reception (1)


Article Directory

STM32F103C8T6+ESP-01S+MQTT server realizes data upload and reception (2)

foreword

ESP-01S firmware burning

ESP-01S recommends using Anxinke official website firmware 1471, and the burning configuration is as shown in the figure below.Alt

Main AT commands

Please replace the content inside <>

AT+CWMODE=1						
#设置模组进入STA模式

AT+CWJAP="<ssid>","<password>"			
#连接wifi

AT+MQTTUSERCFG=0,1,"<Client ID>","<账号>","<密码>",0,0,""
#设置MQTT连接所需要的的参数,包括用户ID(不为空)、账号(admin)以及密码(public)

AT+MQTTCONN=0,"<服务器地址>",<端口号>,<是否重连标志>
#连接mqtt服务器,设置服务器地址,端口号和是否重连标志(0或1)

AT+MQTTPUB=0,"<topic名>","<topic内容>",<QOS>,<retain>						
#发布一条topic

AT+MQTTSUB=0,"<topic名>",<QOS>	
#订阅一条topic

Handwritten simple library functions

constant definition

enum ON_OFF{
    
    
	OFF,
	ON
};
enum Qos{
    
    
	MAX_ONE,
	MIN_ONE,
	ONLY_ONE
};
enum BackFlag{
    
    
	UNKNOW,
	SUCC,
	FAULT
};
enum ESP_MODE{
    
    
	STA=1,
	AP,
	AP_STA
};
enum ATBACK_KEYWORDS{
    
    
	NO,
	WIFI_GOT,
};
#define ERROR "\r\nERROR\r\n"
#define OK "\r\nOK\r\n"
#define FAIL "\r\nFAIL\r\n"
#define WIFI_GOT_IP "WIFI GOT IP\r\n"
#define WIFI_CONNECTED "WIFI CONNECTED\r\n"

global variable declaration

enum BackFlag back_flag=UNKNOW;         //串口发送AT指令反馈标志  UNKNOW:未发送AT指令或者还未反馈、SUCC:8266反馈OK、FAULT:8266反馈ERROR
char USART_ReceiveString[300];         //串口接收到的数据
enum ATBACK_KEYWORDS ATBack_KeyWords;  //用于判断WIFI连接状态

Serial port initialization

Use PA9 and PA10 to connect the RXD and TXD pins of ESP8266 respectively.

void usart_init(uint32_t bound)				//115200
{
    
    
        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_TX   PA.9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

	
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

       

        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);   

        USART_InitStructure.USART_BaudRate = bound;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        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_ITConfig(USART1, USART_IT_IDLE, ENABLE);
				
        USART_Cmd(USART1, ENABLE);                   

}

Disable AT command echo

Since the AT commands sent every time will be sent back by the 8266 through the serial port, in order to relieve the pressure on the serial port and better detect the OK or ERROR feedback from the 8266, it is recommended to turn off the AT command echo. The call of the function has no effect, no test is carried out, and it is only for theoretical explanation. (In order to ensure the correct initialization of 8266, you need to use clearBackFlag() to clear the feedback flag of 8266 before and after sending the AT command, and the subsequent code is the same)

void AT_Init(){
    
    
	clearBackFlag();    
	printf("ATE0\r\n");
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("ATE0\r\n");
		}
	}
	clearBackFlag();
}

Set the working mode of esp8266

Set to STA mode, 8266 as a device to connect to other AP hotspots or WIFI.

void Esp_Mode(enum ESP_MODE mode){
    
    
	clearBackFlag();
	printf("AT+CWMODE=%d\r\n",mode);//sta   mode
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+CWMODE=%d\r\n",mode);
		}
	}
	clearBackFlag();
}

Network distribution in a mechanical way (not recommended)

After the system is powered on, it will wait for 5 seconds. If it is already connected to wifi, it does not need to configure the network, otherwise use a fixed wifi password to connect to a fixed wifi

void WIFI_Connect(char ssid[],char wifi_password[]){
    
    
	delay_s(5);
	if(ATBack_KeyWords!=WIFI_GOT){
    
    
		Esp_Mode(STA);
		clearBackFlag();
		printf("AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,wifi_password);
		while(back_flag!=SUCC){
    
    
			if(back_flag==FAULT){
    
    
				printf("AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,wifi_password);
			}
		}
		clearBackFlag();
	}else{
    
    
		clearATBackKeyWords();
	}
}

Intelligent distribution network (recommended method)

Use WIFI_Connect_Wechat() to call the first three functions for smart distribution.
After the system is powered on, it will wait for 5 seconds. If it is connected to wifi, it does not need to configure the network, otherwise it will start the intelligent network configuration. It can be ended early after success, and the led goes out to indicate the end of the distribution network.

void SmartConfig_ON(){
    
    																						//开始智能配网
	clearBackFlag();
	printf("AT+CWSTARTSMART=3\r\n");																
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+CWSTARTSMART=3\r\n");
		}
	}
	clearBackFlag();
}

uint16_t SmartConfig(){
    
    																									//微信配网过程中  最长持续60s
	uint16_t wifi_delay_i=0;
	while(ATBack_KeyWords!=WIFI_GOT&&wifi_delay_i<20){
    
    						
		delay_s(3);
		wifi_delay_i+=1;
	}
		return wifi_delay_i<10;
}
void SmartConfig_OFF(){
    
    																						//停止微信配网
	clearBackFlag();
	printf("AT+CWSTOPSMART\r\n");																		
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+CWSTOPSMART\r\n");
		}
	}
	clearBackFlag();
}

void WIFI_Connect_Wechat(){
    
    
	delay_s(5);
	if(ATBack_KeyWords!=WIFI_GOT){
    
    																		//如果没有自动连上wifi
		Esp_Mode(STA);
		SmartConfig_ON();
		led_on();
		SmartConfig();
		led_off();
		SmartConfig_OFF();																
	}else{
    
    
		clearATBackKeyWords();
	}
}

Configure the client ID, user name, and password of MQTT

It should be noted that the Client ID cannot be repeated. It is recommended to set the Client ID with the timestamp.

void Mqtt_UserCFG(char *client_id,char *username,char *password){
    
    
	clearBackFlag();
	printf("AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",client_id,username,password);
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
            printf("AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",client_id,username,password);		
		}
	}
	clearBackFlag();
}

Connect to the MQTT server

Connect to the MQTT server through ip and port number.

void Mqtt_Connect(char *ip,char* port,enum ON_OFF reconnect){
    
    
	clearBackFlag();
	printf("AT+MQTTCONN=0,\"%s\",%s,%d\r\n",ip,port,reconnect);
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+MQTTCONN=0,\"%s\",%s,%d\r\n",ip,port,reconnect);
		}
	}
	clearBackFlag();
}

subscribe topic

void Mqtt_SubTopic(char *Topic_Name,enum Qos qos){
    
    
	clearBackFlag();
	printf("AT+MQTTSUB=0,\"%s\",%d\r\n",Topic_Name,qos);
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+MQTTSUB=0,\"%s\",%d\r\n",Topic_Name,qos);
		}
	}
	clearBackFlag();
}

post topic

Two functions for posting topics, the difference is that the first one has 8266 feedback judgment, if the feedback ERROR will continue to send; the second one has no feedback judgment.

void Mqtt_PubTopic(char *Topic_Name,char* data,enum Qos qos,enum ON_OFF retain){
    
    
	clearBackFlag();
	printf("AT+MQTTPUB=0,\"%s\",\"%s\",%d,%d\r\n",Topic_Name,data,qos,retain);
	while(back_flag!=SUCC){
    
    
		if(back_flag==FAULT){
    
    
			printf("AT+MQTTPUB=0,\"%s\",\"%s\",%d,%d\r\n",Topic_Name,data,qos,retain);

		}
	}
	clearBackFlag();
}

void Mqtt_PubTopic_UsartIT(char *Topic_Name,char* data,enum Qos qos,enum ON_OFF retain){
    
    
	printf("AT+MQTTPUB=0,\"%s\",\"%s\",%d,%d\r\n",Topic_Name,data,qos,retain);
}

AT command execution feedback detection

It is used to detect the result returned after the AT command is executed.

uint16_t checkOK(char* res_txt,char*match_txt){
    
    
	uint16_t res_len,mat_len,flag=1;
	res_len=strlen(res_txt);
	mat_len=strlen(match_txt);
	for(int i=res_len-mat_len,j=0;i<res_len&&j<mat_len;i++,j++){
    
    
		if(res_txt[i]!=match_txt[j]){
    
    
			flag=0;
			break;
		}
	}
	return flag;
}

Determine whether it is a topic message subscribed by MQTT

When the serial port receives data, the current function can be used to detect whether it is an mqtt message. Serial port data can be classified and processed.

uint16_t info_type(char USART_ReceiveString[]){
    
    					//1为mqtt消息  0为普通消息
	uint16_t i,flag=1;
	char head[13]="+MQTTSUBRECV";   //12+1   +MQTTSUBRECV+'\0'
	for(i=0;USART_ReceiveString[i]!='\0'&&i<12;i++){
    
    
		if(USART_ReceiveString[i]!=head[i]){
    
    
			flag=0;
			break;
		}
	}
	return flag;
}

clear flag

It is mainly used to assist other functions before and after sending AT commands.

void clearBackFlag(){
    
    
	back_flag=UNKNOW;
}
void clearATBackKeyWords(){
    
    
	ATBack_KeyWords=NO;
}

MQTT initialization

This function integrates the MQTT initialization function. Subscribe to the test/stm32_server topic message, and finally publish a test/stm32_client topic with the content {"type":"init", "msg":"success"}, indicating that the initialization is complete.

void mqtt_init(char *ip,char* port,char *username,char *password,char *client_id){
    
    
	delay_s(1);
	AT_Init();
	WIFI_Connect_Wechat();
	Mqtt_UserCFG(client_id,username,password);
	Mqtt_Connect(ip,port,ON);
	Mqtt_SubTopic("test/stm32_server",MAX_ONE);
	Mqtt_PubTopic("test/stm32_client","{\\\"type\\\":\\\"init\\\"\\,\\\"msg\\\":\\\"success\\\"}",ONLY_ONE,OFF);
}

Guess you like

Origin blog.csdn.net/weixin_46144773/article/details/128793578