【瑞萨RA × Zephyr评测】ADC、DAC和PWM
本文章旨在评估使用 Zephyr RTOS 在 Renesas FPB-RA6E2 开发板上实现 ADC(模数转换器)、DAC(数模转换器)和 PWM(脉宽调制)功能的应用。评估内容包括设备树配置、驱动初始化流程、主程序逻辑的详细解析,以及实验现象与数据分析。
1. 硬件连接与引脚定义
本实验涉及 ADC、DAC 和 PWM 的硬件资源,以下是关键引脚及其功能:
| 功能 | 物理引脚 (Pin) | 信号定义 | 接线说明 |
|---|---|---|---|
| ADC 输入 | P013 | Analog In (AN011) | 连接至 DAC 输出或外部信号源 |
| DAC 输出 | P014 | Analog Out (DA0) | 输出模拟电压 |
| PWM 输出 | P408 | PWM Signal | 使用 GPT1 定时器通道 1 |
2. 软件环境配置
2.1 Device Tree Overlay (app.overlay)
设备树用于定义外设的物理引脚绑定和初始状态。以下是关键配置:
ADC 配置
&adc0 {
status = "okay";
pinctrl-0 = < &adc0_default >;
pinctrl-names = "default";
channel@0 {
reg = < 0 >;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = < ADC_ACQ_TIME_DEFAULT >;
zephyr,resolution = < 12 >;
};
};
};
};
};
#### DAC 配置
&dac0 {
status = "okay";
pinctrl-0 = < &dac0_default >;
pinctrl-names = "default";
};
&pinctrl {
dac0_default: dac0_default {
group1 {
psels = < RA_PSEL(RA_PSEL_DAC, 0, 14) >;
renesas,analog-enable;
};
};
};
};
};
};
#### PWM 配置
&pwm1 {
status = "okay";
};
pwmleds {
compatible = "pwm-leds";
pwm_led_p408: pwm_led_p408 {
pwms = < &pwm1 1 PWM_MSEC(1) PWM_POLARITY_NORMAL >;
};
};
};
};
### 2.2 Kconfig 配置 (prj.conf)
确保启用了 ADC、DAC 和 PWM 驱动支持:
CONFIG_ADC=y
CONFIG_DAC=y
CONFIG_PWM=y
CONFIG_LOG=y
3. 代码逻辑分析
3.1 核心流程
ADC 流程
/* * 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 inpidually 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 readyn", 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;
}
}
while (1) {
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" mVn", val_mv);
}
}
k_msleep(1000);
}
return 0;
}
- 初始化 ADC 驱动并配置通道。
- 调用
adc_read函数读取模拟输入值。 - 将读取的数字值转换为实际电压(基于参考电压和分辨率)。
DAC 流程
/* * Copyright (c) 2020 Libre Solar Technologies GmbH * * SPDX-License-Identifier: Apache-2.0 */
#include < zephyr/kernel.h >
#include < zephyr/sys/printk.h >
#include < zephyr/drivers/dac.h >
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
#if (DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac) &&
DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac_channel_id) &&
DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac_resolution))
#define DAC_NODE DT_PHANDLE(ZEPHYR_USER_NODE, dac)
#define DAC_CHANNEL_ID DT_PROP(ZEPHYR_USER_NODE, dac_channel_id)
#define DAC_RESOLUTION DT_PROP(ZEPHYR_USER_NODE, dac_resolution)
#else
#error "Unsupported board: see README and check /zephyr,user node"
#define DAC_NODE DT_INVALID_NODE
#define DAC_CHANNEL_ID 0
#define DAC_RESOLUTION 0
#endif
static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE);
static const struct dac_channel_cfg dac_ch_cfg = {
.channel_id = DAC_CHANNEL_ID,
.resolution = DAC_RESOLUTION,
#if defined(CONFIG_DAC_BUFFER_NOT_SUPPORT)
.buffered = false,
#else
.buffered = true,
#endif /* CONFIG_DAC_BUFFER_NOT_SUPPORT */
};
int main(void) {
if (!device_is_ready(dac_dev)) {
printk("DAC device %s is not readyn", dac_dev- >name);
return 0;
}
int ret = dac_channel_setup(dac_dev, &dac_ch_cfg);
if (ret != 0) {
printk("Setting up of DAC channel failed with code %dn", ret);
return 0;
}
printk("Generating sawtooth signal at DAC channel %d.n",
DAC_CHANNEL_ID);
while (1) {
/* Number of valid DAC values, e.g. 4096 for 12-bit DAC */
const int dac_values = 1U < < DAC_RESOLUTION;
/* * 1 msec sleep leads to about 4 sec signal period for 12-bit * DACs. For DACs with lower resolution, sleep time needs to * be increased. * Make sure to sleep at least 1 msec even for future 16-bit * DACs (lowering signal frequency). */
const int sleep_time = 4096 / dac_values > 0 ?
4096 / dac_values : 1;
for (int i = 0; i < dac_values; i++) {
ret = dac_write_value(dac_dev, DAC_CHANNEL_ID, i);
if (ret != 0) {
printk("dac_write_value() failed with code %dn", ret);
return 0;
}
k_sleep(K_MSEC(sleep_time));
}
}
return 0;
}
- 初始化 DAC 驱动并设置通道分辨率。
- 调用
dac_write_value函数输出模拟电压。 - 通过循环生成锯齿波或三角波。
PWM 流程
/* * Copyright (c) 2016 Intel Corporation * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */
#include < zephyr/kernel.h >
#include < zephyr/sys/printk.h >
#include < zephyr/device.h >
#include < zephyr/drivers/pwm.h >
/* * 获取设备树中的 pwm-led0 别名 * 注意:根据之前的 Overlay 配置,这对应 P408 引脚 */
static const struct pwm_dt_spec pwm_dev = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));
#define PERIOD PWM_MSEC(1)
/* 每次循环增加的占空比百分数 */
#define STEP 5
/* 每次速度变化的间隔时间 (毫秒) */
#define SLEEP_MS 500
int main(void)
{
int ret;
uint8_t duty_cycle = 0; // 当前占空比 (0-100)
uint32_t pulse_width = 0; // 实际脉宽时间
if (!pwm_is_ready_dt(&pwm_dev)) {
printk("Error: PWM device %s is not readyn",
pwm_dev.dev- >name);
return 0;
}
printk("Starting pwm control on channel %d...n", pwm_dev.channel);
ret = pwm_set_dt(&pwm_dev, PERIOD, 0);
if (ret) {
printk("Error: PWM device does not support period %lun", PERIOD);
return 0;
}
while (1) {
/* 计算脉宽: (周期 * 百分比) / 100 */
pulse_width = (uint32_t)((uint64_t)PERIOD * duty_cycle / 100U);
/* 设置 PWM: 周期固定,改变脉宽 */
ret = pwm_set_dt(&pwm_dev, PERIOD, pulse_width);
if (ret) {
printk("Error %d: failed to set pulse widthn", ret);
return 0;
}
/* 增加速度 */
duty_cycle += STEP;
/* 如果超过 100%,重置为 0 */
if (duty_cycle > 100) {
duty_cycle = 0;
printk(" > > Resetting cycle <
- 初始化 PWM 驱动并设置周期。
- 调用
pwm_set_dt函数调整占空比。 - 通过循环实现占空比的动态变化。
3.2 关键 API 使用
以下是代码中使用的关键 API:
ADC
int adc_read(const struct device *dev, const struct adc_sequence *sequence);
dev: ADC 设备句柄。sequence: 包含通道、缓冲区和采样时间的配置结构体。
DAC
int dac_write_value(const struct device *dev, uint8_t channel, uint32_t value);
dev: DAC 设备句柄。channel: DAC 通道 ID。value: 输出的数字值。
PWM
int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period, uint32_t pulse);
spec: PWM 设备树绑定结构体。period: PWM 周期(纳秒)。pulse: PWM 脉宽(纳秒)。
4. 实验现象与数据分析
4.1 ADC 数据采集
终端应显示如下数据流:
ADC reading[0]:
* adc@40170000, channel 0: 0 = 0 mV
4.2 DAC 输出波形
- 初始状态 : DAC 输出 0V。
- 运行时 : 生成锯齿波或三角波,频率由延时控制。
- 视觉效果 : 使用示波器观测 P014 引脚,应看到稳定的波形。

4.3 PWM 占空比变化
- 初始状态 : PWM 输出低电平。
- 运行时 : 占空比从 0% 到 100% 循环变化。
- 视觉效果 : 使用 LED 或示波器观测 P408 引脚,亮度或波形应随占空比变化。
5. 测评总结
本程序成功演示了 Renesas RA6E2 在 Zephyr RTOS 下的 ADC、DAC 和 PWM 外设控制。通过闭环测试验证了数模转换的准确性,并展示了嵌入式系统中“数字-模拟-数字”的完整转换过程。代码结构清晰,适配了最新的驱动 API,适用于初学者学习和开发者快速验证硬件功能。
- 随机文章
- 热门文章
- 热评文章
- “斜杠城市”浙江龙港遇见“斜杠青年”,“斜杠城市”浙江龙港遇见“斜杠青年”
- 全球唯一大熊猫三胞胎后代“妹珠”迎来一周岁生日,全球唯一大熊猫三胞胎后代“妹珠”迎来一周岁生日
- 江苏大剧院原创民族舞剧《红楼梦》台北首演,江苏大剧院原创民族舞剧《红楼梦》台北首演
- 微医阿里云达成战略合作,共建AI医疗基座,微医阿里云达成战略合作,共建AI医疗基座
- 全球化能力持续进阶:海信连续9年位居中国全球化品牌十强,全球化能力持续进阶:海信连续9年位居中国全球化品牌十强
- 内塔尼亚胡:以色列有能力打击伊朗所有核设施,内塔尼亚胡:以色列有能力打击伊朗所有核设施
- 打造高质量中丹人文交流平台——“中国与丹麦跨文化交流的过去与未来暨庆祝中丹建交75周年”学术研讨会在京举行,打造高质量中丹人文交流平台——“中国与丹麦跨文化交流的过去与未来暨庆祝中丹建交75周年”学术研讨会在京举行
- 通宇通讯(002792):召开2025年第二次临时股东大会的通知
- 4公司获得增持评级-更新中
- 上半年港股募资规模登顶全球 两地证监会正考虑全面优化港股通
- 启迪环境(000826):2024年年度股东大会决议
- [担保]朗坤科技(301305):为子公司提供担保事项的进展公告
- 杭州高新(300478):累积投票实施细则
- 1[担保]中青旅(600138):中青旅为控股子公司提供担保
- 2北京中轴线篆刻作品在故宫展出北京中轴线篆刻作品在故宫展出
- 3IPC-6921有机封装基板国际标准即将落地
- 4“猪王”“肉王”争锋 牧原双汇互抢地盘
- 5IoT设备账号归属操作秘籍:专属固件全攻略来啦!
- 6英国投资代表团走进数贸会 探数字合作新机遇,英国投资代表团走进数贸会 探数字合作新机遇
- 7港股午评|恒生指数早盘涨1.88% 恒生生物科技指数大涨3.77%
- 8泰国王太后去世:总理变更东盟行程,或影响泰柬和平协议签署
- 9国产首台28 纳米关键尺寸电子束量测量产设备出机
- 102025上海世界移动通信大会:机器人纷纷搬出“看家本领”,2025上海世界移动通信大会:机器人纷纷搬出“看家本领”
- 11富煌钢构(002743):发行股份及支付现金购买资产并募集配套资金暨关联交易的进展公告
- 12《〈黄河大合唱〉的故事》(中英双语插图本)新书发布,《〈黄河大合唱〉的故事》(中英双语插图本)新书发布
- 13个人购机器人最高优惠1500元 北京首办机器人消费节
- 1第二十三届“海创会”签约项目总投资超300亿元,第二十三届“海创会”签约项目总投资超300亿元
- 220个项目在广州南沙集中签约 总投资逾154亿元,20个项目在广州南沙集中签约 总投资逾154亿元
- 3空调一年没用开启前最好清洗一下丨中新真探,空调一年没用开启前最好清洗一下丨中新真探
- 4求职遇到“招转贷”怎么办?人社部回应,求职遇到“招转贷”怎么办?人社部回应
- 5京津冀文化产业协同发展天津中心成立,京津冀文化产业协同发展天津中心成立
- 6吉林延边推动地方特产开拓韩国市场,吉林延边推动地方特产开拓韩国市场
- 7上海文史馆馆员书画作品展启幕 展现“江山如此多娇”,上海文史馆馆员书画作品展启幕 展现“江山如此多娇”
- 8湖南锂资源创新应用大会在临武举行 展示5项新科技成果,湖南锂资源创新应用大会在临武举行 展示5项新科技成果
- 9宁夏铁路部门开辟助农增收“黄金通道”,宁夏铁路部门开辟助农增收“黄金通道”
- 10广西恐龙奥秘科学馆启幕 打造AI+数智化科普新范式,广西恐龙奥秘科学馆启幕 打造AI+数智化科普新范式
- 11在廊坊买全球:“一站式”畅享世界好物,在廊坊买全球:“一站式”畅享世界好物
- 12湘粤合作发展避暑康养产业 共拓大湾区市场,湘粤合作发展避暑康养产业 共拓大湾区市场
- 132021年以来广东累计减少松材线虫病发生面积超百万亩,2021年以来广东累计减少松材线虫病发生面积超百万亩
你可能感兴趣的文章
- 【瑞萨RA × Zephyr评测】ADC、DAC和PWM
- PD快充取电芯片XSP26支持多种快充协议和识别电脑传输数据
- iC-Haus磁性离轴绝对位置编码器芯片iC-MUE产品介绍
- 基于图扑 HT 数字孪生 3D 风电场可视化系统实现解析
- ProfiNet转DeviceNet模块:现代食品包装1500产线堡盟FHDK 10P6101编码器实时通讯案例
- 耐达讯自动化赋能:Canopen转Profibus网关水泵连接新范式
- 撷发科技在2026年CES上重点展示AIVO边缘AI平台,助力在交通安全、农业及自主系统领域实现可扩展部署
- 深入解读乐鑫ESP32-S3,如何以单芯片搞定AIoT终端设备的智能交互
- 【FMC129】基于 VITA57.1 标准的 JESD204B 接口 8 通道 125MSPS 16 位 AD 采集子卡模块
- AI+MES:机械加工、设备组装行业迈向智能制造
- IPC-6921有机封装基板国际标准即将落地
- 总部管不好分店能耗?安科瑞 EIOT:一个平台掌控所有门店能源数据
- 高速接口如何选用低电容TVS管?信号完整性与防护性的双重考量
- 如何高效构建与测试非结构化道路场景?
- 功率半导体销售培训手册:电力电子核心技术与SiC碳化硅功率器件的应用
- 极海G32R501实时控制MCU在AI服务器电源中的应用