外观
flexbus ad7606 dma 示例
2026-04-17
本文将详细介绍如何通过FlexBus接口驱动 AD7606 模数转换器(ADC) 采集数据,并利用DMA方式将采集到的数据搬运至内存,最终通过 串口 发送至VOFA+上位机进行波形显示。
AD7606 简介
AD7606是一款多通道同步采样的高精度 ADC,支持并行总线接口(包括标准并行和串行模式),能够在高达 200kSPS 的采样率下实现 16 位分辨率转换。 该器件内置输入模拟前端、采样保持电路和数字滤波器,适用于电力系统监测、工业测控和信号采集等场景。
AD7606 特性
- 同步采样,支持 8 通道 / 16 位分辨率
- 并行 / 串行接口可选(本文以 并行模式 为例)
- 内置 ±10V 输入范围,支持过采样比率配置
- 具备 BUSY、RESET、CONVST、CS 等控制信号
硬件连接
RC-PI-3506 开发板与扩展板需要连接,数据输出串口以及通道连接如下图所示:

DMA 读取 AD7606 数据展示
本示例展示如何通过DMA传输读取的采样数据,通过串口 3 输出数据,VOFA+ 显示数据波形图。
VOFA+ 使用
具体使用方法参见:VOFA-Plus 上位机
本示例使用的控件
- 波形图
- bound_bt(仅用于显示通道名称)
本示例使用的数据引擎
- FireWater
AD7606 数据
通过查阅AD7606的数据手册,可以了解到其并行接口输出为 16 位补码格式,一次采样会输出 8 个通道数据,每个通道占 16bit。 数据读取需在 BUSY 拉低 后,依次通过 FlexBus 总线读取,然后使用DMA传输采集的数据。
创建工程点击展开
依次点击 “文件” -> “新建” -> "RT-Thread RuiChing App 项目"。

在弹出新建向导中选择 开发版 、BSP: 、示例 、 调试器/下载器。选择好之后点击 “完成”。

点击 “完成” 后,等待工程创建完成。

创建完成。

构建工程点击展开
单击工程使工程进入 Active-Debug 模式。

点击工具栏上的构建按钮进行工程编译。

构建成功后,会显示构建成功的信息。

固件下载点击展开
固化设备树

固化 APP

AD7606 DMA 示例相关代码说明
rt_adc_control:该函数实现了 AD7606 配置功能,包括 DMA 启动以及停止。#define AD7606_DATA_P_CH:该宏表示每个通道采集的数据量。#define AD7606_USE_CHANNELS:该宏表示需要采集的具体通道,注意编号需从 1 开始。
核心示例代码
adc_sample.c
#include "rtthread.h"
#include "rtdevice.h"
#include "drv_ad7606.h"
#define AD7606_DEV_NAME "adc0"
#define AD7606_DATA_P_CH (10) // 每个通道数据点数
#define AD7606_DATA_MAX_NUM (AD7606_DATA_P_CH * AD7606_MAX_CHANNELS) // 最大数据量
#define AD7606_USE_CHANNELS (AD7606_CHANNEL(1) | AD7606_CHANNEL(2) | AD7606_CHANNEL(3) | \
AD7606_CHANNEL(4) | AD7606_CHANNEL(5) | AD7606_CHANNEL(6) | \
AD7606_CHANNEL(7) | AD7606_CHANNEL(8)) // 具体使用的通道 注意通道编号需从1开始
#define AD7606_RANGE_IS_10V (0) // 根据硬件RANGE引脚设定:1=±10V,0=±5V
#define AD7606_REFER_VOLTAGE (0) // 参考电压(mv)
#if AD7606_RANGE_IS_10V
#define FULL_SCALE_MV (10000) // ±10V 量程
#else
#define FULL_SCALE_MV (5000) // ±5V 量程
#endif
#define UART_NAME "uart3"
#define INT_TO_FLOAT(in1, out, pos, seg) \
{ \
int len = 0; \
if ((in1) < 0) \
{ \
(len) = rt_sprintf((out) + (pos), "-%d.%03d%s", (-(in1)) / 1000, (-(in1)) % 1000, (seg)); \
} \
else \
{ \
(len) = rt_sprintf((out) + (pos), "%d.%03d%s", (in1) / 1000, (in1) % 1000, (seg)); \
} \
(pos) += len; \
}
static rt_device_t _serial = RT_NULL;
static rt_adc_device_t _adc = RT_NULL;
static volatile rt_bool_t _run_flag = RT_FALSE;
static rt_thread_t _adc_thread = RT_NULL;
static void _adc_vol_show_thread(void *parameter)
{
char out_str[64];
rt_uint8_t ch_num = 0, pos = 0;
int j = 0, i = 0;
rt_err_t ret = RT_EOK;
rt_int16_t raw_val[AD7606_DATA_MAX_NUM];
rt_int32_t voltage[AD7606_DATA_MAX_NUM];
struct rt_adc_dma_cfg adc_dma_cfg;
struct serial_configure uart_cfg;
uart_cfg.baud_rate = BAUD_RATE_115200;
uart_cfg.data_bits = DATA_BITS_8;
uart_cfg.stop_bits = STOP_BITS_1;
uart_cfg.parity = PARITY_NONE;
uart_cfg.invert = NRZ_NORMAL;
uart_cfg.bufsz = 4096;
uart_cfg.flowcontrol = 0;
rt_device_control(_serial, RT_DEVICE_CTRL_CONFIG, &uart_cfg);
rt_device_open(_serial, RT_DEVICE_OFLAG_RDWR);
ret = rt_adc_enable(_adc, 0);
if (ret != RT_EOK)
{
rt_kprintf("enable adc fail: %d\n", ret);
_run_flag = RT_FALSE;
}
adc_dma_cfg.use_channels = AD7606_USE_CHANNELS;
adc_dma_cfg.buf_len = sizeof(raw_val);
adc_dma_cfg.dst_addr = (rt_uint16_t *)raw_val;
rt_adc_control(_adc, RT_ADC_CMD_DMA_START, &adc_dma_cfg);
if (ret != RT_EOK)
{
rt_kprintf("enable adc fail: %d\n", ret);
_run_flag = RT_FALSE;
}
for (i = 1; i <= AD7606_MAX_CHANNELS; i++)
{
if (AD7606_USE_CHANNELS & AD7606_CHANNEL(i))
{
ch_num++;
}
}
while (_run_flag)
{
for (j = 0; j < AD7606_DATA_P_CH; j++)
{
rt_memset(out_str, 0, sizeof(out_str));
pos = 0;
for (i = 0; i < ch_num; i++)
{
voltage[j * ch_num + i] = ((rt_int32_t)raw_val[j * ch_num + i] *
(rt_int32_t)FULL_SCALE_MV) / 32767 + AD7606_REFER_VOLTAGE;
if (i == ch_num - 1)
{
INT_TO_FLOAT(voltage[j * ch_num + i], out_str, pos, "\r\n");
}
else
{
INT_TO_FLOAT(voltage[j * ch_num + i], out_str, pos, ",");
}
}
rt_device_write(_serial, 0, out_str, strlen(out_str));
}
rt_thread_delay(10);
}
if (_serial != RT_NULL)
{
rt_device_close(_serial);
}
if (_adc != RT_NULL)
{
rt_adc_control(_adc, RT_ADC_CMD_DMA_STOP, RT_NULL);
rt_adc_disable(_adc, 0);
}
_serial = RT_NULL;
_adc = RT_NULL;
_adc_thread = RT_NULL;
}
int adc_vol_show(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
if (argc > 1)
{
if (rt_strcmp(argv[1], "--stop") == 0)
{
_run_flag = RT_FALSE;
return RT_EOK;
}
else
{
_run_flag = RT_TRUE;
}
}
else
{
_run_flag = RT_TRUE;
}
_serial = rt_device_find(UART_NAME);
if (_serial == RT_NULL)
{
rt_kprintf("can't find %s\n", UART_NAME);
goto exit;
}
_adc = (rt_adc_device_t)rt_device_find(AD7606_DEV_NAME);
if (!_adc)
{
rt_kprintf("can't find %s\n", AD7606_DEV_NAME);
goto exit;
}
if (_adc_thread != RT_NULL)
{
rt_kprintf("adc_vol_show is already running, use [adc_vol_show --stop] to stop\n");
return RT_EOK;
}
_adc_thread = rt_thread_create("adc_vol", _adc_vol_show_thread, RT_NULL, 2048, 16, 10);
if (_adc_thread == RT_NULL)
{
rt_kprintf("create thread failed\n");
goto exit;
}
rt_thread_startup(_adc_thread);
return ret;
exit:
ret = -RT_ERROR;
_run_flag = RT_FALSE;
return ret;
}运行程序
开发板运行程序后,给AD7606的通道1-4施加正弦波(频率:310Hz 、幅度:5V、偏移: 0v ),通道5-8施加正弦波(频率:310Hz 、幅度:10V、偏移: 0v ),然后在终端输入adc_vol_show命令,结果如下:
msh />adc_vol_show
adc_vol_show is running预期结果:
- 串口 3 打印数据 VOFA+ 显示对应波形

