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. 方案特点
高性能数据采集:
支持高达 2MSPS 的 16 位 ADC 采样
采用 PWM 触发,采样时间精确可控
DMA 自动搬运,零 CPU 干预
实时数据监控:
通过 hpm_monitor 服务实时传输 ADC 数据
支持 USB/UART/ENET 三种通信接口
低延迟、高带宽数据传输
灵活的数据处理:
支持多种采样模式(Notify/Stream/Buffer)
可自定义数据上报频率和格式
支持多通道监控
用户友好:
PC 端图形化界面实时显示波形
参数实时可调
21.4. 框图及调用流程

21.5. 硬件配置
开发板支持 支持全系列HPM EVK开发板。 当前以HPM6300EVK验证,其余EVK需手动微调程序或引脚。
通信接口选择
ENET TCP:适合与 PC 上位机通过网络直连调试
USB CDC:带宽高,连接方便
UART:可选,最高支持 10Mbps 波特率
21.6. 软件配置
工程配置 (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()
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

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 采集;

21.11. 工程运行
运行工程
使用串口助手观察是否有报错的日志。
PC运行HPMicroMonitorStudio工具。
设置HPMicroMonitorStudio采样adc_ch数据,示波器监控adc波形。
21.12. 上位机配置
详细配置可查看hpm_monitor服务说明
HPMicroMonitorStudio 配置
打开 HPMicroMonitorStudio 工具
选择正确的通信端口(USB 或 COM 端口)
设置波特率(如使用 UART)
连接设备
波形显示配置
添加波形显
选择 adc_ch
启动实时显示

21.13. 运行效果

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