[评测&赛事] 【瑞萨RA × Zephyr评测】多通道ADC电压计

[复制链接]
47|1
无垠的广袤 发表于 2026-4-25 20:34 | 显示全部楼层 |阅读模式
, , , , , uart
[i=s] 本帖最后由 无垠的广袤 于 2026-4-27 13:11 编辑 [/i]

【瑞萨RA × Zephyr评测】多通道ADC电压计

本文介绍了瑞萨 FPB-RA6E2 开发板使用 Zephyr 开发环境和 VS Code 获取多通道 ADC 电压并串口打印的项目设计。

项目介绍

  • 准备工作:硬件连接、开发环境搭建等;
  • 工程代码:流程图、关键代码、配置文件等;
  • 编译上传:工程编译、固件上传等流程;
  • 效果演示:使用串口调试工具获取多通道 ADC 电压数据。

ADC

模数转换器 (Analog-to-Digital Converter, ADC) 是指将连续变化的模拟信号转换为离散的数字信号的器件。

ADC_diagram.jpg

ADC 主要包括采样保持和量化编码;

  • 将模拟信号采样,数据点转化为数字量;
  • 根据精度、动态范围等多个角度选择所需要的二进制编码方式,量化后的信号为有限个离散幅度值;

RA6E2 内置双路 12 位 SAR 模数转换器(ADC0 / ADC1),将模拟电压转为数字信号。

  • ADC0 有 13 个 ADC 通道,ADC1有 16 个 ADC 通道;
  • 支持单次 / 连续 / 分组扫描多种采样模式;
  • 最高单通道约 1.9 MSPS 高速转换;
  • 支持外部 3.3V 参考或内部 1.18V 基准;
  • 输入范围 0-3.3V;

硬件连接

FPB-RA6E2 FPB-RA6E2
AN000 GND
AN001 3V3
AN002 empty

实物连接

connect_adc_voltage.jpg

环境搭建

流程图

flowchart_adc_dt.jpg

工程创建

  • 点击左侧 Projects 标签页的新建工程按钮;
  • 在弹出的检索框中搜索 adc_dt 示例工程,回车加载;

vscode_zephyr_new_project_blink.jpg

  • 点击添加 Add Build 构建方案,选择 Zephy Direction Only,选择目标开发板 fpb_ra6e2 ,其他配置选项 Don't Set ;

vscode_zephyr_projects_board.jpg

  • 点击添加 Runner,选择 Jlink,回车确认;

工程代码

打开 .\Zephyr\adc_dt\src\main.c 主程序文件,代码如下

/*
 * Copyright (c) 2020 Libre Solar Technologies GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>

#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
	!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
#error "No suitable devicetree overlay specified"
#endif

#define DT_SPEC_AND_COMMA(node_id, prop, idx) \
	ADC_DT_SPEC_GET_BY_IDX(node_id, idx),

/* Data of ADC io-channels specified in devicetree. */
static const struct adc_dt_spec adc_channels[] = {
	DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
			     DT_SPEC_AND_COMMA)
};

int main(void)
{
	int err;
	uint32_t count = 0;
	uint16_t buf;
	struct adc_sequence sequence = {
		.buffer = &buf,
		/* buffer size in bytes, not number of samples */
		.buffer_size = sizeof(buf),
	};

	/* Configure channels individually prior to sampling. */
	for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
		if (!adc_is_ready_dt(&adc_channels[i])) {
			printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
			return 0;
		}

		err = adc_channel_setup_dt(&adc_channels[i]);
		if (err < 0) {
			printk("Could not setup channel #%d (%d)\n", i, err);
			return 0;
		}
	}

#ifndef CONFIG_COVERAGE
	while (1) {
#else
	for (int k = 0; k < 10; k++) {
#endif
		printk("ADC reading[%u]:\n", count++);
		for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
			int32_t val_mv;

			printk("- %s, channel %d: ",
			       adc_channels[i].dev->name,
			       adc_channels[i].channel_id);

			(void)adc_sequence_init_dt(&adc_channels[i], &sequence);

			err = adc_read_dt(&adc_channels[i], &sequence);
			if (err < 0) {
				printk("Could not read (%d)\n", err);
				continue;
			}

			/*
			 * If using differential mode, the 16 bit value
			 * in the ADC sample buffer should be a signed 2's
			 * complement value.
			 */
			if (adc_channels[i].channel_cfg.differential) {
				val_mv = (int32_t)((int16_t)buf);
			} else {
				val_mv = (int32_t)buf;
			}
			printk("%"PRId32, val_mv);
			err = adc_raw_to_millivolts_dt(&adc_channels[i],
						       &val_mv);
			/* conversion to mV may not be supported, skip if not */
			if (err < 0) {
				printk(" (value in mV not available)\n");
			} else {
				printk(" = %"PRId32" mV\n", val_mv);
			}
		}

		k_sleep(K_MSEC(1000));
	}
	return 0;
}

保存代码。

配置文件

新建 .\Zephyr\adc_dt\boards\fpb_ra6e2.overlay 文件,并添加如下代码

/ {
	zephyr,user {
		io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>;
	};
};

&adc0 {
	status = "okay";
	#address-cells = <1>;
	#size-cells = <0>;

	channel@0 {
		reg = <0>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,resolution = <12>;
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,vref-mv = <3300>;
	};

	channel@1 {
		reg = <1>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,resolution = <12>;
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,vref-mv = <3300>;
	};

	channel@2 {
		reg = <2>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,resolution = <12>;
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,vref-mv = <3300>;
	};
};

保存代码。

编译上传

代码和配置完成后,点击 Devicetree Overlay 选项添加配置文件,

  • 选择 .\Zephyr\adc_dt\boards\fpb_ra6e2.overlay 配置文件;
  • 在顶部窗口选择覆盖板端文件;

adc_overlay.jpg

  • 点击 Build 执行工程编译;
  • 点击 Flash jlink 执行固件上传。

效果演示

使用 Serial Monitor 插件连接 J-LINK 虚拟串口,波特率115200,可获取引脚对应的 ADC 电压数据;

adc_print_voltage.jpg

通过接地或电源可采集实时电压值;

adc_print_GVE.jpg

总结

本文介绍了瑞萨 FPB-RA6E2 开发板使用 Zephyr 开发环境结合 VS Code 获取多通道 ADC 电压并串口打印的项目设计,为相关产品的快速开发和应用设计提供了参考。

劫灰飞尽古今平 发表于 2026-4-26 19:36 | 显示全部楼层
RA6E2 的 IO 口最高耐压只有 3.6V,千万别直接把 5V、12V 这种电压接到 ADC 引脚上,我见过新手直接把 5V 电源怼上去,当场就把芯片烧了,血的教训。要测更高电压,一定要加分压电阻,比如用 100k+100k 的电阻把 5V 降到 2.5V,再在代码里把分压系数乘回去
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

101

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部
0