本文章旨在評估使用 Zephyr RTOS 在 Renesas FPB-RA6E2 開發(fā)板上實現 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. 軟件環(huán)境配置
2.1 Device Tree Overlay (app.overlay)
設備樹用于定義外設的物理引腳綁定和初始狀態(tài)。以下是關鍵配置:
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 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 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函數輸出模擬電壓。 - 通過循環(huán)生成鋸齒波或三角波。
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)
/* 每次循環(huán)增加的占空比百分數 */
#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函數調整占空比。 - 通過循環(huán)實現占空比的動態(tài)變化。
3.2 關鍵 API 使用
以下是代碼中使用的關鍵 API:
ADC
int adc_read(const struct device *dev, const struct adc_sequence *sequence);
dev: ADC 設備句柄。sequence: 包含通道、緩沖區(qū)和采樣時間的配置結構體。
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 輸出波形
- 初始狀態(tài) : DAC 輸出 0V。
- 運行時 : 生成鋸齒波或三角波,頻率由延時控制。
- 視覺效果 : 使用示波器觀測 P014 引腳,應看到穩(wěn)定的波形。

4.3 PWM 占空比變化
- 初始狀態(tài) : PWM 輸出低電平。
- 運行時 : 占空比從 0% 到 100% 循環(huán)變化。
- 視覺效果 : 使用 LED 或示波器觀測 P408 引腳,亮度或波形應隨占空比變化。
5. 測評總結
本程序成功演示了 Renesas RA6E2 在 Zephyr RTOS 下的 ADC、DAC 和 PWM 外設控制。通過閉環(huán)測試驗證了數模轉換的準確性,并展示了嵌入式系統(tǒng)中“數字-模擬-數字”的完整轉換過程。代碼結構清晰,適配了最新的驅動 API,適用于初學者學習和開發(fā)者快速驗證硬件功能。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。
舉報投訴
-
單片機
+關注
關注
6078文章
45534瀏覽量
672293 -
adc
+關注
關注
100文章
7653瀏覽量
556561 -
開發(fā)板
+關注
關注
26文章
6345瀏覽量
119448 -
Zephyr
+關注
關注
0文章
61瀏覽量
6610
發(fā)布評論請先 登錄
相關推薦
熱點推薦
如何搭建瑞薩RA VS code開發(fā)環(huán)境
在上一篇文章“當RA MCU遇見Zephyr,打通嵌入式開發(fā)任督二脈!”中,我們介紹了Zephyr極具前景的發(fā)展趨勢以及瑞薩開發(fā)板對
當RA MCU遇見Zephyr系列(3)——在Vs code中配置Zephyr集成開發(fā)環(huán)境
RA生態(tài)工作室關注我們上一篇文章介紹了如何在VScode中使用瑞薩官方插件為RA芯片創(chuàng)建項目與項目調試,相信大家對RA在VScode中的開發(fā)
【瑞薩RA6E2】ADC、DAC 電壓輸入輸出
);
代碼中 dac 的值為 0 ~ 4095,對應 0 ~ 3.3v 電壓
【ADC 電壓輸入】
瑞薩 RA6E2 支持 12 位
發(fā)表于 11-10 01:29
【瑞薩RA6E2地奇星開發(fā)板試用】DAC 輸出指定電壓、ADC 電壓檢測
);
代碼中 dac 的值為 0 ~ 4095,對應 0 ~ 3.3v 電壓
【ADC 電壓輸入】
瑞薩 RA6E2 支持 12 位
發(fā)表于 12-19 18:30
【瑞薩FPB-RA6E2試用】【原創(chuàng)】【瑞薩RA × Zephyr開發(fā)板評測】+入門級任務測試1
很榮幸獲得了瑞薩RA × Zephyr瑞薩FPB-RA
發(fā)表于 12-24 23:52
【瑞薩FPB-RA6E2試用】【瑞薩RA × Zephyr開發(fā)板評測】Linux環(huán)境配置和初步試用
1. 前言
很榮幸獲得了瑞薩RA × Zephyr瑞薩FPB-
發(fā)表于 12-29 12:55
【瑞薩FPB-RA6E2試用】基礎功能使用2
的基礎功能模塊。
PWM 呼吸燈
前言
硬件:Renesas FPB-RA6E2 開發(fā)板
系統(tǒng) zephyr 4.2.0
目的:測評zephyr對瑞
發(fā)表于 12-30 17:08
【瑞薩FPB-RA6E2試用】【原創(chuàng)】基于【瑞薩FPB-RA6E2】Windows 下Zephyr RTOS自定義項目開發(fā)全流程(創(chuàng)建-編譯-燒錄-串口調試)
【原創(chuàng)】基于【瑞薩FPB-RA6E2】Windows 下Zephyr RTOS自定義項目開發(fā)全流程(創(chuàng)建 · 編譯 · 燒錄 · 串口調試)
《整體全流程演示》。
使用的硬件:
發(fā)表于 01-01 15:35
【瑞薩FPB-RA6E2試用】【瑞薩RA × Zephyr開發(fā)板評測】ADC、DAC、SPI、I2C 測試
1. 前言
在上一篇評測中,我們完成了開發(fā)環(huán)境搭建和基礎 GPIO 控制。作為一款高性能 MCU,RA6E2 的通信接口(SPI/I2C)和模擬外設(ADC/DAC)才是其核心競爭力的
發(fā)表于 01-12 00:01
【瑞薩RA × Zephyr開發(fā)板評測】基于PWM的電機轉速控制
項目使用瑞薩的FPB-RAE62作為控制板,主要功能如下:
ADC采集控制器數據來控制PWM波形的占空比
電機驅動板來控制的電機的轉速
PWM
發(fā)表于 01-16 01:19
【瑞薩FPB-RA6E2試用】【FPB-RA6E2】 DAC-ADC 回環(huán)測試:基于 Zephyr RTOS 的模擬信號通路驗證
Zephyr ADC / DAC API
調試設備樹 / pinctrl
校準 ADC / DAC 偏差
硬件 Bring-up 階段測試
發(fā)表于 01-16 15:22
【瑞薩FPB-RA6E2試用】【瑞薩RA × Zephyr開發(fā)板評測】基于PWM的電機轉速控制
項目使用瑞薩的FPB-RAE62作為控制板,主要功能如下:
ADC采集控制器數據來控制PWM波形的占空比
電機驅動板來控制的電機的轉速
PWM
發(fā)表于 01-17 16:18
【瑞薩RA × Zephyr評測】ADC、DAC和PWM
評論