code: 添加现有程序

This commit is contained in:
DuRuofu
2025-02-17 17:40:08 +08:00
parent 08123c535e
commit 9e552ea395
281 changed files with 13912 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
*build
*managed_components
dependencies.lock
sdkconfig
sdkconfig.old
+6
View File
@@ -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)
+77
View File
@@ -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.
+2
View File
@@ -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"
+17
View File
@@ -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")
+40
View File
@@ -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,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 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,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 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,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 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