mirror of
https://github.com/DuRuofu/ESP32-Guide.git
synced 2026-10-02 22:22:53 +08:00
code: 添加现有程序
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
*build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# 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(blink)
|
||||
@@ -0,0 +1,77 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# Blink Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to blink a LED using GPIO or using the [led_strip](https://components.espressif.com/component/espressif/led_strip) component for the addressable LED, i.e. [WS2812](https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf).
|
||||
|
||||
The `led_strip` is installed via [component manager](main/idf_component.yml).
|
||||
|
||||
## How to Use Example
|
||||
|
||||
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with Espressif SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
||||
* A USB cable for Power supply and programming
|
||||
|
||||
Some development boards use an addressable LED instead of a regular one. These development boards include:
|
||||
|
||||
| Board | LED type | Pin |
|
||||
| -------------------- | -------------------- | -------------------- |
|
||||
| ESP32-C3-DevKitC-1 | Addressable | GPIO8 |
|
||||
| ESP32-C3-DevKitM-1 | Addressable | GPIO8 |
|
||||
| ESP32-S2-DevKitM-1 | Addressable | GPIO18 |
|
||||
| ESP32-S2-Saola-1 | Addressable | GPIO18 |
|
||||
| ESP32-S3-DevKitC-1 | Addressable | GPIO48 |
|
||||
|
||||
See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it.
|
||||
|
||||
### Configure the Project
|
||||
|
||||
Open the project configuration menu (`idf.py menuconfig`).
|
||||
|
||||
In the `Example Configuration` menu:
|
||||
|
||||
* Select the LED type in the `Blink LED type` option.
|
||||
* Use `GPIO` for regular LED blink.
|
||||
* Set the GPIO number used for the signal in the `Blink GPIO number` option.
|
||||
* Set the blinking period in the `Blink period in ms` option.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
As you run the example, you will see the LED blinking, according to the previously defined period. For the addressable LED, you can also change the LED color by setting the `led_strip_set_pixel(led_strip, 0, 16, 16, 16);` (LED Strip, Pixel Number, Red, Green, Blue) with values from 0 to 255 in the [source file](main/blink_example_main.c).
|
||||
|
||||
```text
|
||||
I (315) example: Example configured to blink addressable LED!
|
||||
I (325) example: Turning the LED OFF!
|
||||
I (1325) example: Turning the LED ON!
|
||||
I (2325) example: Turning the LED OFF!
|
||||
I (3325) example: Turning the LED ON!
|
||||
I (4325) example: Turning the LED OFF!
|
||||
I (5325) example: Turning the LED ON!
|
||||
I (6325) example: Turning the LED OFF!
|
||||
I (7325) example: Turning the LED ON!
|
||||
I (8325) example: Turning the LED OFF!
|
||||
```
|
||||
|
||||
Note: The color order could be different according to the LED model.
|
||||
|
||||
The pixel number indicates the pixel position in the LED strip. For a single LED, use 0.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* If the LED isn't blinking, check the GPIO or the LED type selection in the `Example Configuration` menu.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "blink_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Blink Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "led_strip.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
|
||||
or you can edit the following line and set a number here.
|
||||
*/
|
||||
#define BLINK_GPIO CONFIG_BLINK_GPIO
|
||||
|
||||
static uint8_t s_led_state = 0;
|
||||
|
||||
#ifdef CONFIG_BLINK_LED_RMT
|
||||
|
||||
static led_strip_handle_t led_strip;
|
||||
|
||||
static void blink_led(void)
|
||||
{
|
||||
/* If the addressable LED is enabled */
|
||||
if (s_led_state) {
|
||||
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
|
||||
led_strip_set_pixel(led_strip, 0, 16, 16, 16);
|
||||
/* Refresh the strip to send data */
|
||||
led_strip_refresh(led_strip);
|
||||
} else {
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_led(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Example configured to blink addressable LED!");
|
||||
/* LED strip initialization with the GPIO and pixels number*/
|
||||
led_strip_config_t strip_config = {
|
||||
.strip_gpio_num = BLINK_GPIO,
|
||||
.max_leds = 1, // at least one LED on board
|
||||
};
|
||||
led_strip_rmt_config_t rmt_config = {
|
||||
.resolution_hz = 10 * 1000 * 1000, // 10MHz
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
}
|
||||
|
||||
#elif CONFIG_BLINK_LED_GPIO
|
||||
|
||||
static void blink_led(void)
|
||||
{
|
||||
/* Set the GPIO level according to the state (LOW or HIGH)*/
|
||||
gpio_set_level(BLINK_GPIO, s_led_state);
|
||||
}
|
||||
|
||||
static void configure_led(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
|
||||
gpio_reset_pin(BLINK_GPIO);
|
||||
/* Set the GPIO as a push/pull output */
|
||||
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
/* Configure the peripheral according to the LED type */
|
||||
configure_led();
|
||||
|
||||
while (1) {
|
||||
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
|
||||
blink_led();
|
||||
/* Toggle the LED state */
|
||||
s_led_state = !s_led_state;
|
||||
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
dependencies:
|
||||
espressif/led_strip: "^2.0.0"
|
||||
@@ -0,0 +1,17 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
def test_blink(dut: IdfDut) -> None:
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut.app.binary_path, 'blink.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
logging.info('blink_bin_size : {}KB'.format(bin_size // 1024))
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
void Task_1(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "Task_1");
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void Task_2(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "Task_2");
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UBaseType_t taskPriority_1 = 0;
|
||||
UBaseType_t taskPriority_2 = 0;
|
||||
TaskHandle_t taskHandle_1 = NULL;
|
||||
TaskHandle_t taskHandle_2 = NULL;
|
||||
|
||||
xTaskCreate(Task_1, "Task_1", 2048, NULL, 12, &taskHandle_1);
|
||||
taskPriority_1 = uxTaskPriorityGet(taskHandle_1);
|
||||
ESP_LOGI(TAG, "Task_1 优先级:%d", taskPriority_1);
|
||||
|
||||
xTaskCreate(Task_2, "Task_1", 2048, NULL, 12, &taskHandle_2);
|
||||
taskPriority_2 = uxTaskPriorityGet(taskHandle_2);
|
||||
ESP_LOGI(TAG, "Task_1 优先级:%d", taskPriority_2);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
void Task_1(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "Task_1");
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void Task_2(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "Task_2");
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
TaskHandle_t taskHandle_1 = NULL;
|
||||
TaskHandle_t taskHandle_2 = NULL;
|
||||
|
||||
xTaskCreate(Task_1, "Task_1", 2048, NULL, 12, &taskHandle_1);
|
||||
xTaskCreate(Task_2, "Task_1", 2048, NULL, 12, &taskHandle_2);
|
||||
|
||||
|
||||
// 输出任务列表
|
||||
static char cBuffer[512]={0};
|
||||
vTaskList(cBuffer);
|
||||
ESP_LOGI(TAG, "任务列表:\n%s", cBuffer);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) 5.3.2 Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// 任务函数
|
||||
void myTask(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "myTask");
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 创建一个 FreeRTOS 任务
|
||||
// 参数说明:
|
||||
// 1. 任务入口函数:myTask
|
||||
// 2. 任务名称:"myTask",用于调试时标识任务
|
||||
// 3. 任务堆栈大小:2048 字节(适当分配以避免栈溢出)
|
||||
// 4. 任务参数:NULL(未传递参数)
|
||||
// 5. 任务优先级:1(优先级较低,空闲任务优先级为 0)
|
||||
// 6. 任务句柄:NULL(不需要保存任务句柄)
|
||||
xTaskCreate(myTask, "myTask", 2048, NULL, 1, NULL);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Int;
|
||||
int Array[3];
|
||||
} MyStruct;
|
||||
|
||||
// 任务函数1:接收整型参数
|
||||
void Task_1(void *pvParameters)
|
||||
{
|
||||
int *pInt = (int *)pvParameters;
|
||||
ESP_LOGI(TAG, "取得整型参数为:%d", *pInt);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// 任务函数2:接收数组参数
|
||||
void Task_2(void *pvParameters)
|
||||
{
|
||||
int *pArray = (int *)pvParameters;
|
||||
ESP_LOGI(TAG, "取得数组参数为:%d %d %d", *pArray, *(pArray + 1), *(pArray + 2));
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// 任务函数3:接收结构体参数
|
||||
void Task_3(void *pvParameters)
|
||||
{
|
||||
MyStruct *pStruct = (MyStruct *)pvParameters;
|
||||
ESP_LOGI(TAG, "取得结构体参数为:%d %d %d %d", pStruct->Int, pStruct->Array[0], pStruct->Array[1], pStruct->Array[2]);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// 任务函数4:接收字符串参数
|
||||
void Task_4(void *pvParameters)
|
||||
{
|
||||
char *pChar = (char *)pvParameters;
|
||||
ESP_LOGI(TAG, "取得字符串参数为:%s", pChar);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
int Parameters_1 = 1;
|
||||
int Parameters_2[3] = {1, 2, 3};
|
||||
MyStruct Parameters_3 = {1, {1, 2, 3}};
|
||||
static const char *Parameters_4 = "Hello World!";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 传递整形参数
|
||||
xTaskCreate(Task_1, "Task_1", 2048, (void *)&Parameters_1, 1, NULL);
|
||||
|
||||
// 传递数组参数
|
||||
xTaskCreate(Task_2, "Task_2", 2048, (void *)&Parameters_2, 1, NULL);
|
||||
|
||||
// 传递结构体参数
|
||||
xTaskCreate(Task_3, "Task_3", 3048, (void *)&Parameters_3, 1, NULL);
|
||||
|
||||
// 传递字符串参数(注意这里没有取地址符号&)
|
||||
xTaskCreate(Task_4, "Task_4", 3048, (void *)Parameters_4, 1, NULL);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// 任务函数
|
||||
void myTask(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "myTask");
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 任务句柄
|
||||
TaskHandle_t taskHandle = NULL;
|
||||
// 创建一个 FreeRTOS 任务
|
||||
xTaskCreate(myTask, "myTask", 2048, NULL, 1, &taskHandle);
|
||||
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
|
||||
// 删除任务
|
||||
if (taskHandle != NULL)
|
||||
{
|
||||
vTaskDelete(taskHandle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// 任务函数
|
||||
void myTask(void *pvParameters)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "myTask:1");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "myTask:2");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "myTask:3");
|
||||
|
||||
// 删除任务(如果传递 NULL,则删除当前任务)
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 任务句柄
|
||||
TaskHandle_t taskHandle = NULL;
|
||||
// 创建一个 FreeRTOS 任务
|
||||
xTaskCreate(myTask, "myTask", 2048, NULL, 1, &taskHandle);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
@@ -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(main)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// 定时器回调
|
||||
void TimerCallback_1(TimerHandle_t xTimer)
|
||||
{
|
||||
// 取到定时器的名字
|
||||
const char *timerName = pcTimerGetName(xTimer);
|
||||
// 取得定时器的ID
|
||||
void *timerID = pvTimerGetTimerID(xTimer);
|
||||
ESP_LOGI(TAG, "定时器名称:%s,定时器id:%d,定时器回调函数执行", timerName, (int)timerID);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 创建定时器句柄
|
||||
TimerHandle_t xTimer_1;
|
||||
TimerHandle_t xTimer_2;
|
||||
xTimer_1 = xTimerCreate("timer1", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, TimerCallback_1);
|
||||
xTimer_2 = xTimerCreate("timer2", pdMS_TO_TICKS(2000), pdTRUE, (void *)1, TimerCallback_1);
|
||||
|
||||
xTimerStart(xTimer_1, 0); // 启动定时器
|
||||
xTimerStart(xTimer_2, 0); // 启动定时器
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
//停止定时器
|
||||
xTimerStop(xTimer_1, 0);
|
||||
xTimerStop(xTimer_2, 0);
|
||||
}
|
||||
|
||||
|
||||
// 其他常用函数
|
||||
// xTimerChangePeriod():修改定时器周期
|
||||
// xTimerReset():重置定时器
|
||||
// xTimerDelete():删除定时器
|
||||
@@ -0,0 +1,7 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) 5.3.2 Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(adc_continuous)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "adc_continuous.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_adc/adc_continuous.h"
|
||||
|
||||
#define _EXAMPLE_ADC_UNIT_STR(unit) #unit
|
||||
// C预处理器的字符串化操作符 #,它可以将宏参数转换为字符串常量。如果传递 ADC_UNIT 给 _EXAMPLE_ADC_UNIT_STR,它会生成字符串 "ADC_UNIT"。
|
||||
#define EXAMPLE_ADC_UNIT_STR(unit) _EXAMPLE_ADC_UNIT_STR(unit)
|
||||
// 宏嵌套
|
||||
|
||||
// 用于从 adc_digi_output_data_t 结构体中提取通道号和数据值。
|
||||
#define EXAMPLE_ADC_GET_CHANNEL(p_data) ((p_data)->type1.channel)
|
||||
#define EXAMPLE_ADC_GET_DATA(p_data) ((p_data)->type1.data)
|
||||
|
||||
|
||||
#define ADC_UNIT ADC_UNIT_1
|
||||
|
||||
|
||||
// ADC通道
|
||||
//static adc_channel_t channel[2] = {ADC_CHANNEL_6, ADC_CHANNEL_7};
|
||||
static adc_channel_t channel[1] = {ADC_CHANNEL_6};
|
||||
|
||||
|
||||
static TaskHandle_t s_task_handle;
|
||||
static const char *TAG = "ADC_CONTINUOUS";
|
||||
|
||||
// ADC连续模式的事件回调(一个转换帧完成时)
|
||||
static bool IRAM_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
|
||||
{
|
||||
BaseType_t mustYield = pdFALSE;
|
||||
//Notify that ADC continuous driver has done enough number of conversions
|
||||
//vTaskNotifyGiveFromISR 是 FreeRTOS 提供的一个函数,它允许从中断服务例程(ISR)安全地向任务发送通知
|
||||
vTaskNotifyGiveFromISR(s_task_handle, &mustYield);
|
||||
|
||||
return (mustYield == pdTRUE);
|
||||
}
|
||||
|
||||
// adc初始化
|
||||
static void continuous_adc_init(adc_channel_t *channel, uint8_t channel_num, adc_continuous_handle_t *out_handle)
|
||||
{
|
||||
// 创建一个ADC连续模式的句柄
|
||||
adc_continuous_handle_t handle = NULL;
|
||||
|
||||
// 配置ADC连续模式的参数
|
||||
adc_continuous_handle_cfg_t adc_config = {
|
||||
.max_store_buf_size = 1024, // 最大存储缓冲区大小
|
||||
.conv_frame_size = 256, // 转换帧大小
|
||||
};
|
||||
ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config, &handle));
|
||||
|
||||
// ADC IO
|
||||
adc_continuous_config_t dig_cfg = {
|
||||
.sample_freq_hz = 20 * 1000, // 采样频率
|
||||
.conv_mode = ADC_CONV_SINGLE_UNIT_1, // 转换模式
|
||||
.format = ADC_DIGI_OUTPUT_FORMAT_TYPE1, // 输出格式
|
||||
};
|
||||
|
||||
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
|
||||
dig_cfg.pattern_num = channel_num; // 通道数量
|
||||
for (int i = 0; i < channel_num; i++) {
|
||||
adc_pattern[i].atten = ADC_ATTEN_DB_11; // ADC 衰减
|
||||
adc_pattern[i].channel = channel[i] & 0x7; // 通道
|
||||
adc_pattern[i].unit = ADC_UNIT; // ADC单元
|
||||
adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; // 位宽
|
||||
|
||||
// 打印配置信息
|
||||
// - PRIx8 是一个预处理宏,定义在 C 语言的标准库头文件 <inttypes.h> 中。它用于以可移植的方式格式化输出 uint8_t 类型的数据为十六进制形式。
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].atten is :%"PRIx8, i, adc_pattern[i].atten);
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].channel is :%"PRIx8, i, adc_pattern[i].channel);
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].unit is :%"PRIx8, i, adc_pattern[i].unit);
|
||||
}
|
||||
|
||||
// 要使用的 ADC 通道的配置列表
|
||||
dig_cfg.adc_pattern = adc_pattern;
|
||||
ESP_ERROR_CHECK(adc_continuous_config(handle, &dig_cfg));
|
||||
|
||||
*out_handle = handle;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t ret; // 返回状态
|
||||
uint32_t ret_num = 0; // 转换完成的数据数量
|
||||
// 定义接收数组
|
||||
uint8_t result[256] = {0};
|
||||
// 初始化数组,填充为0xcc
|
||||
memset(result, 0xcc, 256);
|
||||
|
||||
//获取app_mian任务的句柄。
|
||||
s_task_handle = xTaskGetCurrentTaskHandle();
|
||||
|
||||
// 初始化ADC
|
||||
adc_continuous_handle_t handle = NULL;
|
||||
continuous_adc_init(channel, sizeof(channel) / sizeof(adc_channel_t), &handle);
|
||||
|
||||
// 事件回调
|
||||
adc_continuous_evt_cbs_t cbs = {
|
||||
// 当一个转换帧完成时,触发此事件:s_conv_done_cb
|
||||
.on_conv_done = s_conv_done_cb,
|
||||
};
|
||||
|
||||
// 注册事件回调
|
||||
ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(handle, &cbs, NULL));
|
||||
// 启动ADC连续模式
|
||||
ESP_ERROR_CHECK(adc_continuous_start(handle));
|
||||
|
||||
while (1) {
|
||||
|
||||
/**
|
||||
* This is to show you the way to use the ADC continuous mode driver event callback.
|
||||
* This `ulTaskNotifyTake` will block when the data processing in the task is fast.
|
||||
* However in this example, the data processing (print) is slow, so you barely block here.
|
||||
*
|
||||
* Without using this event callback (to notify this task), you can still just call
|
||||
* `adc_continuous_read()` here in a loop, with/without a certain block timeout.
|
||||
*/
|
||||
// ulTaskNotifyTake() 等待通知
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
// 生成字符串
|
||||
char unit[] = EXAMPLE_ADC_UNIT_STR(ADC_UNIT);
|
||||
|
||||
while (1) {
|
||||
// 读取ADC数据
|
||||
ret = adc_continuous_read(handle, result, 256, &ret_num, 0);
|
||||
// 读取成功
|
||||
if (ret == ESP_OK) {
|
||||
// 显示读取操作的返回状态和实际读取到的数据字节数
|
||||
ESP_LOGI("TASK", "ret is %x, ret_num is %"PRIu32" bytes", ret, ret_num);
|
||||
// 循环遍历读取到的数据,解析每个ADC数据项,并打印出来
|
||||
// - 循环以 SOC_ADC_DIGI_RESULT_BYTES 为步长迭代,这个常量定义了每个ADC数据项的字节大小。
|
||||
// - adc_digi_output_data_t 是一个结构体类型,用于解析ADC数据项。
|
||||
// - EXAMPLE_ADC_GET_CHANNEL(p) 和 EXAMPLE_ADC_GET_DATA(p) 是宏,用于从 adc_digi_output_data_t 结构体中提取通道号和数据值。
|
||||
for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) {
|
||||
adc_digi_output_data_t *p = (adc_digi_output_data_t*)&result[i];
|
||||
uint32_t chan_num = EXAMPLE_ADC_GET_CHANNEL(p);
|
||||
uint32_t data = EXAMPLE_ADC_GET_DATA(p);
|
||||
/*检查通道编号验证,如果通道编号超过最大通道,则数据无效 */
|
||||
// - PRIu32 是 C 语言标准库中的宏,它用于以可移植的方式格式化输出 uint32_t 类型的数据。
|
||||
if (chan_num < SOC_ADC_CHANNEL_NUM(ADC_UNIT)) {
|
||||
ESP_LOGI(TAG, "Unit: %s, Channel: %"PRIu32", Value: %"PRIu32, unit, chan_num, data);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Invalid data [%s_%"PRIu32"_%"PRIu32"]", unit, chan_num, data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Because printing is slow, so every time you call `ulTaskNotifyTake`, it will immediately return.
|
||||
* To avoid a task watchdog timeout, add a delay here. When you replace the way you process the data,
|
||||
* usually you don't need this delay (as this task will block for a while).
|
||||
*/
|
||||
vTaskDelay(1);
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
//We try to read `EXAMPLE_READ_LEN` until API returns timeout, which means there's no available data
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 停止ADC连续模式
|
||||
ESP_ERROR_CHECK(adc_continuous_stop(handle));
|
||||
ESP_ERROR_CHECK(adc_continuous_deinit(handle));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(adc_oneshot)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "adc_oneshot.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_adc/adc_oneshot.h"
|
||||
|
||||
#define EXAMPLE_ADC1_CHAN0 ADC_CHANNEL_6 // 根据您的硬件配置选择合适的通道
|
||||
#define EXAMPLE_ADC1_CHAN1 ADC_CHANNEL_7 // 根据您的硬件配置选择合适的通道
|
||||
|
||||
static const char* TAG = "ADC_ONESHOT_EXAMPLE";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
adc_oneshot_unit_handle_t adc1_handle;
|
||||
adc_oneshot_unit_init_cfg_t init_config1 = {
|
||||
.unit_id = ADC_UNIT_1,
|
||||
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||
};
|
||||
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
|
||||
|
||||
adc_oneshot_chan_cfg_t config = {
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
.atten = ADC_ATTEN_DB_11, // 设置适当的衰减以匹配您的输入电压范围
|
||||
};
|
||||
|
||||
// 配置两个通道
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN0, &config));
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN1, &config));
|
||||
|
||||
int adc_raw[2];
|
||||
|
||||
// 对每个通道进行单次转换并读取结果
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw[0]));
|
||||
ESP_LOGI(TAG, "ADC1 Channel[%d] Raw Data: %d", EXAMPLE_ADC1_CHAN0, adc_raw[0]);
|
||||
|
||||
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN1, &adc_raw[1]));
|
||||
ESP_LOGI(TAG, "ADC1 Channel[%d] Raw Data: %d", EXAMPLE_ADC1_CHAN1, adc_raw[1]);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // 等待1秒再次读取
|
||||
}
|
||||
|
||||
// 回收资源
|
||||
ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(dac_cosine)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "dac_cosine.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/dac_cosine.h"
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
dac_cosine_handle_t chan0_handle;
|
||||
dac_cosine_handle_t chan1_handle;
|
||||
/* Normally two channels can only be configured to one frequency
|
||||
* But we can set force_set_freq bit to force update the frequency
|
||||
* The example here will produce cosine wave at 8 KHz on both channels */
|
||||
dac_cosine_config_t cos0_cfg = {
|
||||
.chan_id = DAC_CHAN_0,
|
||||
.freq_hz = 1000, // It will be covered by 8000 in the latter configuration
|
||||
.clk_src = DAC_COSINE_CLK_SRC_DEFAULT,
|
||||
.offset = 0,
|
||||
.phase = DAC_COSINE_PHASE_0,
|
||||
.atten = DAC_COSINE_ATTEN_DEFAULT,
|
||||
.flags.force_set_freq = false,
|
||||
};
|
||||
dac_cosine_config_t cos1_cfg = {
|
||||
.chan_id = DAC_CHAN_1,
|
||||
.freq_hz = 8000,
|
||||
.clk_src = DAC_COSINE_CLK_SRC_DEFAULT,
|
||||
.offset = 0,
|
||||
.phase = DAC_COSINE_PHASE_180,
|
||||
.atten = DAC_COSINE_ATTEN_DB_6,
|
||||
.flags.force_set_freq = true, // set true will allow to overwrite the frequency that set before
|
||||
};
|
||||
ESP_ERROR_CHECK(dac_cosine_new_channel(&cos0_cfg, &chan0_handle));
|
||||
ESP_ERROR_CHECK(dac_cosine_new_channel(&cos1_cfg, &chan1_handle));
|
||||
ESP_ERROR_CHECK(dac_cosine_start(chan0_handle));
|
||||
ESP_ERROR_CHECK(dac_cosine_start(chan1_handle));
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(dac_oneshot)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "dac_oneshot.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/dac_oneshot.h"
|
||||
//#include "esp_check.h"
|
||||
|
||||
static void dac_output_task(void *args)
|
||||
{
|
||||
dac_oneshot_handle_t handle = (dac_oneshot_handle_t)args;
|
||||
uint32_t val = 0;
|
||||
while (1) {
|
||||
/* Set the voltage every 100 ms */
|
||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(handle, val));
|
||||
val += 10;
|
||||
val %= 250;
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* DAC oneshot init */
|
||||
dac_oneshot_handle_t chan0_handle;
|
||||
dac_oneshot_config_t chan0_cfg = {
|
||||
.chan_id = DAC_CHAN_0,
|
||||
};
|
||||
ESP_ERROR_CHECK(dac_oneshot_new_channel(&chan0_cfg, &chan0_handle));
|
||||
|
||||
dac_oneshot_handle_t chan1_handle;
|
||||
dac_oneshot_config_t chan1_cfg = {
|
||||
.chan_id = DAC_CHAN_1,
|
||||
};
|
||||
ESP_ERROR_CHECK(dac_oneshot_new_channel(&chan1_cfg, &chan1_handle));
|
||||
|
||||
/* DAC oneshot outputting threads */
|
||||
xTaskCreate(dac_output_task, "dac_chan0_output_task", 4096, chan0_handle, 5, NULL);
|
||||
vTaskDelay(pdMS_TO_TICKS(500)); // To differential the output of two channels
|
||||
xTaskCreate(dac_output_task, "dac_chan1_output_task", 4096, chan1_handle, 5, NULL);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(gpio)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "gpio.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#define LED_GPIO GPIO_NUM_2
|
||||
#define BUTTON_GPIO GPIO_NUM_0
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 初始化LED GPIO为输出模式
|
||||
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
|
||||
|
||||
// 初始化按钮GPIO为输入模式
|
||||
gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY);
|
||||
|
||||
while (1) {
|
||||
// 读取按钮状态
|
||||
int button_state = gpio_get_level(BUTTON_GPIO);
|
||||
|
||||
// 如果按钮被按下(逻辑低电平),点亮LED
|
||||
if(button_state == 0) {
|
||||
gpio_set_level(LED_GPIO, 1);
|
||||
} else {
|
||||
gpio_set_level(LED_GPIO, 0);
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(gpio_exit)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "gpio_exit.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#define LED_GPIO GPIO_NUM_2
|
||||
#define BUTTON_GPIO GPIO_NUM_0
|
||||
|
||||
// 声明一个用于处理GPIO中断的函数
|
||||
static void IRAM_ATTR gpio_isr_handler(void* arg) {
|
||||
// 读取按钮状态并设置LED
|
||||
int button_state = gpio_get_level(BUTTON_GPIO);
|
||||
gpio_set_level(LED_GPIO, button_state == 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
// 初始化LED GPIO为输出模式
|
||||
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
|
||||
|
||||
// 初始化按钮GPIO为输入模式,并设置为上拉
|
||||
gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY);
|
||||
|
||||
// 安装GPIO服务
|
||||
gpio_install_isr_service(0);
|
||||
// 配置GPIO中断类型,并注册中断服务函数
|
||||
gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_ANYEDGE);
|
||||
gpio_isr_handler_add(BUTTON_GPIO, gpio_isr_handler, NULL);
|
||||
|
||||
while (1) {
|
||||
// 在中断模式下,主循环可以执行其他任务或进入睡眠状态
|
||||
vTaskDelay(portMAX_DELAY); // 使用portMAX_DELAY使任务永久挂起,直到中断唤醒
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(gptimer)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "gptimer.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,196 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "gptimer";
|
||||
|
||||
typedef struct {
|
||||
uint64_t event_count;
|
||||
} example_queue_element_t;
|
||||
|
||||
// 定时器警报事件的回调函数(案例1)
|
||||
// 三个参数:定时器句柄 timer、事件数据指针 edata 和用户数据指针 user_data。
|
||||
static bool IRAM_ATTR example_timer_on_alarm_cb_v1(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
||||
{
|
||||
BaseType_t high_task_awoken = pdFALSE;
|
||||
QueueHandle_t queue = (QueueHandle_t)user_data;
|
||||
// 立即停止计时器
|
||||
gptimer_stop(timer);
|
||||
// 从事件数据中获取计数值,并将其存储在 example_queue_element_t 结构体变量 ele 的 event_count 字段中。
|
||||
example_queue_element_t ele = {
|
||||
.event_count = edata->count_value
|
||||
};
|
||||
//使用 xQueueSendFromISR() 函数将 ele 变量发送到队列中
|
||||
xQueueSendFromISR(queue, &ele, &high_task_awoken);
|
||||
// return whether we need to yield at the end of ISR
|
||||
return (high_task_awoken == pdTRUE);
|
||||
}
|
||||
|
||||
// 定时器警报事件的回调函数(案例2)
|
||||
static bool IRAM_ATTR example_timer_on_alarm_cb_v2(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
||||
{
|
||||
BaseType_t high_task_awoken = pdFALSE;
|
||||
QueueHandle_t queue = (QueueHandle_t)user_data;
|
||||
// Retrieve count value and send to queue
|
||||
example_queue_element_t ele = {
|
||||
.event_count = edata->count_value
|
||||
};
|
||||
xQueueSendFromISR(queue, &ele, &high_task_awoken);
|
||||
// return whether we need to yield at the end of ISR
|
||||
return (high_task_awoken == pdTRUE);
|
||||
}
|
||||
|
||||
// 定时器警报事件的回调函数(案例3:动态更新报警值)
|
||||
static bool IRAM_ATTR example_timer_on_alarm_cb_v3(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
||||
{
|
||||
BaseType_t high_task_awoken = pdFALSE;
|
||||
QueueHandle_t queue = (QueueHandle_t)user_data;
|
||||
// Retrieve count value and send to queue
|
||||
example_queue_element_t ele = {
|
||||
.event_count = edata->count_value
|
||||
};
|
||||
xQueueSendFromISR(queue, &ele, &high_task_awoken);
|
||||
// reconfigure alarm value
|
||||
gptimer_alarm_config_t alarm_config = {
|
||||
.alarm_count = edata->alarm_value + 1000000, // alarm in next 1s
|
||||
};
|
||||
gptimer_set_alarm_action(timer, &alarm_config);
|
||||
// return whether we need to yield at the end of ISR
|
||||
return (high_task_awoken == pdTRUE);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 定义一个 example_queue_element_t 类型的变量 ele
|
||||
example_queue_element_t ele;
|
||||
//创建了一个长度为 10,每个元素大小为 example_queue_element_t 类型的队列,并将其赋值给 queue 变量。
|
||||
QueueHandle_t queue = xQueueCreate(10, sizeof(example_queue_element_t));
|
||||
if (!queue) {
|
||||
ESP_LOGE(TAG, "创建队列失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化定时器
|
||||
ESP_LOGW(TAG, "创建分辨率为 1 MHz 的通用定时器句柄");
|
||||
gptimer_handle_t gptimer = NULL;
|
||||
gptimer_config_t timer_config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = 1000000, // 1MHz, 1 tick=1us
|
||||
};
|
||||
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
||||
|
||||
// 注册定时器事件回调函数(警报事件的回调函数)
|
||||
gptimer_event_callbacks_t cbs = {
|
||||
.on_alarm = example_timer_on_alarm_cb_v1,
|
||||
};
|
||||
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
|
||||
|
||||
// 使能定时器
|
||||
ESP_LOGI(TAG, "Enable timer");
|
||||
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||
|
||||
// 设置定时器的周期为 1s(触发警报事件的目标计数值)
|
||||
ESP_LOGI(TAG, "Start timer, stop it at alarm event");
|
||||
gptimer_alarm_config_t alarm_config1 = {
|
||||
.alarm_count = 1000000, // period = 1s
|
||||
};
|
||||
// 设置定时器的报警事件
|
||||
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config1));
|
||||
// 启动定时器
|
||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||
|
||||
// 等待定时器报警事件(从队列中接收数据,接收到的数据将会存储在 &ele 中)
|
||||
if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) {
|
||||
ESP_LOGI(TAG, "Timer stopped, count=%llu", ele.event_count);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Missed one count event");
|
||||
}
|
||||
|
||||
// 设置定时器的计数值(异步更新)
|
||||
ESP_LOGI(TAG, "Set count value");
|
||||
ESP_ERROR_CHECK(gptimer_set_raw_count(gptimer, 100));
|
||||
ESP_LOGI(TAG, "Get count value");
|
||||
|
||||
// 获取定时器的计数值
|
||||
uint64_t count;
|
||||
ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &count));
|
||||
ESP_LOGI(TAG, "Timer count value=%llu", count);
|
||||
|
||||
//--------------------------------------------------------------------//
|
||||
ESP_LOGW(TAG, "案例1结束,案例2开始");
|
||||
//--------------------------------------------------------------------//
|
||||
|
||||
// 在更新报警回调之前,我们应该确保计时器没有处于启用状态
|
||||
ESP_LOGI(TAG, "Disable timer");
|
||||
ESP_ERROR_CHECK(gptimer_disable(gptimer));
|
||||
// 设置一个新的回调函数
|
||||
cbs.on_alarm = example_timer_on_alarm_cb_v2;
|
||||
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
|
||||
ESP_LOGI(TAG, "Enable timer");
|
||||
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||
|
||||
// 重新设置报警条件
|
||||
ESP_LOGI(TAG, "Start timer, auto-reload at alarm event");
|
||||
gptimer_alarm_config_t alarm_config2 = {
|
||||
.reload_count = 0,
|
||||
.alarm_count = 1000000, // period = 1s
|
||||
.flags.auto_reload_on_alarm = true, //报警事件发生后立即通过硬件重新加载计数值
|
||||
};
|
||||
// 设置定时器的报警事件
|
||||
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2));
|
||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||
|
||||
// 循环次数为4次。在每次循环中,通过 xQueueReceive() 函数从队列中接收数据,并等待最多2秒。如果成功接收到数据,则打印定时器重新加载的消息
|
||||
int record = 4;
|
||||
while (record) {
|
||||
if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) {
|
||||
ESP_LOGI(TAG, "Timer reloaded, count=%llu", ele.event_count);
|
||||
record--;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Missed one count event");
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Stop timer");
|
||||
ESP_ERROR_CHECK(gptimer_stop(gptimer));
|
||||
|
||||
ESP_LOGI(TAG, "Disable timer");
|
||||
ESP_ERROR_CHECK(gptimer_disable(gptimer));
|
||||
|
||||
//--------------------------------------------------------------------//
|
||||
ESP_LOGW(TAG, "案例2结束,案例3开始");
|
||||
//--------------------------------------------------------------------//
|
||||
// 案例3动态更新报警值
|
||||
cbs.on_alarm = example_timer_on_alarm_cb_v3;
|
||||
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
|
||||
ESP_LOGI(TAG, "Enable timer");
|
||||
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||
|
||||
ESP_LOGI(TAG, "Start timer, update alarm value dynamically");
|
||||
gptimer_alarm_config_t alarm_config3 = {
|
||||
.alarm_count = 1000000, // period = 1s
|
||||
};
|
||||
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config3));
|
||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||
record = 4;
|
||||
while (record) {
|
||||
if (xQueueReceive(queue, &ele, pdMS_TO_TICKS(2000))) {
|
||||
ESP_LOGI(TAG, "Timer alarmed, count=%llu", ele.event_count);
|
||||
record--;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Missed one count event");
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Stop timer");
|
||||
ESP_ERROR_CHECK(gptimer_stop(gptimer));
|
||||
ESP_LOGI(TAG, "Disable timer");
|
||||
ESP_ERROR_CHECK(gptimer_disable(gptimer));
|
||||
ESP_LOGI(TAG, "Delete timer");
|
||||
ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
|
||||
|
||||
vQueueDelete(queue);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(i2c_bh1750)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
|
||||
// I2C Master 配置
|
||||
#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
|
||||
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
|
||||
// BH1750 Sensor 配置
|
||||
#define BH1750_SENSOR_ADDR 0x23 //0010_0011 // 传感器地址
|
||||
#define BH1750_CMD_START 0x23 //0010_0011 // 传感器模式:单次采集模式
|
||||
#define WRITE_BIT I2C_MASTER_WRITE // I2C 读取位 :1
|
||||
#define READ_BIT I2C_MASTER_READ // I2C 写入位 :0
|
||||
#define ACK_CHECK_EN 0x1 // 检测从机应答
|
||||
#define ACK_CHECK_DIS 0x0 // 不检测从机应答
|
||||
#define ACK_VAL 0x0 // 响应值
|
||||
#define NACK_VAL 0x1 // 无响应值
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief test code to operate on BH1750 sensor
|
||||
*
|
||||
* 1. set operation mode(e.g One time L-resolution mode)
|
||||
* _________________________________________________________________
|
||||
* | start | slave_addr + wr_bit + ack | write 1 byte + ack | stop |
|
||||
* --------|---------------------------|---------------------|------|
|
||||
* 2. wait more than 24 ms
|
||||
* 3. read data
|
||||
* ______________________________________________________________________________________
|
||||
* | start | slave_addr + rd_bit + ack | read 1 byte + ack | read 1 byte + nack | stop |
|
||||
* --------|---------------------------|--------------------|--------------------|------|
|
||||
*/
|
||||
static esp_err_t i2c_master_sensor_test(i2c_port_t i2c_num, uint8_t *data_h, uint8_t *data_l)
|
||||
{
|
||||
int ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); // 创建I2C命令
|
||||
i2c_master_start(cmd); // 起始信号
|
||||
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN); //从机地址及读写位
|
||||
i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN); //数据位(数组)
|
||||
i2c_master_stop(cmd); //终止信号
|
||||
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS); //i2c_num 发送这个数据帧,timeout设置为1000毫秒
|
||||
i2c_cmd_link_delete(cmd); //删除i2c_cmd_handle_t对象,释放资源
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN); //从机地址及读写位
|
||||
i2c_master_read_byte(cmd, data_h, ACK_VAL); //读取数据(高位)
|
||||
i2c_master_read_byte(cmd, data_l, NACK_VAL); //读取数据(低位)
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C master initialization
|
||||
*/
|
||||
static esp_err_t i2c_master_init(void)
|
||||
{
|
||||
// 配置I2C
|
||||
int i2c_master_port = I2C_MASTER_NUM;
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
// .clk_flags = 0, /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */
|
||||
};
|
||||
esp_err_t err = i2c_param_config(i2c_master_port, &conf);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
// 安装I2C驱动
|
||||
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
}
|
||||
|
||||
|
||||
static void i2c_task(void *arg)
|
||||
{
|
||||
int ret; // Return value
|
||||
int task_idx = (int)arg;
|
||||
uint8_t sensor_data_h, sensor_data_l;
|
||||
int cnt = 0;
|
||||
|
||||
while (1) {
|
||||
// 读取数据
|
||||
ESP_LOGI(TAG, "TASK[%d] test cnt: %d", task_idx, cnt++);
|
||||
ret = i2c_master_sensor_test(I2C_MASTER_NUM, &sensor_data_h, &sensor_data_l);
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
ESP_LOGE(TAG, "I2C Timeout");
|
||||
} else if (ret == ESP_OK) {
|
||||
printf("*******************\n");
|
||||
printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx);
|
||||
printf("*******************\n");
|
||||
printf("data_h: %02x\n", sensor_data_h);
|
||||
printf("data_l: %02x\n", sensor_data_l);
|
||||
printf("sensor val: %.02f [Lux]\n", (sensor_data_h << 8 | sensor_data_l) / 1.2);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "%s: No ack, sensor not connected...skip...", esp_err_to_name(ret));
|
||||
}
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// 初始化I2C
|
||||
ESP_ERROR_CHECK(i2c_master_init());
|
||||
// 创建I2C采集任务
|
||||
xTaskCreate(i2c_task, "i2c_task", 1024 * 2, (void *)0, 10, NULL);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# The following 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)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/advanced/components)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(i2c_tools)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "i2ctools_example_main.c"
|
||||
"cmd_i2ctools.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,10 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_STORE_HISTORY
|
||||
bool "Store command history in flash"
|
||||
default y
|
||||
help
|
||||
Linenoise line editing library provides functions to save and load
|
||||
command history. If this option is enabled, initalizes a FAT filesystem
|
||||
and uses it to store command history.
|
||||
endmenu
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
/* cmd_i2ctools.h
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void register_i2ctools(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/* i2c-tools example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "cmd_system.h"
|
||||
#include "cmd_i2ctools.h"
|
||||
|
||||
static const char *TAG = "i2c-tools";
|
||||
|
||||
#if CONFIG_EXAMPLE_STORE_HISTORY
|
||||
|
||||
#define MOUNT_PATH "/data"
|
||||
#define HISTORY_PATH MOUNT_PATH "/history.txt"
|
||||
|
||||
static void initialize_filesystem(void)
|
||||
{
|
||||
static wl_handle_t wl_handle;
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.max_files = 4,
|
||||
.format_if_mount_failed = true
|
||||
};
|
||||
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(MOUNT_PATH, "storage", &mount_config, &wl_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_STORE_HISTORY
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
|
||||
#if CONFIG_EXAMPLE_STORE_HISTORY
|
||||
initialize_filesystem();
|
||||
repl_config.history_save_path = HISTORY_PATH;
|
||||
#endif
|
||||
repl_config.prompt = "i2c-tools>";
|
||||
|
||||
// install console REPL environment
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
#elif CONFIG_ESP_CONSOLE_USB_CDC
|
||||
esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &repl));
|
||||
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
esp_console_dev_usb_serial_jtag_config_t usbjtag_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&usbjtag_config, &repl_config, &repl));
|
||||
#endif
|
||||
|
||||
register_i2ctools();
|
||||
|
||||
printf("\n ==============================================================\n");
|
||||
printf(" | Steps to Use i2c-tools |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | 1. Try 'help', check all supported commands |\n");
|
||||
printf(" | 2. Try 'i2cconfig' to configure your I2C bus |\n");
|
||||
printf(" | 3. Try 'i2cdetect' to scan devices on the bus |\n");
|
||||
printf(" | 4. Try 'i2cget' to get the content of specific register |\n");
|
||||
printf(" | 5. Try 'i2cset' to set the value of specific register |\n");
|
||||
printf(" | 6. Try 'i2cdump' to dump all the register (Experiment) |\n");
|
||||
printf(" | |\n");
|
||||
printf(" ==============================================================\n\n");
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, fat, , 528K,
|
||||
|
@@ -0,0 +1,17 @@
|
||||
# Reduce bootloader log verbosity
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||
|
||||
# Increase main task stack size
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=7168
|
||||
|
||||
# Enable filesystem
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
||||
|
||||
# Enable FreeRTOS stats formatting functions, needed for 'tasks' command
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
||||
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(led_pwm)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "led_pwm.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include "driver/ledc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define LEDC_TIMER LEDC_TIMER_0
|
||||
#define LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_OUTPUT_IO (2) // Define the output GPIO
|
||||
#define LEDC_CHANNEL LEDC_CHANNEL_0
|
||||
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
|
||||
#define LEDC_DUTY (4096) // Set duty to 50%. (2 ** 13) * 50% = 4096
|
||||
#define LEDC_FREQUENCY (4000) // Frequency in Hertz. Set frequency at 4 kHz
|
||||
#define FADE_TIME (2000) // Fade time in milliseconds
|
||||
|
||||
static void example_ledc_init(void)
|
||||
{
|
||||
// Prepare and then apply the LEDC PWM timer configuration
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = LEDC_MODE,
|
||||
.duty_resolution = LEDC_DUTY_RES,
|
||||
.timer_num = LEDC_TIMER,
|
||||
.freq_hz = LEDC_FREQUENCY, // Set output frequency at 4 kHz
|
||||
.clk_cfg = LEDC_AUTO_CLK
|
||||
};
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||
|
||||
// Prepare and then apply the LEDC PWM channel configuration
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.speed_mode = LEDC_MODE,
|
||||
.channel = LEDC_CHANNEL,
|
||||
.timer_sel = LEDC_TIMER,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = LEDC_OUTPUT_IO,
|
||||
.duty = 0, // Start with duty 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
|
||||
|
||||
// Install LEDC fade function
|
||||
ESP_ERROR_CHECK(ledc_fade_func_install(0));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Set the LEDC peripheral configuration
|
||||
example_ledc_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Fade to 100% duty cycle within FADE_TIME milliseconds
|
||||
ESP_ERROR_CHECK(ledc_set_fade_with_time(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY, FADE_TIME));
|
||||
ESP_ERROR_CHECK(ledc_fade_start(LEDC_MODE, LEDC_CHANNEL, LEDC_FADE_WAIT_DONE));
|
||||
|
||||
// Wait for the fade to complete
|
||||
vTaskDelay(FADE_TIME / portTICK_PERIOD_MS);
|
||||
|
||||
// Fade back to 0% duty cycle within FADE_TIME milliseconds
|
||||
ESP_ERROR_CHECK(ledc_set_fade_with_time(LEDC_MODE, LEDC_CHANNEL, 0, FADE_TIME));
|
||||
ESP_ERROR_CHECK(ledc_fade_start(LEDC_MODE, LEDC_CHANNEL, LEDC_FADE_WAIT_DONE));
|
||||
|
||||
// Wait for the fade to complete
|
||||
vTaskDelay(FADE_TIME / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(uart)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "uart.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "string.h"
|
||||
|
||||
#define TX_GPIO_NUM 17
|
||||
#define RX_GPIO_NUM 16
|
||||
|
||||
// 配置串口3
|
||||
void uart_config(void) {
|
||||
const uart_port_t uart_num = UART_NUM_2;
|
||||
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
|
||||
// 配置UART参数
|
||||
ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
|
||||
|
||||
// 设置UART引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(uart_num, TX_GPIO_NUM, RX_GPIO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 安装UART驱动程序,不使用事件队列
|
||||
const int uart_buffer_size = (1024 * 2);
|
||||
ESP_ERROR_CHECK(uart_driver_install(uart_num, uart_buffer_size, 0, 0, NULL, 0));
|
||||
}
|
||||
|
||||
// 串口发送测试
|
||||
void uart_send_receive_demo(void) {
|
||||
const uart_port_t uart_num = UART_NUM_2;
|
||||
char* test_str = "This is a UART test string.\n";
|
||||
uint8_t data[128];
|
||||
|
||||
// 发送数据
|
||||
uart_write_bytes(uart_num, test_str, strlen(test_str));
|
||||
|
||||
while(1){
|
||||
vTaskDelay(1);
|
||||
// 等待数据接收
|
||||
int length = 0;
|
||||
ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
|
||||
if(length > 0) {
|
||||
int read_len = uart_read_bytes(uart_num, data, length, pdMS_TO_TICKS(1000));
|
||||
if(read_len > 0) {
|
||||
// 输出接收到的数据
|
||||
printf("Received: %.*s\n", read_len, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void app_main(void) {
|
||||
uart_config();
|
||||
uart_send_receive_demo();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
*build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(flash_fatfs)
|
||||
@@ -0,0 +1 @@
|
||||
11111111111111111111111111111222222222
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(SRCS "flash_fatfs.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
set(image ../fatfs_image)
|
||||
fatfs_create_spiflash_image(storage ${image} FLASH_IN_PROJECT)
|
||||
@@ -0,0 +1,85 @@
|
||||
// 演示读写文件
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_flash.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
static const char *TAG = "FAT";
|
||||
|
||||
// Handle of the wear levelling library instance
|
||||
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
|
||||
|
||||
// Mount path for the partition
|
||||
const char *base_path = "/fatfs_image";
|
||||
|
||||
// Mount FATFS partition
|
||||
static bool mount_fatfs(const char* partition_label)
|
||||
{
|
||||
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.max_files = 4,
|
||||
.format_if_mount_failed = true,
|
||||
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
|
||||
};
|
||||
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, &mount_config, &s_wl_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
const char *partition_label = "storage";
|
||||
// Initialize FAT FS in the partition
|
||||
if (!mount_fatfs(partition_label)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print FAT FS size information
|
||||
uint64_t bytes_total, bytes_free;
|
||||
esp_vfs_fat_info(base_path, &bytes_total, &bytes_free);
|
||||
ESP_LOGI(TAG, "FAT FS: %" PRIu64 " kB total, %" PRIu64 " kB free", bytes_total / 1024, bytes_free / 1024);
|
||||
|
||||
Create a file in FAT FS
|
||||
ESP_LOGI(TAG, "Opening file");
|
||||
FILE *f = fopen("/fatfs_image/hello.txt", "wb");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
fprintf(f, "fat文件系统测试 %s\n", "hollo world!");
|
||||
fclose(f);
|
||||
ESP_LOGI(TAG, "File written");
|
||||
|
||||
// Open file for reading
|
||||
ESP_LOGI(TAG, "Reading file");
|
||||
f = fopen("/fatfs_image/hello.txt", "rb");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
char line[128];
|
||||
fgets(line, sizeof(line), f);
|
||||
fclose(f);
|
||||
// strip newline
|
||||
char *pos = strchr(line, '\n');
|
||||
if (pos) {
|
||||
*pos = '\0';
|
||||
}
|
||||
ESP_LOGI(TAG, "Read from file: '%s'", line);
|
||||
// Unmount FAT FS
|
||||
ESP_LOGI(TAG, "Unmounting FAT filesystem");
|
||||
esp_err_t unmount_err = esp_vfs_fat_spiflash_unmount_rw_wl(base_path, s_wl_handle);
|
||||
if (unmount_err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to unmount FATFS (%s)", esp_err_to_name(unmount_err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_flash.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
static const char *TAG = "FAT";
|
||||
|
||||
// Handle of the wear levelling library instance
|
||||
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
|
||||
|
||||
// Mount path for the partition
|
||||
const char *base_path = "/fatfs_image";
|
||||
|
||||
// Mount FATFS partition
|
||||
static bool mount_fatfs(const char* partition_label)
|
||||
{
|
||||
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.max_files = 4,
|
||||
.format_if_mount_failed = true,
|
||||
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
|
||||
};
|
||||
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, &mount_config, &s_wl_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
const char *partition_label = "storage";
|
||||
// Initialize FAT FS in the partition
|
||||
if (!mount_fatfs(partition_label)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print FAT FS size information
|
||||
uint64_t bytes_total, bytes_free;
|
||||
esp_vfs_fat_info(base_path, &bytes_total, &bytes_free);
|
||||
ESP_LOGI(TAG, "FAT FS: %" PRIu64 " kB total, %" PRIu64 " kB free", bytes_total / 1024, bytes_free / 1024);
|
||||
|
||||
// 读取写入的镜像文件
|
||||
// Open file for reading
|
||||
ESP_LOGI(TAG, "Reading file");
|
||||
FILE *f = fopen("/fatfs_image/hello.txt", "rb");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
char line[128];
|
||||
fgets(line, sizeof(line), f);
|
||||
fclose(f);
|
||||
// strip newline
|
||||
char *pos = strchr(line, '\n');
|
||||
if (pos) {
|
||||
*pos = '\0';
|
||||
}
|
||||
ESP_LOGI(TAG, "Read from file: '%s'", line);
|
||||
// Unmount FAT FS
|
||||
ESP_LOGI(TAG, "Unmounting FAT filesystem");
|
||||
esp_err_t unmount_err = esp_vfs_fat_spiflash_unmount_rw_wl(base_path, s_wl_handle);
|
||||
if (unmount_err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to unmount FATFS (%s)", esp_err_to_name(unmount_err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x4000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, fat, 0x110000, 1M,
|
||||
|
||||
|
@@ -0,0 +1,6 @@
|
||||
build
|
||||
*managed_components
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
@@ -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(flash_spiffs)
|
||||
@@ -0,0 +1,8 @@
|
||||
idf_component_register(SRCS "flash_spiffs.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# Create a SPIFFS image from the contents of the 'spiffs_image' directory
|
||||
# that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that
|
||||
# the generated image should be flashed when the entire project is flashed to
|
||||
# the target with 'idf.py -p PORT flash'.
|
||||
spiffs_create_partition_image(storage ../spiffs_image FLASH_IN_PROJECT)
|
||||
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_spiffs.h"
|
||||
#include "mbedtls/md5.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
static void read_hello_txt(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Reading hello.txt");
|
||||
|
||||
// Open for reading hello.txt
|
||||
FILE* f = fopen("/spiffs/hello.txt", "r");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open hello.txt");
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[64];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
fread(buf, 1, sizeof(buf), f);
|
||||
fclose(f);
|
||||
|
||||
// Display the read contents from the file
|
||||
ESP_LOGI(TAG, "Read from hello.txt: %s", buf);
|
||||
}
|
||||
|
||||
static void compute_alice_txt_md5(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Computing alice.txt MD5 hash");
|
||||
|
||||
// The file alice.txt lives under a subdirectory, though SPIFFS itself is flat
|
||||
FILE* f = fopen("/spiffs/sub/alice.txt", "r");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open alice.txt");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read file and compute the digest chunk by chunk
|
||||
#define MD5_MAX_LEN 16
|
||||
|
||||
char buf[64];
|
||||
mbedtls_md5_context ctx;
|
||||
unsigned char digest[MD5_MAX_LEN];
|
||||
|
||||
mbedtls_md5_init(&ctx);
|
||||
mbedtls_md5_starts(&ctx);
|
||||
|
||||
size_t read;
|
||||
|
||||
do {
|
||||
read = fread((void*) buf, 1, sizeof(buf), f);
|
||||
mbedtls_md5_update(&ctx, (unsigned const char*) buf, read);
|
||||
} while(read == sizeof(buf));
|
||||
|
||||
mbedtls_md5_finish(&ctx, digest);
|
||||
|
||||
// Create a string of the digest
|
||||
char digest_str[MD5_MAX_LEN * 2];
|
||||
|
||||
for (int i = 0; i < MD5_MAX_LEN; i++) {
|
||||
sprintf(&digest_str[i * 2], "%02x", (unsigned int)digest[i]);
|
||||
}
|
||||
|
||||
// For reference, MD5 should be deeb71f585cbb3ae5f7976d5127faf2a
|
||||
ESP_LOGI(TAG, "Computed MD5 hash of alice.txt: %s", digest_str);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing SPIFFS");
|
||||
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = NULL,
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = false
|
||||
};
|
||||
|
||||
// Use settings defined above to initialize and mount SPIFFS filesystem.
|
||||
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t total = 0, used = 0;
|
||||
ret = esp_spiffs_info(NULL, &total, &used);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
|
||||
}
|
||||
|
||||
/* The following calls demonstrate reading files from the generated SPIFFS
|
||||
* image. The images should contain the same files and contents as the spiffs_image directory.
|
||||
*/
|
||||
|
||||
// Read and display the contents of a small text file (hello.txt)
|
||||
read_hello_txt();
|
||||
|
||||
// Compute and display the MD5 hash of a large text file (alice.txt)
|
||||
compute_alice_txt_md5();
|
||||
|
||||
// All done, unmount partition and disable SPIFFS
|
||||
esp_vfs_spiffs_unregister(NULL);
|
||||
ESP_LOGI(TAG, "SPIFFS unmounted");
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x4000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, spiffs, , 0xF0000,
|
||||
|
||||
|
@@ -0,0 +1 @@
|
||||
Hello World!
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user