STM32-ESP8266-JSON格式上报温湿度+远程控制LED灯亮灭项目笔记


1- 串口接收转发

连接上ESP8266之后,我们需要进行通信,怎么通信呢?
我们可以在STM32单片机上通过软件编程实现一个串口接收转发的程序

  • 从USART1收到的数据(PC端发过来的)转发给USART2(ESP8266 WiFi模块)
  • 从USART2收到的数据(ESP8266 WiFi模块)转发给USART1(PC端)

在这里插入图片描述

/* USER CODE BEGIN 0 */
static uint8_t  s_uart1_rxch;
char            g_uart1_rxbuf[256];
uint8_t         g_uart1_bytes;

static uint8_t  s_uart2_rxch;
char            g_uart2_rxbuf[256];
uint8_t         g_uart2_bytes;
/* USER CODE END 0 */

...
void MX_USART1_UART_Init(void)//USART1的中断处理函数
{
  /* USER CODE BEGIN USART1_Init 2 */
HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
  /* USER CODE END USART1_Init 2 */
...
}

void MX_USART2_UART_Init(void)//USART2的中断处理函数
{
  /* USER CODE BEGIN USART2_Init 2 */
  HAL_UART_Receive_IT(&huart2, &s_uart2_rxch, 1);
  /* USER CODE END USART2_Init 2 */
  ...
}
...
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart -> Instance == USART1)
	{
		if(g_uart1_bytes < sizeof(g_uart1_rxbuf))
		{
			g_uart1_rxbuf[g_uart1_bytes++] = s_uart1_rxch;
		}
		HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
	}

	if(huart -> Instance == USART2)
	{
		if(g_uart2_bytes < sizeof(g_uart2_rxbuf))
		{
			g_uart2_rxbuf[g_uart2_bytes++] = s_uart2_rxch;
		}
		HAL_UART_Receive_IT(&huart2, &s_uart2_rxch, 1);
	}
}

/*添加usart1和usart2的收发转发功能函数, main() 函数中会调用*/
void uart_forward(void)
{
	if(strstr(g_uart1_rxbuf, "\r\n"))
	{
		HAL_UART_Transmit(&huart2, (uint8_t *)g_uart1_rxbuf, g_uart1_bytes, 0xFF);
		clear_uart1_rxbuf();
	}

	if(g_uart2_bytes > 0)
	{
		HAL_Delay(100);
		HAL_UART_Transmit(&huart1, (uint8_t *)g_uart2_rxbuf, g_uart2_bytes, 0xFF);
		clear_uart2_rxbuf();
	}
}
/* USER CODE END 1 */

这是根据串口USART1(USART2也是一样的)写的代码画出来的比较好理解的图:(CPU接收到数据怎么样进行存储的)

在这里插入图片描述

2- 函数详解(加深对代码的理解)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


3- AT命令

(1)WiFi 初始化命令

在这里插入图片描述

(2)无线连接命令

在这里插入图片描述

(3)数据收发命令

在这里插入图片描述


4- 实现代码

(1)esp8266.c / esp8266.h

esp8266.h

/*
 * esp8266.h
 *
 *  Created on: Nov 11, 2022
 *      Author: Administrator
 */

#ifndef INC_ESP8266_H_
#define INC_ESP8266_H_


#include <stdio.h>
#include "usart.h"

#define wifi_huart     &huart2               /* WiFi 模块使用的串口 */
#define g_wifi_rxbuf   g_uart2_rxbuf       /* WiFi 模块的接收buffer */
#define g_wifi_rxbytes g_uart2_bytes     /* WiFi 模块接收数据的大小 */

/*清除WiFi 模块接收buffer里面的数据内容宏,用宏不用函数是因为函数需要额外时间开销*/
#define clear_atcmd_buf() do{memset(g_wifi_rxbuf, 0, sizeof(g_wifi_rxbuf));g_wifi_rxbytes = 0;} while(0)

/*ESP8266 WiFi 模块发送AT命令函数。返回值为0表示成功,!0表示失败*/
#define EXPECT_OK "OK\r\n"
extern int send_atcmd(char *atcmd, char *expect_replay, unsigned int timeout);

extern int atcmd_send_data(unsigned char *data, int bytes, unsigned int timeout);

/* ESP8266 WiFi模块初始化函数。返回值为0表示成功, !0表示失败*/
extern int esp8266_module_init(void);

/*WSP8266 WiFi 模块复位重启函数,返回值为0表示成功,!0表示失败*/
extern int esp8266_module_reset(void);

/* ESP8266 WiFi模块连接路由器函数。返回值为0表示成功,!0表示失败 */
extern int esp8266_join_network(char *ssid, char *pwd);

/* ESP8266 获取自己的IP地址和网关IP地址。返回值为0表示成功, !0表示失败*/
int esp8266_get_ipaddr(char *ipaddr, char *gateway, int ipaddr_size);

/* ESP8266 WiFi模块做ping命令测试网络连通性。返回值为0表示成功, !0表示失败 */
int esp8266_ping_test (char *host);

/* ESP8266 WiFi模块建立TCP socket连接函数。返回值为0表示成功, !0表示失败*/
extern int esp8266_sock_connect(char *servip, int port);

/* ESP8266 WiFi模块断开TCP socket连接函数。返回值为0表示成功, !0表示失败*/
extern int esp8266_sock_disconnect(void);

/* ESP8266 WiFi 通过TCP Socket发送数据函数。返回值为0表示失败,>0表示成功发送字节数*/
extern int esp8266_sock_send (unsigned char *data, int bytes);

/* ESP8266 WiFi通过TCP Socket接收数据函数。返回值为0无数据,>0表示接收到数据字节数*/
extern int esp8266_sock_recv(unsigned char *buf, int size);


#endif /* INC_ESP8266_H_ */

esp8266.c

/*
 * esp8266.c
 *
 *  Created on: Nov 11, 2022
 *      Author: Administrator
 */

#include <stdio.h>
#include "usart.h"
#include "esp8266.h"
#include <string.h>
#include <stdlib.h>

/* WiFi模块驱动调试宏,注释下面两个宏定义可以取消调试打印*/

//#define CONFIG _WIFI_DEBUG
#define CONFIG_WIFI_PRINT

#ifdef CONFIG_WIFI_DEBUG
#define wifi_dbg(format, args...) printf(format, ##args)
#else
#define wifi_dbg(format, args...) do{} while(0)
#endif

#ifdef CONFIG_WIFI_PRINT
#define wifi_print(format, args...) printf(format, ##args)
#else
#define wifi_print(format, args...) do}{} while(0)
#endif

/*ESP8266 WiFi 模块发送AT命令函数。返回值为0表示成功,!0表示失败*/
int send_atcmd(char *atcmd, char *expect_replay, unsigned int timeout)
{
	int           rv = 11;
	unsigned int  i;
	char          *expect;

	/*check function input argument validation*/
	if( !atcmd || strlen(atcmd) <= 0)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}
	wifi_dbg("\r\nStart send AT command: %s", atcmd);
	clear_atcmd_buf();
	HAL_UART_Transmit(wifi_huart, (uint8_t *)atcmd, strlen(atcmd), 1000);

	expect = expect_replay ? expect_replay: "OK\r\n";

	/*Receive AT reply string by UART interrupt handler, stop by "OK/ERROR" or timeout*/
	for(i=0; i<timeout; i++)
	{
		if(strstr(g_wifi_rxbuf, expect) )
		{
			wifi_dbg("AT command Got expect reply '%s' \r\n", expect);
			rv = 0;
			goto Cleanup;
		}

		if( strstr(g_wifi_rxbuf, "ERROR\r\n") || strstr(g_wifi_rxbuf, "FAIL\r\n"))
		{
			rv = 2;
			goto Cleanup;
		}
		HAL_Delay(1);
	}

Cleanup:
	wifi_dbg("<<<< AT command reply:\r\n%s", g_wifi_rxbuf);
	return rv;
}


int atcmd_send_data(unsigned char *data, int bytes, unsigned int timeout)
{
	int          rv = -1;
	unsigned int i;

	/*check function input argument validation*/
	if(!data || bytes <= 0)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}

	wifi_dbg("\r\nStart AT command send [%d] bytes data\n", bytes);
	clear_atcmd_buf();
	HAL_UART_Transmit(wifi_huart, data, bytes, 1000);

	/*Receive AT reply string by UART interrupt handler, stop by "OK/ERROR" or timeout*/
	for(i=0; i<timeout; i++)
	{
		if(strstr(g_wifi_rxbuf, "SEND OK\r\n"))
		{
			rv = 0;
			goto Cleanup;
		}

		if(strstr(g_wifi_rxbuf, "ERROR\r\n"))
		{
			rv = 1;
			goto Cleanup;
		}

		HAL_Delay(1);
	}

Cleanup:
	wifi_dbg("<<<< AT command reply:\r\n%s", g_wifi_rxbuf);
	return rv;
}


/* ESP8266 WiFi模块初始化函数。返回值为0表示成功, !0表示失败*/
int esp8266_module_init(void)
{
	int     i;
	wifi_print("INFO: Initialize ESP8266 module now...\r\n");
	send_atcmd("AT+RST\r\n", EXPECT_OK, 500);//重启、复位wifi模块,如果成功会返回OK,我们strstr()函数判断返回的内容g_wifi_rxbuf是否有OK就可判断是否成功

	for(i=0; i<6; i++)
	{
		if(!send_atcmd("AT\r\n", EXPECT_OK, 500))
		{
			wifi_print("INFO: Send AT to ESP8266 and got reply ok\r\n");
			break;
		}

		HAL_Delay(100);
	}

	if(i>=6)
	{
		wifi_print("ERROR: Can't receive AT reply after reset\r\n");
		return -2;
	}

	if(send_atcmd("AT+CWMODE=1\r\n", EXPECT_OK, 500))
	{
		wifi_print("ERROR: Set ESP8266 work as Station mode failure\r\n");
		return -3;
	}

	if(send_atcmd("AT+CWDHCP=1,1\r\n", EXPECT_OK, 500))
	{
		wifi_print("ERROR: Enable ESP8266 Station mode DHCP failure\r\n");
		return -4;
	}

#if 0
	if(send_atcmd("AT+GMR\r\n", EXPECT_OK, 500))
	{
		wifi_print("ERROR: AT+GMR check ESP8266 reversion failure\r\n");
		return -5;
	}
#endif

	HAL_Delay(500);
	return 0;
}

/* ESP8266 WiFi模块连接路由器函数。返回值为0表示成功,!0表示失败 */
int esp8266_join_network(char *ssid, char *pwd)
{
	char    atcmd[128] = {0x00};
	int     i;

	if(!ssid || !pwd)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}

	snprintf(atcmd, sizeof(atcmd), "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);
	if(send_atcmd(atcmd, "CONNECTED", 10000))
	{
		wifi_print("ERROR: ESP8266 connect to '%s' failure\r\n", ssid);
		return -2;
	}

	wifi_print("INFO: ESP8266 connect to '%s' OK\r\n", ssid);

	/*check got IP address or not by netmask (255.)*/
	for(i=0; i<10; i++)
	{
		if(!send_atcmd("AT+CIPSTA_CUR?\r\n", "255.", 1000))
		{
			wifi_print("INFO: ESP8266 got IP address ok\r\n");
			return 0;
		}
		HAL_Delay(300);
	}
	wifi_print("ERROR: ESP8266 assigned IP address failure\r\n");
	return -3;
}
/*
+CIPSTA_CUR:ip: "192.168.2.100"
+CIPSTA_CUR:gateway: "192.168.2.1"
*/

static int util_parser_ipaddr(char *buf, char *key, char *ipaddr, int size)
{
	char *start;
	char *end;
	int  len;

	if(!buf || !key || !ipaddr)
	{
		return -1;
	}
	/*find the key string*/
	start = strstr(buf, key);
	if(!start)
	{
		return -2;
	}

	start+=strlen(key)+1;/*skip " */
	end = strchr(start,'"');/*find last "*/
	if(!end)
	{
		return -3;
	}

	len = end - start;
	len = len>size ? size : len;

	memset(ipaddr, 0, size);
	strncpy(ipaddr, start, len);

	return 0;

}


/* ESP8266 获取自己的IP地址和网关IP地址。返回值为0表示成功, !0表示失败*/
int esp8266_get_ipaddr(char *ipaddr, char *gateway, int ipaddr_size)
{
	if(!ipaddr || !gateway || ipaddr_size<7 )
	{
		wifi_print("ERROR:Invalid input argument\r\n");
		return -1;
	}

	if(send_atcmd("AT+CIPSTA_CUR?\r\n", "255.", 1000))
	{
		wifi_print("ERROR: ESP8266 AT+CIPSTA_CUR? command failure\r\n");
		return -2;
	}

	if(util_parser_ipaddr(g_wifi_rxbuf, "ip", ipaddr, ipaddr_size))
	{
		wifi_print("ERROR: ESP8266 AT+CIPSTA_CUR? parser IP address failure\r\n");
		return -3;
	}

	if(util_parser_ipaddr(g_wifi_rxbuf, "gateway:", gateway, ipaddr_size))
	{
		wifi_print("ERROR: ESP8266 AT+CIPSTA_CUR? parser gateway gailure\r\n");
		return -4;
	}

	wifi_print("INFO: ESP8266 got IP address[%s] gateway[%s] ok\r\n", ipaddr, gateway);
	return 0;
}

/* ESP8266 WiFi模块做ping命令测试网络连通性。返回值为0表示成功, !0表示失败 */
int esp8266_ping_test (char *host)
{
	char atcmd[128] = {0x00};

	if(!host)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}

	snprintf(atcmd, sizeof(atcmd), "AT+PING=\"%s\"\r\n", host);
	if(send_atcmd(atcmd, EXPECT_OK, 3000))
	{
		wifi_print("ERROR: ESP8266 ping test [%s] failure\r\n", host);
		return -2;
	}
	wifi_print("INFO: ESP8266 ping rest [%s] ok\r\n", host);
	return 0;
}

/* ESP8266 WiFi模块建立TCP socket连接函数。返回值为0表示成功, !0表示失败*/
int esp8266_sock_connect(char *servip, int port)
{
	char atcmd[128] = {0x00};

	if(!servip || port <= 0)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}

	send_atcmd("AT+CIPMUX=0\r\n", EXPECT_OK, 1500);

	snprintf(atcmd, sizeof(atcmd), "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n", servip, port);
	if(send_atcmd(atcmd, "CONNECT\r\n", 1000))
	{
		wifi_print("ERROR: ESP8266 socket connect to [%s:%d] failure\r\n", servip, port);
		return -2;
	}

	wifi_print("INFO: ESP8266 socke connect to [%s:%d] OK\r\n", servip, port);
	return 0;
}

/* ESP8266 WiFi模块断开TCP socket连接函数。返回值为0表示成功, !0表示失败*/
int esp8266_sock_disconnect(void)
{
	send_atcmd("AT+CIPCLOSE\r\n", EXPECT_OK, 1500);
	return 0;
}

/* ESP8266 WiFi 通过TCP Socket发送数据函数。返回值为0表示失败,>0表示成功发送字节数*/
int esp8266_sock_send(unsigned char *data, int bytes)
{
	char atcmd[128] = {0x00};

	if(!data || bytes <= 0)
	{
		wifi_print("ERRPR: Invalid input argument\r\n");
		return -1;
	}

	snprintf(atcmd, sizeof(atcmd), "AT+CIPSEND=%d\r\n", bytes);
	if(send_atcmd(atcmd, ">", 500))
	{
		wifi_print("ERROR: AT+CIPSEND command failure\r\n");
		return 0;
	}

	if(atcmd_send_data((unsigned char *)data, bytes, 1000))
	{
		wifi_print("ERROR: AT+CIPSEND send data failure\r\n");
		return 0;
	}
	return bytes;
}

/* ESP8266 WiFi通过TCP Socket接收数据函数。返回值为0无数据,>0表示接收到数据字节数*/
int esp8266_sock_recv(unsigned char *buf, int size)
{
	char   *data = NULL;
	char   *ptr = NULL;

	int    len;
	int    rv;
	int    bytes;

	if(!buf || size <= 0)
	{
		wifi_print("ERROR: Invalid input argument\r\n");
		return -1;
	}

	if(g_wifi_rxbytes <= 0)
	{
		return 0;
	}
	if(!(ptr=strstr(g_wifi_rxbuf, "+IPD")) || !(data = strstr(ptr,":")) )
	{
		return 0;
	}

	data ++;
	bytes = atoi(ptr+strlen("+IPD,"));

	len = g_wifi_rxbytes - (data-g_uart2_rxbuf);

	if(len < bytes)
	{
		wifi_dbg("+IPD data not receive over, receive again later...\r\n");
		return 0;
	}

	memset(buf, 0, size);
	rv = bytes>size ? size : bytes;
	memcpy(buf, data, rv);

	clear_atcmd_buf();

	return rv;
}

(2)sht30.c / sht30.h

sht30.h

/*
 * sht30.h
 *
 *  Created on: Nov 13, 2022
 *      Author: Administrator
 */

#ifndef INC_SHT30_H_
#define INC_SHT30_H_


#include "stm32l4xx_hal.h"

#define SHT30_ADDR 0x44

#define SHT30_ADDR_WR (SHT30_ADDR<<1)
#define SHT30_ADDR_RD ((SHT30_ADDR<<1) | 0x01)

#define SHT30_DATA_SIZE 6

typedef enum
{
	SOFT_RESET_CMD = 0x30A2,

	HIGH_ENABLED_CMD = 0x2C06,
	MEDIUM_ENABLED_CMD =0x2C0D,
	LOW_ENSABLED_CMD = 0x2C10,
	HIGH_DISABLED_CMD = 0x2400,
	MEDIUM_DISABLED_CMD = 0X240B,
	LOW_DISABLED_CMD = 0x2416,


	HIGH_0_5_CMD = 0x2032,
	MEDIUM_0_5_CMD = 0x2024,
	LOW_0_5_CMD = 0x202F,
	HIGH_1_CMD = 0x2130,
	MEDIUM_1_CMD = 0x2126,
	LOW_1_CMD = 0x212D,
	HIGH_2_CMD = 0x2236,

	MEDIUM_2_CMD = 0x2220,
	LOW_2_CMD = 0x222B,
	HIGH_4_CMD = 0x2334,
	MEDIUM_4_CMD = 0x2322,
	LOW_4_CMD = 0x2329,
	HIGH_10_CMD = 0x2737,
	MEDIUM_10_CMD = 0x2721,
	LOW_10_CMD = 0x272A,
}SHT30_CMD;

extern int SHT30_SampleData(float *temperature, float *humidity);

#endif /* INC_SHT30_H_ */

sht30.c

/*
 * sht30.c
 *
 *  Created on: Nov 3, 2022
 *      Author: Administrator
 */

#include <stdio.h>
#include "stm32l4xx_hal.h"
#include "i2c.h"
#include "sht30.h"

#define CONFIG_SHT30_DEBUG

#ifdef CONGIF_SHT30_DEBUG
#define sht30_print(format, args...) printf(format, ##args)
#else
#define sht30_print(format, args...) do{} while(0)
#endif

static int sht30_send_cmd(SHT30_CMD cmd)
{
	uint8_t buf[2];

	buf[0] = cmd >> 8;
	buf[1] = cmd & 0xFF;

	return HAL_I2C_Master_Transmit(&hi2c2, SHT30_ADDR_WR, (uint8_t*)buf, 2, 0xFFFF);
}

static void sht30_soft_reset(void)
{
	sht30_send_cmd(SOFT_RESET_CMD);
	HAL_Delay(1);
}

static int sht30_single_shot_measurement(uint8_t *buf, uint8_t buf_size)
{
	uint16_t cmd = HIGH_ENABLED_CMD;
	uint8_t  rv;

	if( !buf || buf_size < SHT30_DATA_SIZE )
	{
		sht30_print("%s(): Invalid input argument\n", __func__);
		return -1;
	}

	rv = sht30_send_cmd(cmd);
	if( rv )
	{
		sht30_print("ERROR: HST30 send messurement command failure, rv = &d\n", rv);
		sht30_soft_reset();
		return -2;
	}

	rv = HAL_I2C_Master_Receive(&hi2c2, SHT30_ADDR_RD, buf, SHT30_DATA_SIZE, 0xFFFF);
	if(rv)
	{
		sht30_print("ERROR: SHT30 read measurement result failure, rv = %d\n", rv);
		return -3;
	}

	return 0;
}

static uint8_t sht30_crc8(const uint8_t *data, int len)
{
	const uint8_t POLYNOMIAL = 0x31;
	uint8_t       crc = 0xFF;
	int           i,j;

	for (i=0; i<len; ++i)
	{
		crc ^= *data++;

		for (j=0; j<8; j++)
		{
			crc = (crc & 0x80)? (crc << 1) ^ POLYNOMIAL:(crc << 1);
		}
	}
	return crc;
}

int SHT30_SampleData(float *temperature, float *humidity)
{
	uint8_t buf[SHT30_DATA_SIZE];
	int rv;
	uint16_t temp;
	uint16_t humd;
	uint16_t crc;

	if(!temperature || !humidity)
	{
		sht30_print("%s(): Invalid input argument\n", __func__);
		return -1;
	}

	rv = sht30_single_shot_measurement(buf, SHT30_DATA_SIZE);
	if(rv)
	{
		sht30_print("SHT30 Single Short measurement failure, rv=%d\n", rv);
		return -2;
	}

#ifdef CONFIG_SHT30_DEBUG
	{
		int i;

		sht30_print("SHT30 get %d bytes sample data: \n", SHT30_DATA_SIZE);
		for(i=0; i<SHT30_DATA_SIZE; i++)
		{
			sht30_print("0x%02x ", buf[i]);
		}
		sht30_print("\n");
	}
#endif

	crc = sht30_crc8(buf, 2);
	sht30_print("SHT30 temperature Cal_CRC: [%02x] EXP_CRC: [%02x]\n", crc, buf[2]);
	if(crc != buf[2])
	{
		sht30_print("SHT30 measurement temperature got CRC error\n");
		return -3;
	}

	crc = sht30_crc8(&buf[3], 2);
	sht30_print("SHT30 humidity Cal_CRC: [%02x] EXP_CRC: [%02x]\n", crc, buf[5]);
	if(crc != buf[5])
	{
		sht30_print("SHT30 messurement temperature got CRC error\n");
		return -4;
	}

	temp = (buf[0]<<8) | buf[1];
	humd = (buf[3]<<8) | buf[4];

	*temperature = -45 + 175*((float)temp/65535);
	*humidity = 100 * ((float)humd/65535);

	return 0;
}

(3)gpio.c / gpio.c

gpio.h

/* USER CODE BEGIN Prototypes */
enum
{
	BlueLed,
	RedLed,
	GreenLed,
	LedMax,
};

#define OFF 0
#define ON 1

/*将gpio.c中定义的gpio_t结构体定义移到头文件中来,并在它里面添加一个char *name的字�?,其它C文件会用到这个结构体�?*/
typedef struct gpio_s
{
	  const char     *name;
	  GPIO_TypeDef   *group;
	  uint16_t       pin;
} gpio_t;

extern gpio_t      leds[LedMax];

extern void turn_led(int which, int status);

/* USER CODE END Prototypes */

gpio.c

/* USER CODE BEGIN 2 */

gpio_t      leds[LedMax] =
{
		{"BlueLed", BlueLed_GPIO_Port,  BlueLed_Pin},
		{"RedLed", RedLed_GPIO_Port,  RedLed_Pin},
		{"GreenLed", GreenLed_GPIO_Port,  GreenLed_Pin},
};

void turn_led(int which, int status)
{
	GPIO_PinState       level;
	if( which<0 || which>=LedMax)
	{
		return ;
	}
	level = status == OFF ? GPIO_PIN_SET : GPIO_PIN_RESET;

	HAL_GPIO_WritePin(leds[which].group, leds[which].pin, level);
}
/* USER CODE END 2 */

(4)usart.c / usart.h

usart.h

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart.h
  * @brief   This file contains all the function prototypes for
  *          the usart.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */

extern UART_HandleTypeDef huart1;

extern UART_HandleTypeDef huart2;

/* USER CODE BEGIN Private defines */
extern char     g_uart1_rxbuf[256];
extern uint8_t  g_uart1_bytes;
#define clear_uart1_rxbuf() do { memset(g_uart1_rxbuf, 0, sizeof(g_uart1_rxbuf));g_uart1_bytes=0;} while(0)

extern char     g_uart2_rxbuf[256];
extern uint8_t  g_uart2_bytes;
#define clear_uart2_rxbuf() do { memset(g_uart2_rxbuf, 0, sizeof(g_uart2_rxbuf));g_uart2_bytes=0;} while(0)

extern void uart_forward(void);
/* USER CODE END Private defines */

void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);

/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __USART_H__ */

usart.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */
static uint8_t  s_uart1_rxch;
char            g_uart1_rxbuf[256];
uint8_t         g_uart1_bytes;

static uint8_t  s_uart2_rxch;
char            g_uart2_rxbuf[256];
uint8_t         g_uart2_bytes;
/* USER CODE END 0 */

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
  /* USER CODE END USART1_Init 2 */

}
/* USART2 init function */

void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
  HAL_UART_Receive_IT(&huart2, &s_uart2_rxch, 1);
  /* USER CODE END USART2_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
  else if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */

  /* USER CODE END USART2_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
    PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART2 interrupt Init */
    HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART2_IRQn);
  /* USER CODE BEGIN USART2_MspInit 1 */

  /* USER CODE END USART2_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
  else if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspDeInit 0 */

  /* USER CODE END USART2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();

    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);

    /* USART2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART2_IRQn);
  /* USER CODE BEGIN USART2_MspDeInit 1 */

  /* USER CODE END USART2_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart -> Instance == USART1)
	{
		if(g_uart1_bytes < sizeof(g_uart1_rxbuf))
		{
			g_uart1_rxbuf[g_uart1_bytes++] = s_uart1_rxch;
		}
		HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
	}

	if(huart -> Instance == USART2)
	{
		if(g_uart2_bytes < sizeof(g_uart2_rxbuf))
		{
			g_uart2_rxbuf[g_uart2_bytes++] = s_uart2_rxch;
		}
		HAL_UART_Receive_IT(&huart2, &s_uart2_rxch, 1);
	}
}

/*添加usart1和usart2的收发转发功能函数, main() 函数中会调用*/
void uart_forward(void)
{
	if(strstr(g_uart1_rxbuf, "\r\n"))
	{
		HAL_UART_Transmit(&huart2, (uint8_t *)g_uart1_rxbuf, g_uart1_bytes, 0xFF);
		clear_uart1_rxbuf();
	}

	if(g_uart2_bytes > 0)
	{
		HAL_Delay(100);
		HAL_UART_Transmit(&huart1, (uint8_t *)g_uart2_rxbuf, g_uart2_bytes, 0xFF);
		clear_uart2_rxbuf();
	}
}

#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)/*char类型是以int类型存储的,�??以可以用int*/
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}
/* USER CODE END 1 */

(5)main.c / main.h

main.h

/* USER CODE BEGIN Private defines */
#define time_after(a,b)  ( (int32_t)(b) - (int32_t)(a) < 0)
#define time_before(a,b)  time_after(b,a)

#define time_after_eq(a,b)  ( (int32_t)(a) - (int32_t)(b) >= 0)
#define time_before_eq(a,b)  time_after_eq(b,a)

/* USER CODE END Private defines */

main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "sht30.h"
#include <string.h>
#include "esp8266.h"
#include <stdio.h>
#include "core_json.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
#define FLAG_WIFI_CONNECTED (1<<0) /*WIFI连接路由器标志位*/
#define FLAG_SOCK_CONNECTED (1<<1) /*Socket连接服务器标志位*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static int report_tempRH_json();
static int  parser_led_json(char *json_string, int bytes);
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t last_time = 0;
	unsigned char buf[256];
	int rv;


	char ipaddr[16];
	char gateway[16];
	unsigned wifi_flag = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_I2C2_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  printf("Welcome to the esp8266WIFi module\r\n");
  esp8266_module_init();
  while (1)
  {
	  //uart_forward();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  /*wifi没有连接上无线路由器就去连接无线路由器并且进行ping测试*/
	  /*
	   wifi_flag & FLAG_WIFI_CONNECTED = 0
	   wifi_flay | FLAG_WIFI_CONNECTED = 1
	   */
	  if(!(wifi_flag&FLAG_WIFI_CONNECTED))
	  {
		  if(esp8266_join_network("513","lrh2822736036"))
		  {
			  esp8266_module_init();
			  HAL_Delay(200);
			  continue;
		  }
		  if(esp8266_get_ipaddr(ipaddr, gateway, sizeof(ipaddr)))
		  {
			  HAL_Delay(1000);
			  continue;
		  }
		  if(esp8266_ping_test(gateway))
		  {
			  HAL_Delay(1000);
			  continue;
		  }
		  wifi_flag |= FLAG_WIFI_CONNECTED;
	  }

	  /*网络socket没有连接上socket服务器的话就连接服务�?*/
	  /*
	   wifi_flag & FLAG_SOCK_CONNECTED = 0
	   wifi_flag | FLAG_SOCK_CONNECTED = 2
	   */
	  if(!(wifi_flag&FLAG_SOCK_CONNECTED))
	  {
		  if(esp8266_sock_connect("192.168.1.127",12345))
		  {
			  HAL_Delay(1000);
			  continue;
		  }
		  wifi_flag |= FLAG_SOCK_CONNECTED;
	  }
		 /*接收并且打印socket服务器发送过来的数据*/
		 if( (rv = esp8266_sock_recv(buf, sizeof(buf))) > 0)
		 {
			parser_led_json((char *)buf, rv);
			printf("ESP8266 socket receive %d bytes data: %s\n", rv, buf);
		 }


		  /*定时发数据到socket服务器*/
		 if(time_after(HAL_GetTick(), last_time + 3000))
		  {
			  rv = report_tempRH_json();
			  if(0 == rv)
			  {
				  printf("ESP8266 socket send message ok\n");
			  }
			  else
			  {
				  printf("ESP8266 socket send message failure, rv = %d\r\n", rv);

				  wifi_flag &= ~FLAG_SOCK_CONNECTED;

				  if(esp8266_ping_test(gateway))
				  {
					  wifi_flag &= ~FLAG_WIFI_CONNECTED;
				  }
			  }

			  last_time = HAL_GetTick();
		  }
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/*JSON上报温湿度*/
int report_tempRH_json()
{
	float     temperature, humidity;
	char      temper_hum_buf[256];
	int       rv;

	if(SHT30_SampleData(&temperature, &humidity) < 0)
	{
		printf("ERROR: SHT30 Sample data failure\n");
		return -1;
	}
	memset(temper_hum_buf, 0, sizeof(temper_hum_buf));

	snprintf(temper_hum_buf, sizeof(temper_hum_buf), "{\"Temperature\":\"%.2f\", \"Humidity\":\"%.2f\"}", temperature, humidity);

	rv = esp8266_sock_send((uint8_t *)temper_hum_buf, strlen(temper_hum_buf));

	return rv > 0 ? 0: -2;
}

/*解析JSON字符串格式进行控制LED灯的亮灭*/
int  parser_led_json(char *json_string, int bytes)
{
	JSONStatus_t   result;
	char           save;
	char           *value;
	size_t         valen;
	int            i;

	printf("BDUG: Start parser JSON string:%s\r\n", json_string);

	result = JSON_Validate(json_string, bytes);

	if(JSONPartial == result)
	{
		printf("WARN: JSON document is valid so far but incomplete!\r\n");
		return 0;
	}

	if(JSONSuccess != result )
	{
		printf("ERROR: JSON doument is not valid JSON!\r\n");
		return -1;
	}

	for(i=0; i<LedMax; i++)
	{
		result = JSON_Search( json_string, bytes, leds[i].name, strlen(leds[i].name), &value, &valen);

		if(JSONSuccess == result)
		{
			save = value[valen];
			value[valen] = '\0';

			if( !strncasecmp(value, "on", 2))
			{
				printf("DBUG: turn %s on\r\n", leds[i].name);
				turn_led(i, ON);
			}

			else if(!strncasecmp(value, "off", 3))
			{
				printf("DBUG: turn %s off\r\n", leds[i].name);
				turn_led(i, OFF);
			}

			value[valen] = save;
		}
	}
	return 1;
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


5- 结果展示

在这里插入图片描述

在这里插入图片描述


  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值