21. HPM_MONITOR + ADC 高性能数据监控解决方案

21.1. 依赖SDK1.10.0

21.2. 介绍

-本方案展示了如何在先楫半导体MCU微控制器上实现高性能 ADC 采样,并通过 hpm_monitor 服务实时传输数据到 PC 上位机,用于波形显示和分析。

-HPM6300 系列支持 3 个 16 位的 ADC 转换器,可以转换来自外部引脚以及芯片内部的模拟信号。ADC 的转换精度设置为 16 位时,最大采样率 2MSPS;ADC 的转换精度设置为 12 位时,最大采样率 4MSPS。ADC 支持读取转换模式、周期转换模式、序列转换模式和抢占转换模式。

-本方案以 HPM6300 开发板为例,介绍如何实现高速 ADC 采样,并通过 hpm_monitor 服务将采样数据实时传输到 PC 端的 HPMicroMonitorStudio 工具进行波形显示。方案采用抢占转换模式、PWM 触发方式,通过 DMA 自动搬运数据,实现高效的数据采集和传输。

21.3. 方案特点

  1. 高性能数据采集:

    • 支持高达 2MSPS 的 16 位 ADC 采样

    • 采用 PWM 触发,采样时间精确可控

    • DMA 自动搬运,零 CPU 干预

  2. 实时数据监控:

    • 通过 hpm_monitor 服务实时传输 ADC 数据

    • 支持 USB/UART/ENET 三种通信接口

    • 低延迟、高带宽数据传输

  3. 灵活的数据处理:

    • 支持多种采样模式(Notify/Stream/Buffer)

    • 可自定义数据上报频率和格式

    • 支持多通道监控

  4. 用户友好:

    • PC 端图形化界面实时显示波形

    • 参数实时可调

21.4. 框图及调用流程

adc_lwipapi_main

21.5. 硬件配置

  1. 开发板支持 支持全系列HPM EVK开发板。 当前以HPM6300EVK验证,其余EVK需手动微调程序或引脚。

  2. 通信接口选择

    • ENET TCP:适合与 PC 上位机通过网络直连调试

    • USB CDC:带宽高,连接方便

    • UART:可选,最高支持 10Mbps 波特率

21.6. 软件配置

  1. 工程配置 (CMakeLists.txt)

# Copyright (c) 2021 HPMicro
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.13)

set(APP_VERSION_STRING "\"1.10.0\"")

set(RV_ARCH "rv32imafc")
set(RV_ABI "ilp32f")

# set(SES_TOOLCHAIN_VARIANT "Andes")
# set(CONFIG_HPM_MATH 1)
# set(CONFIG_HPM_MATH_DSP 1)
# set(HPM_MATH_DSP_SES_LIB "libdspf")


set(CONFIG_A_HPMMONITOR 1)
# set(CONFIG_MONITOR_INTERFACE "uart")
# set(CONFIG_MONITOR_INTERFACE "usb")
set(CONFIG_MONITOR_INTERFACE "enet")

if("${CONFIG_MONITOR_INTERFACE}" STREQUAL "uart")

elseif("${CONFIG_MONITOR_INTERFACE}" STREQUAL "usb")
    set(CONFIG_CHERRYUSB 1)
    set(CONFIG_USB_DEVICE 1)
    set(CONFIG_USB_DEVICE_CDC 1)
elseif("${CONFIG_MONITOR_INTERFACE}" STREQUAL "enet")
    set(CONFIG_LWIP 1)
    set(CONFIG_ENET_PHY 1)
    set(APP_USE_ENET_PORT_COUNT 1)
    #set(APP_USE_ENET_ITF_RGMII 1)
    #set(APP_USE_ENET_ITF_RMII 1)
    #set(APP_USE_ENET_PHY_DP83867 1)
    #set(APP_USE_ENET_PHY_RTL8211 1)
    #set(APP_USE_ENET_PHY_DP83848 1)
    set(APP_USE_ENET_PHY_RTL8201 1)
    if(NOT DEFINED APP_USE_ENET_PORT_COUNT)
        message(FATAL_ERROR "APP_USE_ENET_PORT_COUNT is undefined!")
    endif()

    if(NOT APP_USE_ENET_PORT_COUNT EQUAL 1)
        message(FATAL_ERROR "This sample supports only one Ethernet port!")
    endif()

    if (APP_USE_ENET_ITF_RGMII AND APP_USE_ENET_ITF_RMII)
        message(FATAL_ERROR "This sample doesn't support more than one Ethernet phy!")
    endif()
endif()

find_package(hpm-sdk REQUIRED HINTS $ENV{HPM_SDK_BASE})

sdk_ld_options("-lm")
# sdk_compile_options("-O2")

if("${CONFIG_MONITOR_INTERFACE}" STREQUAL "uart")
    sdk_compile_definitions("-DCONFIG_UART_CHANNEL=1")
    sdk_compile_definitions("-DCONFIG_USE_CONSOLE_UART=1")
    sdk_compile_definitions("-DCONFIG_MONITOR_DBG_LEVEL=0")
elseif("${CONFIG_MONITOR_INTERFACE}" STREQUAL "usb")
    sdk_compile_definitions("-DCONFIG_USB_CHANNEL=1")
elseif("${CONFIG_MONITOR_INTERFACE}" STREQUAL "enet")
    sdk_compile_definitions("-DCONFIG_ENET_CHANNEL=1")
    sdk_inc(inc/enet)
endif()

sdk_compile_definitions("-DHPM_MONITOR_ENABLE=1")

project(hpm_monitor_adc)

sdk_inc(../common/adc)
sdk_inc(inc)
sdk_inc(inc/config)

sdk_app_src(src/main.c)
sdk_app_src(../common/adc/adc_16_pmt.c)

add_subdirectory(../../../../ hpm_apps/build_tmp)

generate_ses_project()
  1. MONITOR配置 (monitor_config.h)

#define MONITOR_PID                  (0xFFFF)
#define MONITOR_VID                  (0x34B7) /* HPMicro VID */

#define MONITOR_PROFILE_MAXSIZE      (4096)

#define MONITOR_MEM_SIZE             (10*1024)

/*--------monitor log--------*/
#define CONFIG_MONITOR_PRINTF(...) printf(__VA_ARGS__)

#ifndef CONFIG_MONITOR_DBG_LEVEL
#define CONFIG_MONITOR_DBG_LEVEL MONITOR_DBG_INFO
#endif

#if defined(CONFIG_UART_CHANNEL) && CONFIG_UART_CHANNEL

#define MONITOR_UART_DMA_ENABLE

#ifndef CONFIG_USE_CONSOLE_UART
#define MONITOR_UART_BASE            HPM_UART2
#define MONITOR_UART_CLK_NAME        clock_uart2
#define MONITOR_UART_IRQ             IRQn_UART2
#define MONITOR_UART_BAUDRATE        (2000000UL)//(115200UL)

#ifdef MONITOR_UART_DMA_ENABLE
#define MONITOR_UART_TX_DMA_REQ        HPM_DMA_SRC_UART2_TX
#define MONITOR_UART_RX_DMA_REQ        HPM_DMA_SRC_UART2_RX
#endif

#else
#define MONITOR_UART_BASE            BOARD_CONSOLE_UART_BASE
#define MONITOR_UART_CLK_NAME        BOARD_CONSOLE_UART_CLK_NAME
#define MONITOR_UART_IRQ             BOARD_CONSOLE_UART_IRQ
#define MONITOR_UART_BAUDRATE        BOARD_CONSOLE_UART_BAUDRATE

#ifdef MONITOR_UART_DMA_ENABLE
#define MONITOR_UART_TX_DMA_REQ      BOARD_CONSOLE_UART_TX_DMA_REQ
#define MONITOR_UART_RX_DMA_REQ      BOARD_CONSOLE_UART_RX_DMA_REQ
#endif
#endif

#ifdef MONITOR_UART_DMA_ENABLE
#define MONITOR_UART_DMA_CONTROLLER    HPM_HDMA
#define MONITOR_UART_DMAMUX_CONTROLLER HPM_DMAMUX
#define MONITOR_UART_TX_DMA_CHN        (0U)
#define MONITOR_UART_RX_DMA_CHN        (1U)
#define MONITOR_UART_TX_DMAMUX_CHN     DMA_SOC_CHN_TO_DMAMUX_CHN(MONITOR_UART_DMA_CONTROLLER, MONITOR_UART_TX_DMA_CHN)
#define MONITOR_UART_RX_DMAMUX_CHN     DMA_SOC_CHN_TO_DMAMUX_CHN(MONITOR_UART_DMA_CONTROLLER, MONITOR_UART_RX_DMA_CHN)
#define MONITOR_UART_DMA_IRQ           IRQn_HDMA
#endif

#endif

#if defined(CONFIG_USB_CHANNEL) && CONFIG_USB_CHANNEL

#define CONFIG_USB_POLLING_ENABLE

#include "usb_config.h"
#define MONITOR_USB_BASE             CONFIG_HPM_USBD_BASE
#define MONITOR_USB_BUSID            0
#define MONITOR_USB_IRQ              CONFIG_HPM_USBD_IRQn
#define MONITOR_USB_PRIORITY         2

#endif

21.7. 核心代码实现

  • 定义ADC的触发源PWM和使用的互联管理器

#define BOARD_APP_ADC16_PMT_PWM         HPM_PWM0
#define BOARD_APP_ADC16_PMT_TRGM        HPM_TRGM0
#define BOARD_APP_ADC16_PMT_TRGM_IN     HPM_TRGM0_INPUT_SRC_PWM0_CH8REF
#define BOARD_APP_ADC16_PMT_TRGM_OUT    TRGM_TRGOCFG_ADCX_PTRGI0A

  • 定义ADC的采样率和每次传输的数据长度

#define APP_ADC16_DMA_BUFF_LEN_IN_BYTES   (1024U)
#define APP_ADC16_TCP_SEND_SIZE           (APP_ADC16_DMA_BUFF_LEN_IN_BYTES*sizeof(uint16_t))

  • 用户自定义通道定义

MONITOR_DEFINE_GLOBAL_VAR(adc_ch, 0, uint16_t, ADC_SAMPLE_FREQ, APP_ADC16_DMA_BUFF_LEN_IN_BYTES);
  • MONITOR对ADC采样发送

static void monitor_adc_handle(void)
{
    if (adc_get_done(0) && adc_get_done(1))
    {
        printf("adc dual buff full up!\r\n");
    }
    if (adc_get_done(0) && monitor_report_ch_is_released(0))
    {
        adc_clear_done(0);
        monitor_channel_report_array(0, adc_get_buf_addr_point(0), APP_ADC16_DMA_BUFF_LEN_IN_BYTES);
    }
    else if (adc_get_done(1) && monitor_report_ch_is_released(0))
    {
        adc_clear_done(1);
        monitor_channel_report_array(0, adc_get_buf_addr_point(1), APP_ADC16_DMA_BUFF_LEN_IN_BYTES);
    }
}
  • DEMO例程

int main(void)
{
    board_init();
    printf("monitor adc demo!\r\n");
    printf("__DATE__:%s, __TIME__:%s\r\n", __DATE__, __TIME__);

    monitor_init();

    adc_pmt_auto_config(ADC_SAMPLE_FREQ);
    while (1)
    {
        monitor_adc_handle();
        monitor_handle();
    }
    return 0;
}

21.8. 工程路径

  • 工程路径:monitor_adc/software/hpm_monitor

21.9. 工程构建

  • windows下工程构建\n WIN构建

  • linux工程构建编译

    //切换到示例应用目录
    cd hpm_apps\apps\monitor_adc\software\hpm_monitor
    //创建build目录
    mkdir build
    //切换目录到"build"
    cd build
    //Ninja-build产生构建文件
    cmake -GNinja  -DBOARD=hpm6300evk -DCMAKE_BUILD_TYPE=flash_xip ..
    //编译
    ninja

21.10. 硬件设置

  • 本方案使用的hpm6300evk板。

  • 用户可以使用其他evk板,注意修改对应的pin脚。

  • hpm6300evk usb/uart连接PC

  • hpm6300evk adc pin 和 hpm6200evk(DAC数模转换) dac pin连接。

  • hpm6200evk 烧录DAC 例程,直接运行三角波发波,hpm6300evk adc 采集; had_env

21.11. 工程运行

  • 运行工程

  • 使用串口助手观察是否有报错的日志。

  • PC运行HPMicroMonitorStudio工具。

  • 设置HPMicroMonitorStudio采样adc_ch数据,示波器监控adc波形。

21.12. 上位机配置

详细配置可查看hpm_monitor服务说明

  1. HPMicroMonitorStudio 配置

    • 打开 HPMicroMonitorStudio 工具

    • 选择正确的通信端口(USB 或 COM 端口)

    • 设置波特率(如使用 UART)

    • 连接设备

  2. 波形显示配置

    • 添加波形显

    • 选择 adc_ch

    • 启动实时显示 monitor_config_1 monitor_cofnig_2

21.13. 运行效果

monitor_run_1

21.14. 注意事项

  • 当出现波形断帧时,说明传输存在丢包等情况。当前HPMicroMonitorStudio工具性能还在持续优化中,可适当降低ADC采样频率。