文章目录
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 */