ESP32S3 ADC DMA使用记录(坑记录)(大牛欢迎给出建议)

这篇具有很好参考价值的文章主要介绍了ESP32S3 ADC DMA使用记录(坑记录)(大牛欢迎给出建议)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目前测到三个问题:

一、ADC DMA采样频率sample_freq_hz取值范围611-83333,虽然可以达到83333,但是只能是在while循环里面不停采样才可以,如果想要隔一段时间采样一次则不行,假如隔一段时间使用adc_digi_read_bytes读取40byte数据,结果经常会返回ESP_ERR_INVALID_STATE,且经常读取的数据量少于40byte。

        所以ADC DMA采样方式(大约是15us)虽然比单次采样(大约是35us)速度要快,但是不能间隔采样,只能连续不停采样。

二、ADC DMA采样精度太烂,粗略使用还行,要想精确不能用。

三、ADC DMA和WIFI STA模式冲突

adc_digi_read_bytes执行的时候,如果正好wifi sta在初始化或者在连接ap,那么100%会超时,返回值ESP_ERR_TIMEOUT。而且后期无法恢复,只能调用下列函数才可以恢复。

adc_digi_stop();
adc_digi_start();

新解决方案:升级idf到4.4.3

具体见下面代码

代码:

main.c

/* Handwrite Board

   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 "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_http_client.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_wifi.h"

//local variable
static const char* TAG = "Main";
TaskHandle_t wifi_sta_ap_task_handle = NULL;
TaskHandle_t rmt_task_handle = NULL;



//extern method
extern void HWB_Wifi_Init_Sta_And_Ap();
extern void HWB_RMT_Task(void *Parameters);



void HWB_Wifi_Sta_Ap_Task(void *Parameters)
{
  HWB_Wifi_Init_Sta_And_Ap();
}


void app_main(void)
{
    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
     ESP_ERROR_CHECK(nvs_flash_erase());//test
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    //创建业务处理线程,启动wifi sta
	xTaskCreate(HWB_Wifi_Sta_Ap_Task, "HWB_Wifi_Sta_Ap_Task", (4*1024), NULL, 1, &wifi_sta_ap_task_handle);
    xTaskCreate(HWB_RMT_Task, "HWB_RMT_Task", (4*1024), NULL, 20, &rmt_task_handle);
}

rmt.c


#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/rmt.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include <sys/time.h>



//extern variable
extern xQueueHandle adc_data_queue;
//extern method

//local variable
static const char *TAG = "example";
#define TIMES              40
#define GET_UNIT(x)        ((x>>3) & 0x1)
#define ADC_RESULT_BYTE     4
#define ADC_CONV_LIMIT_EN   0
#define ADC_CONV_MODE       ADC_CONV_SINGLE_UNIT_1
#define ADC_OUTPUT_TYPE     ADC_DIGI_OUTPUT_FORMAT_TYPE2

#define RMT_TX_U102_29_CHANNEL  RMT_CHANNEL_0
#define RMT_TX_U102_29_GPIO     4
#define RMT_TX_U102_16_CHANNEL  RMT_CHANNEL_1
#define RMT_TX_U102_16_GPIO     6
#define RMT_TX_U102_15_CHANNEL  RMT_CHANNEL_2
#define RMT_TX_U102_15_GPIO     7
#define ADC_DMA_MODE            1
#define         DEFAULT_VREF    1100        //Use adc2_vref_to_gpio() to obtain a better estimate
static esp_adc_cal_characteristics_t *adc_chars;

static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
static const adc_atten_t atten = ADC_ATTEN_DB_11;

#if ADC_DMA_MODE
static uint16_t adc1_chan_mask = BIT(4);
static uint16_t adc2_chan_mask = 0;
static adc_channel_t channel1[1] = {ADC1_CHANNEL_4};
#endif
/*
 * Prepare a raw table with a message in the Morse code
 *
 * The message is "ESP" : . ... .--.
 *
 * The table structure represents the RMT item structure:
 * {duration, level, duration, level}
 *
 */
 static const rmt_item32_t morse_esp_type1[] = {
     {{{ 10, 0, 60, 1 }}}, 
     {{{ 20, 0, 10, 0 }}}, 
 };

static const rmt_item32_t morse_esp2[] = {
    {{{ 100, 1, 180, 0 }}}, 
};
// static const rmt_item32_t morse_esp3[] = {
//     {{{ 100, 1, 60, 0 }}}, 
// };
extern int THRESHOLD_VALUE;
static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num)
{
    printf("continuous_adc_init %d,%d\n",adc1_chan_mask,adc2_chan_mask);
    adc_digi_init_config_t adc_dma_config = {
        .max_store_buf_size = 1024,
        .conv_num_each_intr = TIMES,
        .adc1_chan_mask = adc1_chan_mask,
        .adc2_chan_mask = adc2_chan_mask,
    };
    ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config));

    adc_digi_configuration_t dig_cfg = {
        .conv_limit_en = ADC_CONV_LIMIT_EN,
        .conv_limit_num = 250,
        .sample_freq_hz = 83333,
        .conv_mode = ADC_CONV_MODE,
        .format = ADC_OUTPUT_TYPE,
    };

    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++) {
        uint8_t unit = GET_UNIT(channel[i]);
        uint8_t ch = channel[i] & 0x7;
        adc_pattern[i].atten = ADC_ATTEN_DB_11;
        adc_pattern[i].channel = ch;
        adc_pattern[i].unit = unit;
        adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;

        printf("adc_pattern[%d].atten is :%x\n", i, adc_pattern[i].atten);
        printf("adc_pattern[%d].channel is :%x\n", i, adc_pattern[i].channel);
        printf("adc_pattern[%d].unit is :%x\n", i, adc_pattern[i].unit);
        printf("adc_pattern[%d].bit_width is :%d,%d\n", i, adc_pattern[i].bit_width,SOC_ADC_DIGI_MAX_BITWIDTH);
    }
    dig_cfg.adc_pattern = adc_pattern;
    ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg));
}

static void check_efuse(void)
{
    //Check if TP is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("eFuse Two Point: NOT supported\n");
    }
    //Check Vref is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        printf("eFuse Vref: Supported\n");
    } else {
        printf("eFuse Vref: NOT supported\n");
    }
}

static void print_char_val_type(esp_adc_cal_value_t val_type)
{
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        printf("Characterized using Two Point Value\n");
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        printf("Characterized using eFuse Vref\n");
    } else {
        printf("Characterized using Default Vref\n");
    }
}
/*
 * Initialize the RMT Tx channel
 */
static void rmt_tx_init(void)
{
	printf("run rmt_tx_init");
    rmt_config_t config1 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_29_GPIO, RMT_TX_U102_29_CHANNEL);
    config1.flags = RMT_CHANNEL_FLAGS_INVERT_SIG;
    config1.tx_config.carrier_en = true;
    config1.tx_config.carrier_duty_percent = 50;
    config1.tx_config.carrier_freq_hz = 500000;
    config1.clk_div = 80;

    rmt_config_t config2 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_16_GPIO, RMT_TX_U102_16_CHANNEL);
    config2.tx_config.carrier_en = false;
    config2.tx_config.carrier_duty_percent = 50;
    config2.tx_config.carrier_freq_hz = 500000;
    config2.clk_div = 80;

    rmt_config_t config3 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_15_GPIO, RMT_TX_U102_15_CHANNEL);
    config3.tx_config.carrier_en = false;
    config3.tx_config.carrier_duty_percent = 50;
    config3.tx_config.carrier_freq_hz = 500000;
    config3.clk_div = 80;

    ESP_ERROR_CHECK(rmt_config_self(&config1, true)); /*20221011 YB added new API to set open Drain for TX or not*/
    ESP_ERROR_CHECK(rmt_config(&config2));
    ESP_ERROR_CHECK(rmt_config(&config3));
    ESP_ERROR_CHECK(rmt_driver_install(config1.channel, 0, 0));
    ESP_ERROR_CHECK(rmt_driver_install(config2.channel, 0, 0));
    ESP_ERROR_CHECK(rmt_driver_install(config3.channel, 0, 0));

    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_29_CHANNEL));
    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_16_CHANNEL));
    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_15_CHANNEL));
}

void HWB_RMT_Task(void *Parameters)
{
    printf("Configuring transmitter");
    uint32_t ret_num = 0;
	uint8_t result[TIMES] = {0};
    memset(result, 0xcc, TIMES);
	
    //Check if Two Point or Vref are burned into eFuse
    check_efuse();

    //Characterize ADC
    adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, atten, width, DEFAULT_VREF, adc_chars);
    print_char_val_type(val_type);
#if ADC_DMA_MODE
    continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel1, sizeof(channel1) / sizeof(adc_channel_t));
    adc_digi_start();
#endif

    rmt_tx_init();
	
    while (1) {		
        ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_15_CHANNEL, morse_esp2, sizeof(morse_esp2) / sizeof(morse_esp2[0]), false));
		ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_29_CHANNEL, morse_esp_type1, sizeof(morse_esp_type1) / sizeof(morse_esp_type1[0]), false));
		ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_16_CHANNEL, morse_esp_type1, sizeof(morse_esp_type1) / sizeof(morse_esp_type1[0]), false));
        rmt_wait_tx_done(RMT_TX_U102_16_CHANNEL,10); 

#if ADC_DMA_MODE
        esp_err_t ret = adc_digi_read_bytes(result, TIMES, &ret_num, 10/*ADC_MAX_DELAY*/);
        uint32_t max_adc_val = 0;
        if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) {
            for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
                adc_digi_output_data_t *p = (void*)&result[i];
                if (p->type2.unit == 0 && p->type2.channel == 4) {
                    max_adc_val = (max_adc_val > p->type2.data ? max_adc_val : p->type2.data);
                    printf("Unit: %d,Channel: %d, Value: %d\n", p->type2.unit+1, p->type2.channel, p->type2.data);
                }
            }
        }else if(ret == ESP_ERR_TIMEOUT){
            printf("ESP_ERR_TIMEOUT\n");
            // adc_digi_stop();
            // adc_digi_start();
        }
#endif

        rmt_wait_tx_done(RMT_TX_U102_15_CHANNEL,10); 
    }
}

wifi_ap_sta.c文章来源地址https://www.toymoban.com/news/detail-669700.html

/* WiFi station 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 <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"

#define     HWB_WIFI_AP_SSID                        "1TMT_HWB"
#define     HWB_WIFI_AP_PASSWORD                    "12345678" //最小长度是8,最大长度是64
#define     HWB_WIFI_AP_CHANNEL                     1    //范围1-13,默认值1    
#define     HWB_WIFI_AP_MAX_STA_CONN                1
#define     HWB_WIFI_STA_MAXIMUM_RETRY              5
//local variable
static const char *TAG = "HWB_Wifi_Sta_Ap";

//local method


static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        printf("WIFI_EVENT_STA_START");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        printf("WIFI_EVENT_STA_DISCONNECTED");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
        printf("WIFI_EVENT_STA_CONNECTED");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        printf("IP_EVENT_STA_GOT_IP");
    }else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
        printf("WIFI_EVENT_AP_STACONNECTED");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        printf("WIFI_EVENT_AP_STADISCONNECTED");
    }
}


void HWB_Wifi_Init_Sta_And_Ap()
{
    printf("HWB_Wifi_Init_Sta_And_Ap start");

    ESP_ERROR_CHECK(esp_netif_init());//创建一个 LwIP(轻量级的 TCP/IP 协议栈)核心任务,并初始化 LwIP 相关工作

    //创建一个系统事件任务,并初始化应用程序事件的回调函数。
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();//创建带有 TCP/IP 堆栈的默认网络接口实例绑定 AP
    //WIFI 驱动程序初始化配置时建议使用 IDF 默认的参数进行配置,WIFI_INIT_CONFIG_DEFAULT是一个宏,
    //这个宏的作用就是对结构体wifi_init_config_t进行初始化
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    //创建 WIFI 驱动程序任务并初始化 WIFI 驱动程序,这个API必须第一个调用,才能调用wifi的其他API
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    //向system event loop注册event handler
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    //wifi_config_t是配置WIFI的集合union。
    //wifi_ap_config_t  ap  用于配置AP
    //wifi_sta_config_t sta 用于配置STA
    //WIFI STA Config
    wifi_config_t wifi_config_sta;
    memset(&wifi_config_sta, 0, sizeof(wifi_config_sta));
    wifi_config_sta.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;

    if (strlen((char *)wifi_config_sta.sta.password) == 0) {
        printf("authmode WIFI_AUTH_OPEN");
        wifi_config_sta.sta.threshold.authmode = WIFI_AUTH_OPEN;
    }
    //WIFI AP Config
    wifi_config_t wifi_config_ap = {
        .ap = {
            .ssid = HWB_WIFI_AP_SSID,
            .ssid_len = strlen(HWB_WIFI_AP_SSID),
            .channel = HWB_WIFI_AP_CHANNEL,
            .password = HWB_WIFI_AP_PASSWORD,
            .max_connection = HWB_WIFI_AP_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(HWB_WIFI_AP_PASSWORD) == 0) {
        wifi_config_ap.ap.authmode = WIFI_AUTH_OPEN;
    }
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA) );//配置WIFI的工作模式为AP-STA,即AP 和STA共存模式;
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config_sta) );//对wifi的STA模式进行配置
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config_ap) );//对wifi的AP模式进行配置
    ESP_ERROR_CHECK(esp_wifi_start() );//启动WIFI

    printf("HWB_Wifi_Init_Sta_And_Ap finished.");
    while(1){
      vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

到了这里,关于ESP32S3 ADC DMA使用记录(坑记录)(大牛欢迎给出建议)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ESP32S3 Sense接入百度在线语音识别】

    视频地址: ESP32S3 Sense接入百度在线语音识别 目前这是我使用的ESP32S3官方硬件👍👍👍(小小的身材有大大的力量)只需要35元加摄像头麦克风79元,后期我会整理相关专栏进行Arduino系统学习😘😘😘。有需要可以购买xiao开发板💕💕💕,SeeedXIAO ESP32S3 Sense硬件购买地址:

    2024年04月10日
    浏览(33)
  • ESP32S3系列--SPI主机驱动详解(一)

    SPI是一种串行同步接口,可用于与外围设备进行通信。 ESP32S3自带4个SPI外设,其中SPI0/SPI1内部专用,共用一组信号线,通过一个仲裁器访问外部Flash和PSRAM;SPI2/3各自使用一组独立的信号线;开发者可以使用SPI2/3控制外部SPI从设备(Slave device);其中SPI2作为主设备有6个片选,数据

    2023年04月09日
    浏览(32)
  • 【EPS32S3学习笔记】ESP32+OPENCV+人脸识别 本地部署

    提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 从https://github.com/joachimBurket/esp32-

    2024年02月09日
    浏览(49)
  • 【ESP32S3 Sense接入语音识别+MiniMax模型对话】

    围绕ESP32S3 Sense接入语音识别+MiniMax模型对话展开,首先串口输入“1”字符,随后麦克风采集2s声音数据,对接百度在线语音识别,将返回文本结果丢入MiniMax模型,进而返回第二次结果文本,实现语言对话文本效果。以上一共有两次调用,后期只需加入tts模块就可完整对话。

    2024年04月16日
    浏览(57)
  • 【EPS32S3学习笔记】ESP32+OPENCV+OV2640+LVGL

    提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 前面已经完成了ESP32S3+LVGL+OV2640的工

    2024年02月06日
    浏览(50)
  • ESP32S3学习——LEDC LED PWM 控制器

    芯片:esp32s3 开发环境:espidfv4.4 1)LED 控制器 (LEDC) 主要用于控制 LED,也可产生 PWM 信号用于 其他设备 的控制。 该控制器有 8 路通道 ,可以产生独立的波形来驱动 RGB LED 等设备。 LED PWM 控制器可在 无需 CPU 干预 的情况下 自动改变占 空比,实现亮度和颜色渐变(因为这个功能

    2024年02月06日
    浏览(30)
  • 视频图像处理算法opencv在esp32及esp32s3上面的移植,也可以移植openmv

    opencv 在 esp32 及 esp32s3 上面的移植 Opencv 简介       OpenCV 是一个基于 Apache2.0 许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在 Linux 、 Windows 、 Android 和 Mac OS 操作系统上,它轻量级而且高效—— 由一系列 C 函数和少量 C++ 类构成,同时提供了 Python 、 R

    2024年02月09日
    浏览(30)
  • 【ESP32S3 Sense接入语音识别+MiniMax模型+TTS模块语音播报】

    讲解视频: ESP32S3 AI助手使用MiniMax大模型生产工具1 大家好,今天的教程将围绕如何实现精准的语音播报功能展开,我们用到了ESP32S3 Sense接入语音识别+MiniMax模型对话+SNR9816TTS模块。 目前这是我使用的ESP32S3官方硬件👍👍👍(小小的身材有大大的力量)只需要35元加摄像头麦

    2024年04月12日
    浏览(34)
  • ESP32学习笔记09-ADC多通道采集 dma方式传输

    9.1.1特点 高性能。时钟更快,因此采样 速率实现了大幅提升 。 支持 多通道扫描 模式。每个 SAR ADC 的测量规则可见 样式表 。扫描模式可配置为 单通道模式 双通道模式 交替模式。 扫描可由软件或 I2S 总线发起。 支持 DMA,扫描完成即发生中断 9.1.2样式表 通道 分辨率 衰减倍

    2023年04月21日
    浏览(35)
  • STM32 -ADC+DMA使用(巨全面)

    在STM32中,ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁¹。STM32的ADC为12位,AD最大值是4095,对应最大电压3.3V,可对0-3.3v之间的任意电压量化¹。STM32的ADC有18个输入通道,可测量16个外部和2个内部信号源¹。 在多通道数据

    2024年04月25日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包