master
hwf453 1 month ago
commit f48be4ee03

@ -0,0 +1,4 @@
{
"idf.flashType": "UART",
"idf.portWin": "COM4"
}

@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(dht11)

@ -0,0 +1,35 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# _Sample project_
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This is the simplest buildable example. The example is used by command `idf.py create-project`
that copies the project to user specified path and set it's name. For more information follow the [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project)
## How to use example
We encourage the users to use the example as a template for the new projects.
A recommended way is to follow the instructions on a [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project).
## Example folder contents
The project **sample_project** contains one source file in C language [main.c](main/main.c). The file is located in folder [main](main).
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt`
files that provide set of directives and instructions describing the project's source files and targets
(executable, library, or both).
Below is short explanation of remaining files in the project folder.
```
├── CMakeLists.txt
├── main
│   ├── CMakeLists.txt
│   └── main.c
└── README.md This is the file you are currently reading
```
Additionally, the sample project contains Makefile and component.mk files, used for the legacy Make based build system.
They are not used or needed when building with CMake and idf.py.

@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c" "dht11.c"
INCLUDE_DIRS ".")

@ -0,0 +1,165 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <driver/rmt_rx.h>
#include <driver/rmt_tx.h>
#include <soc/rmt_reg.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp32/rom/ets_sys.h"
#define TAG "DHT11"
uint8_t DHT11_PIN = -1;
//rmt接收通道句柄
static rmt_channel_handle_t rx_chan_handle = NULL;
//数据接收队列
static QueueHandle_t rx_receive_queue = NULL;
// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_symbol_word_t *item, int item_num, int *humidity, int *temp_x10);
//接收完成回调函数
static bool IRAM_ATTR example_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;
QueueHandle_t rx_receive_queue = (QueueHandle_t)user_data;
// send the received RMT symbols to the parser task
xQueueSendFromISR(rx_receive_queue, edata, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
/** DHT11初始化
* @param dht11_pin GPIO
* @return
*/
void DHT11_Init(uint8_t dht11_pin)
{
DHT11_PIN = dht11_pin;
rmt_rx_channel_config_t rx_chan_config = {
.clk_src = RMT_CLK_SRC_APB, // 选择时钟源
.resolution_hz = 1000 * 1000, // 1 MHz 滴答分辨率,即 1 滴答 = 1 µs
.mem_block_symbols = 64, // 内存块大小,即 64 * 4 = 256 字节
.gpio_num = dht11_pin, // GPIO 编号
.flags.invert_in = false, // 不反转输入信号
.flags.with_dma = false, // 不需要 DMA 后端(ESP32S3才有)
};
//创建rmt接收通道
ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_chan_config, &rx_chan_handle));
//新建接收数据队列
rx_receive_queue = xQueueCreate(20, sizeof(rmt_rx_done_event_data_t));
assert(rx_receive_queue);
//注册接收完成回调函数
ESP_LOGI(TAG, "register RX done callback");
rmt_rx_event_callbacks_t cbs = {
.on_recv_done = example_rmt_rx_done_callback,
};
ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(rx_chan_handle, &cbs, rx_receive_queue));
//使能RMT接收通道
ESP_ERROR_CHECK(rmt_enable(rx_chan_handle));
}
// 将RMT读取到的脉冲数据处理为温度和湿度(rmt_symbol_word_t称为RMT符号)
static int parse_items(rmt_symbol_word_t *item, int item_num, int *humidity, int *temp_x10)
{
int i = 0;
unsigned int rh = 0, temp = 0, checksum = 0;
if (item_num < 41){ // 检查是否有足够的脉冲数
//ESP_LOGI(TAG, "item_num < 41 %d",item_num);
return 0;
}
if(item_num > 41)
item++; // 跳过开始信号脉冲
for (i = 0; i < 16; i++, item++) // 提取湿度数据
{
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
rh = (rh << 1) + (duration < 35 ? 0 : 1);
}
for (i = 0; i < 16; i++, item++) // 提取温度数据
{
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
temp = (temp << 1) + (duration < 35 ? 0 : 1);
}
for (i = 0; i < 8; i++, item++){ // 提取校验数据
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
checksum = (checksum << 1) + (duration < 35 ? 0 : 1);
}
// 检查校验
if ((((temp >> 8) + temp + (rh >> 8) + rh) & 0xFF) != checksum){
ESP_LOGI(TAG, "Checksum failure %4X %4X %2X\n", temp, rh, checksum);
return 0;
}
// 返回数据
rh = rh >> 8;
temp = (temp >> 8) * 10 + (temp & 0xFF);
//判断数据合法性
if(rh <= 100)
*humidity = rh;
if(temp <= 600)
*temp_x10 = temp;
return 1;
}
/** 获取DHT11数据
* @param temp_x10
* @return
*/
int DHT11_StartGet(int *temp_x10, int *humidity)
{
//发送20ms开始信号脉冲启动DHT11单总线
gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DHT11_PIN, 1);
ets_delay_us(1000);
gpio_set_level(DHT11_PIN, 0);
ets_delay_us(20000);
//拉高20us
gpio_set_level(DHT11_PIN, 1);
ets_delay_us(20);
//信号线设置为输入准备接收数据
gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(DHT11_PIN,GPIO_PULLUP_ONLY);
//启动RMT接收器以获取数据
rmt_receive_config_t receive_config = {
.signal_range_min_ns = 100, //最小脉冲宽度(0.1us),信号长度小于这个值,视为干扰
.signal_range_max_ns = 1000*1000, //最大脉冲宽度(1000us),信号长度大于这个值,视为结束信号
};
static rmt_symbol_word_t raw_symbols[128]; //接收缓存
static rmt_rx_done_event_data_t rx_data; //实际接收到的数据
ESP_ERROR_CHECK(rmt_receive(rx_chan_handle, raw_symbols, sizeof(raw_symbols), &receive_config));
// wait for RX done signal
if (xQueueReceive(rx_receive_queue, &rx_data, pdMS_TO_TICKS(1000)) == pdTRUE) {
// parse the receive symbols and print the result
return parse_items(rx_data.received_symbols, rx_data.num_symbols,humidity, temp_x10);
}
return 0;
}

@ -0,0 +1,18 @@
#ifndef _DHT11_H_
#define _DHT11_H_
#include <stdint.h>
/** DHT11初始化
* @param dht11_pin GPIO
* @return
*/
void DHT11_Init(uint8_t dht11_pin);
/** 获取DHT11数据
* @param temp_x10 X10
* @param humidity 湿
* @return
*/
int DHT11_StartGet(int *temp_x10, int *humidity);
#endif

@ -0,0 +1,38 @@
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <driver/rmt_rx.h>
#include <driver/rmt_tx.h>
#include <soc/rmt_reg.h>
#include "driver/gpio.h"
#include <esp_log.h>
#include <freertos/queue.h>
#include "esp32/rom/ets_sys.h"
#include "dht11.h"
#define DHT11_GPIO 15 // DHT11引脚定义
const static char *TAG = "DHT11_Demo";
// 温度 湿度变量
int temp = 0,hum = 0;
// 主函数
void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "[APP] APP Is Start!~\r\n");
ESP_LOGI(TAG, "[APP] IDF Version is %d.%d.%d",ESP_IDF_VERSION_MAJOR,ESP_IDF_VERSION_MINOR,ESP_IDF_VERSION_PATCH);
ESP_LOGI(TAG, "[APP] Free memory: %lu bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
DHT11_Init(DHT11_GPIO);
while (1){
if (DHT11_StartGet(&temp, &hum)){
ESP_LOGI(TAG, "temp->%i.%i C hum->%i%%", temp / 10, temp % 10, hum);
}
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPathWin}\\tools\\xtensa-esp-elf\\esp-13.2.0_20230928\\xtensa-esp-elf\\bin\\xtensa-esp32-elf-gcc.exe",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**"
],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
],
"version": 4
}

@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "espidf",
"name": "Launch",
"request": "launch"
}
]
}

@ -0,0 +1,10 @@
{
"C_Cpp.intelliSenseEngine": "default",
"idf.portWin": "COM4",
"idf.flashType": "UART",
"files.associations": {
"nvs_flash.h": "c",
"esp_log.h": "c",
"string.h": "c"
}
}

@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mqtt)

@ -0,0 +1,35 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# _Sample project_
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This is the simplest buildable example. The example is used by command `idf.py create-project`
that copies the project to user specified path and set it's name. For more information follow the [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project)
## How to use example
We encourage the users to use the example as a template for the new projects.
A recommended way is to follow the instructions on a [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project).
## Example folder contents
The project **sample_project** contains one source file in C language [main.c](main/main.c). The file is located in folder [main](main).
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt`
files that provide set of directives and instructions describing the project's source files and targets
(executable, library, or both).
Below is short explanation of remaining files in the project folder.
```
├── CMakeLists.txt
├── main
│   ├── CMakeLists.txt
│   └── main.c
└── README.md This is the file you are currently reading
```
Additionally, the sample project contains Makefile and component.mk files, used for the legacy Make based build system.
They are not used or needed when building with CMake and idf.py.

@ -0,0 +1,2 @@
idf_component_register(SRCS "dht11.c" "main.c" "simple_wifi_sta.c"
INCLUDE_DIRS ".")

@ -0,0 +1,165 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <driver/rmt_rx.h>
#include <driver/rmt_tx.h>
#include <soc/rmt_reg.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp32/rom/ets_sys.h"
#define TAG "DHT11"
uint8_t DHT11_PIN = -1;
//rmt接收通道句柄
static rmt_channel_handle_t rx_chan_handle = NULL;
//数据接收队列
static QueueHandle_t rx_receive_queue = NULL;
// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_symbol_word_t *item, int item_num, int *humidity, int *temp_x10);
//接收完成回调函数
static bool IRAM_ATTR example_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;
QueueHandle_t rx_receive_queue = (QueueHandle_t)user_data;
// send the received RMT symbols to the parser task
xQueueSendFromISR(rx_receive_queue, edata, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
/** DHT11初始化
* @param dht11_pin GPIO
* @return
*/
void DHT11_Init(uint8_t dht11_pin)
{
DHT11_PIN = dht11_pin;
rmt_rx_channel_config_t rx_chan_config = {
.clk_src = RMT_CLK_SRC_APB, // 选择时钟源
.resolution_hz = 1000 * 1000, // 1 MHz 滴答分辨率,即 1 滴答 = 1 µs
.mem_block_symbols = 64, // 内存块大小,即 64 * 4 = 256 字节
.gpio_num = dht11_pin, // GPIO 编号
.flags.invert_in = false, // 不反转输入信号
.flags.with_dma = false, // 不需要 DMA 后端(ESP32S3才有)
};
//创建rmt接收通道
ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_chan_config, &rx_chan_handle));
//新建接收数据队列
rx_receive_queue = xQueueCreate(20, sizeof(rmt_rx_done_event_data_t));
assert(rx_receive_queue);
//注册接收完成回调函数
ESP_LOGI(TAG, "register RX done callback");
rmt_rx_event_callbacks_t cbs = {
.on_recv_done = example_rmt_rx_done_callback,
};
ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(rx_chan_handle, &cbs, rx_receive_queue));
//使能RMT接收通道
ESP_ERROR_CHECK(rmt_enable(rx_chan_handle));
}
// 将RMT读取到的脉冲数据处理为温度和湿度(rmt_symbol_word_t称为RMT符号)
static int parse_items(rmt_symbol_word_t *item, int item_num, int *humidity, int *temp_x10)
{
int i = 0;
unsigned int rh = 0, temp = 0, checksum = 0;
if (item_num < 41){ // 检查是否有足够的脉冲数
//ESP_LOGI(TAG, "item_num < 41 %d",item_num);
return 0;
}
if(item_num > 41)
item++; // 跳过开始信号脉冲
for (i = 0; i < 16; i++, item++) // 提取湿度数据
{
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
rh = (rh << 1) + (duration < 35 ? 0 : 1);
}
for (i = 0; i < 16; i++, item++) // 提取温度数据
{
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
temp = (temp << 1) + (duration < 35 ? 0 : 1);
}
for (i = 0; i < 8; i++, item++){ // 提取校验数据
uint16_t duration = 0;
if(item->level0)
duration = item->duration0;
else
duration = item->duration1;
checksum = (checksum << 1) + (duration < 35 ? 0 : 1);
}
// 检查校验
if ((((temp >> 8) + temp + (rh >> 8) + rh) & 0xFF) != checksum){
ESP_LOGI(TAG, "Checksum failure %4X %4X %2X\n", temp, rh, checksum);
return 0;
}
// 返回数据
rh = rh >> 8;
temp = (temp >> 8) * 10 + (temp & 0xFF);
//判断数据合法性
if(rh <= 100)
*humidity = rh;
if(temp <= 600)
*temp_x10 = temp;
return 1;
}
/** 获取DHT11数据
* @param temp_x10
* @return
*/
int DHT11_StartGet(int *temp_x10, int *humidity)
{
//发送20ms开始信号脉冲启动DHT11单总线
gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DHT11_PIN, 1);
ets_delay_us(1000);
gpio_set_level(DHT11_PIN, 0);
ets_delay_us(20000);
//拉高20us
gpio_set_level(DHT11_PIN, 1);
ets_delay_us(20);
//信号线设置为输入准备接收数据
gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(DHT11_PIN,GPIO_PULLUP_ONLY);
//启动RMT接收器以获取数据
rmt_receive_config_t receive_config = {
.signal_range_min_ns = 100, //最小脉冲宽度(0.1us),信号长度小于这个值,视为干扰
.signal_range_max_ns = 1000*1000, //最大脉冲宽度(1000us),信号长度大于这个值,视为结束信号
};
static rmt_symbol_word_t raw_symbols[128]; //接收缓存
static rmt_rx_done_event_data_t rx_data; //实际接收到的数据
ESP_ERROR_CHECK(rmt_receive(rx_chan_handle, raw_symbols, sizeof(raw_symbols), &receive_config));
// wait for RX done signal
if (xQueueReceive(rx_receive_queue, &rx_data, pdMS_TO_TICKS(1000)) == pdTRUE) {
// parse the receive symbols and print the result
return parse_items(rx_data.received_symbols, rx_data.num_symbols,humidity, temp_x10);
}
return 0;
}

@ -0,0 +1,18 @@
#ifndef _DHT11_H_
#define _DHT11_H_
#include <stdint.h>
/** DHT11初始化
* @param dht11_pin GPIO
* @return
*/
void DHT11_Init(uint8_t dht11_pin);
/** 获取DHT11数据
* @param temp_x10 X10
* @param humidity 湿
* @return
*/
int DHT11_StartGet(int *temp_x10, int *humidity);
#endif

@ -0,0 +1,178 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "mqtt_client.h"
#include "simple_wifi_sta.h"
#include <freertos/queue.h>
#include "esp32/rom/ets_sys.h"
#include "dht11.h"
#include <driver/rmt_rx.h>
#include <driver/rmt_tx.h>
#include <soc/rmt_reg.h>
#include "driver/gpio.h"
#include <string.h>
#include <esp_log.h>
#define DHT11_GPIO 15 // DHT11引脚定义
const static char *TAG1 = "DHT11_Demo";
static const char* TAG = "main";
// 温度 湿度变量
int temp = 0,hum = 0;
#define MQTT_ADDRESS "mqtt://47.242.184.139" //MQTT连接地址
#define MQTT_PORT 1883 //MQTT连接端口号
#define MQTT_CLIENT "mqttx_esp32_01" //Client ID设备唯一大家最好自行改一下
#define MQTT_USERNAME "admin" //MQTT用户名
#define MQTT_PASSWORD "publish452131wW452131wW$" //MQTT密码
#define MQTT_PUBLIC_TOPIC "/test/topic1" //测试用的,推送消息主题
#define MQTT_SUBSCRIBE_TOPIC "/test/topic1" //测试用的,需要订阅的主题
// #define MQTT_SUBSCRIBE_TOPIC "WifiSHT/+/SHT20"
//定义一个事件组用于通知main函数WIFI连接成功
#define WIFI_CONNECT_BIT BIT0
static EventGroupHandle_t s_wifi_ev = NULL;
//MQTT客户端操作句柄
static esp_mqtt_client_handle_t s_mqtt_client = NULL;
//MQTT连接标志
static bool s_is_mqtt_connected = false;
/**
* mqtt
* @param event
* @return
*/
static void aliot_mqtt_event_handler(void* event_handler_arg,
esp_event_base_t event_base,
int32_t event_id,
void* event_data)
{
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
// your_context_t *context = event->context;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED: //连接成功
ESP_LOGI(TAG, "mqtt connected");
s_is_mqtt_connected = true;
//连接成功后,订阅测试主题
esp_mqtt_client_subscribe_single(s_mqtt_client,MQTT_SUBSCRIBE_TOPIC,1);
break;
case MQTT_EVENT_DISCONNECTED: //连接断开
ESP_LOGI(TAG, "mqtt disconnected");
s_is_mqtt_connected = false;
esp_mqtt_client_start(s_mqtt_client);
break;
case MQTT_EVENT_SUBSCRIBED: //收到订阅消息ACK
ESP_LOGI(TAG, " mqtt subscribed ack, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED: //收到解订阅消息ACK
break;
case MQTT_EVENT_PUBLISHED: //收到发布消息ACK
ESP_LOGI(TAG, "mqtt publish ack, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); //收到Pub消息直接打印出来
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
break;
}
}
/** 启动mqtt连接
* @param
* @return
*/
void mqtt_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {0};
mqtt_cfg.broker.address.uri = MQTT_ADDRESS;
mqtt_cfg.broker.address.port = MQTT_PORT;
//Client ID
mqtt_cfg.credentials.client_id = MQTT_CLIENT;
//用户名
mqtt_cfg.credentials.username = MQTT_USERNAME;
//密码
mqtt_cfg.credentials.authentication.password = MQTT_PASSWORD;
ESP_LOGI(TAG,"mqtt connect->clientId:%s,username:%s,password:%s",mqtt_cfg.credentials.client_id,
mqtt_cfg.credentials.username,mqtt_cfg.credentials.authentication.password);
//设置mqtt配置返回mqtt操作句柄
s_mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
//注册mqtt事件回调函数
esp_mqtt_client_register_event(s_mqtt_client, ESP_EVENT_ANY_ID, aliot_mqtt_event_handler, s_mqtt_client);
//启动mqtt连接
esp_mqtt_client_start(s_mqtt_client);
}
/** wifi事件通知
* @param
* @return
*/
void wifi_event_handler(WIFI_EV_e ev)
{
if(ev == WIFI_CONNECTED)
{
xEventGroupSetBits(s_wifi_ev,WIFI_CONNECT_BIT);
}
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
//NVS出现错误执行擦除
ESP_ERROR_CHECK(nvs_flash_erase());
//重新尝试初始化
ESP_ERROR_CHECK(nvs_flash_init());
}
s_wifi_ev = xEventGroupCreate();
EventBits_t ev = 0;
//初始化WIFI传入回调函数用于通知连接成功事件
wifi_sta_init(wifi_event_handler);
//一直监听WIFI连接事件直到WiFi连接成功后才启动MQTT连接
ev = xEventGroupWaitBits(s_wifi_ev,WIFI_CONNECT_BIT,pdTRUE,pdFALSE,portMAX_DELAY);
if(ev & WIFI_CONNECT_BIT)
{
mqtt_start();
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
DHT11_Init(DHT11_GPIO);
static char mqtt_pub_buff[64];
while(1)
{
if (DHT11_StartGet(&temp, &hum)){
ESP_LOGI(TAG1, "temp->%i.%i C hum->%i%%", temp / 10, temp % 10, hum);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
int count = 0;
//延时2秒发布一条消息到/test/topic1主题
if(s_is_mqtt_connected)
{
//snprintf(mqtt_pub_buff,64,"{\"count\":\"%d\"}",count);
snprintf(mqtt_pub_buff,64,"{%i.%i %i}",temp / 10, temp % 10, hum);
esp_mqtt_client_publish(s_mqtt_client, MQTT_PUBLIC_TOPIC,
mqtt_pub_buff, strlen(mqtt_pub_buff),1, 0);
count++;
}
vTaskDelay(pdMS_TO_TICKS(9000));
}
return;
}
// TOPIC=WifiSHT/7C87CE9F5CBF/SHT20
// DATA=52.5 28.8

@ -0,0 +1,105 @@
#include "simple_wifi_sta.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
//需要把这两个修改成你家WIFI测试是否连接成功
#define DEFAULT_WIFI_SSID "rehome"
#define DEFAULT_WIFI_PASSWORD "Ruihong123"
static const char *TAG = "wifi";
//事件通知回调函数
static wifi_event_cb wifi_cb = NULL;
/** 事件回调函数
* @param arg
* @param event_base
* @param event_id ID
* @param event_data
* @return
*/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
if(event_base == WIFI_EVENT)
{
switch (event_id)
{
case WIFI_EVENT_STA_START: //WIFI以STA模式启动后触发此事件
esp_wifi_connect(); //启动WIFI连接
break;
case WIFI_EVENT_STA_CONNECTED: //WIFI连上路由器后触发此事件
ESP_LOGI(TAG, "connected to AP");
break;
case WIFI_EVENT_STA_DISCONNECTED: //WIFI从路由器断开连接后触发此事件
esp_wifi_connect(); //继续重连
ESP_LOGI(TAG,"connect to the AP fail,retry now");
break;
default:
break;
}
}
if(event_base == IP_EVENT) //IP相关事件
{
switch(event_id)
{
case IP_EVENT_STA_GOT_IP: //只有获取到路由器分配的IP才认为是连上了路由器
if(wifi_cb)
wifi_cb(WIFI_CONNECTED);
ESP_LOGI(TAG,"get ip address");
break;
}
}
}
//WIFI STA初始化
esp_err_t wifi_sta_init(wifi_event_cb f)
{
ESP_ERROR_CHECK(esp_netif_init()); //用于初始化tcpip协议栈
ESP_ERROR_CHECK(esp_event_loop_create_default()); //创建一个默认系统事件调度循环,之后可以注册回调函数来处理系统的一些事件
esp_netif_create_default_wifi_sta(); //使用默认配置创建STA对象
//初始化WIFI
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//注册事件
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL));
//WIFI配置
wifi_config_t wifi_config =
{
.sta =
{
.ssid = DEFAULT_WIFI_SSID, //WIFI的SSID
.password = DEFAULT_WIFI_PASSWORD, //WIFI密码
.threshold.authmode = WIFI_AUTH_WPA2_PSK, //加密方式
.pmf_cfg =
{
.capable = true,
.required = false
},
},
};
wifi_cb = f;
//启动WIFI
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); //设置工作模式为STA
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); //设置wifi配置
ESP_ERROR_CHECK(esp_wifi_start() ); //启动WIFI
ESP_LOGI(TAG, "wifi_init_sta finished.");
return ESP_OK;
}

@ -0,0 +1,19 @@
#ifndef _WIFI_MANAGER_H_
#define _WIFI_MANAGER_H_
#include "esp_err.h"
typedef enum
{
WIFI_DISCONNECTED, //wifi断开
WIFI_CONNECTED, //wifi已连接
}WIFI_EV_e;
typedef void(*wifi_event_cb)(WIFI_EV_e);
//WIFI STA初始化
esp_err_t wifi_sta_init(wifi_event_cb f);
#endif

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save