
1.驱动程序
官方的驱动,内核太老了,话说他们这也不知道更新一下,费劲
提供源码ad4115_driver.cpp
#include "ad4115_driver.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <errno.h>
#include <time.h>
// ============ 寄存器地址 ============
#define AD4115_REG_COMMS 0x00
#define AD4115_REG_STATUS 0x00
#define AD4115_REG_ADC_MODE 0x01
#define AD4115_REG_INTERFACE_MODE 0x02
#define AD4115_REG_DATA 0x04
#define AD4115_REG_GPIO 0x06
#define AD4115_REG_ID 0x07
#define AD4115_REG_CH(x) (0x10 + (x))
#define AD4115_REG_SETUP(x) (0x20 + (x))
#define AD4115_REG_FILTER(x) (0x28 + (x))
// ============ 常量定义 ============
#define AD4115_ID 0x38D0
#define AD4115_ID_MASK 0xFFF0
#define AD4115_CH_ENABLE 0x8000
// ============ 差分通道 INPUT 编码表(关键修复!)===========
static const uint16_t diff_input_codes[8] = {
0x001, // CH0: VIN0+, VIN1-
0x043, // CH1: VIN2+, VIN3-
0x085, // CH2: VIN4+, VIN5-
0x0C7, // CH3: VIN6+, VIN7-
0x109, // CH4: VIN8+, VIN9-
0x14B, // CH5: VIN10+, VIN11-
0x18D, // CH6: VIN12+, VIN13-
0x1CF // CH7: VIN14+, VIN15-
};
// ============ 数据速率配置 ============
static const ad4115_data_rate_t ad4115_data_rates[] = {
{0, 24845000, "24.845 MSPS"},
{1, 24845000, "24.845 MSPS"},
{2, 20725000, "20.725 MSPS"},
{3, 20725000, "20.725 MSPS"},
{4, 15564000, "15.564 MSPS"},
{5, 13841000, "13.841 MSPS"},
{6, 10390000, "10.390 MSPS"},
{7, 10390000, "10.390 MSPS"},
{8, 4994000, "4.994 MSPS"},
{9, 2499000, "2.499 MSPS"},
{10, 1000000, "1.000 MSPS"},
{11, 500000, "500 kSPS"},
{12, 395500, "395.5 kSPS"},
{13, 200000, "200 kSPS"},
{14, 100000, "100 kSPS"},
{15, 59890, "59.89 kSPS"},
{16, 49920, "49.92 kSPS"},
{17, 20000, "20 kSPS"}, // ✅ 推荐:8 通道=每通道 2.5kSPS
{18, 16660, "16.66 kSPS"},
{19, 10000, "10 kSPS"},
{20, 5000, "5 kSPS"},
{21, 2500, "2.5 kSPS"},
{22, 2500, "2.5 kSPS"}
};
// ============ SPI 传输函数 ============
static int spi_transfer(ad4115_dev_t *dev, uint8_t *tx_buf, uint8_t *rx_buf, uint32_t len) {
if (!dev || dev->spi_fd < 0) {
return -1;
}
struct spi_ioc_transfer transfer;
memset(&transfer, 0, sizeof(transfer));
transfer.tx_buf = (unsigned long)tx_buf;
transfer.rx_buf = (unsigned long)rx_buf;
transfer.len = len;
transfer.speed_hz = dev->speed_hz;
transfer.delay_usecs = 0;
transfer.bits_per_word = dev->bits_per_word;
transfer.cs_change = 0;
int ret = ioctl(dev->spi_fd, SPI_IOC_MESSAGE(1), &transfer);
if (ret < 0) {
perror("SPI transfer failed");
}
return ret;
}
// ============ 设备复位(关键修复!)===========
static int ad4115_reset(ad4115_dev_t *dev) {
// 发送 64 个时钟周期的复位序列(CS=0, DIN=1)
uint8_t reset_buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t rx_buf[8] = {0};
int ret = spi_transfer(dev, reset_buf, rx_buf, 8);
if (ret < 0) {
return -1;
}
// 等待 500µs 让 LDO 稳定(数据手册要求)
usleep(1000);
return 0;
}
// ============ 读取寄存器 ============
static int ad4115_read_register(ad4115_dev_t *dev, uint8_t reg, uint8_t size, uint32_t *value) {
uint8_t tx_buf[5] = {0};
uint8_t rx_buf[5] = {0};
tx_buf[0] = 0x40 | (reg & 0x3F);
int ret = spi_transfer(dev, tx_buf, rx_buf, size + 1);
if (ret != (size + 1)) {
return -1;
}
*value = 0;
for (int i = 0; i < size; i++) {
*value = (*value << 8) | rx_buf[i + 1];
}
usleep(1); // 短暂延时,避免死等占用总线
return 0;
}
// ============ 写入寄存器 ============
static int ad4115_write_register(ad4115_dev_t *dev, uint8_t reg, uint8_t size, uint32_t value) {
uint8_t tx_buf[5] = {0};
uint8_t rx_buf[5] = {0};
tx_buf[0] = reg & 0x3F;
for (int i = 0; i < size; i++) {
tx_buf[size - i] = (value >> (8 * i)) & 0xFF;
}
int ret = spi_transfer(dev, tx_buf, rx_buf, size + 1);
if (ret != (size + 1)) {
return -1;
}
usleep(1); // 短暂延时,避免死等占用总线
return 0;
}
// ============ 通道配置(关键修复!)===========
static int ad4115_configure_channel(ad4115_dev_t *dev, int channel) {
if (channel < 0 || channel >= AD4115_MAX_CHANNELS) {
return -1;
}
// 通道配置寄存器格式(16 位):
// Bit 15: CH_EN (1=启用)
// Bits 14-12: SETUP_SEL (选择 Setup 0)
// Bits 11-10: Reserved
// Bits 9-0: INPUT[9:0] (差分输入编码)
uint16_t channel_config = AD4115_CH_ENABLE | // 启用通道
(0 << 12) | // 使用 Setup 0
diff_input_codes[channel]; // 正确的差分输入编码
int ret = ad4115_write_register(dev, AD4115_REG_CH(channel), 2, channel_config);
if (ret < 0) {
return ret;
}
dev->channels_enabled[channel] = true;
return 0;
}
// ============ 设备初始化(完整修复)===========
ad4115_dev_t* ad4115_init(const char* spi_device, uint32_t speed_hz) {
ad4115_dev_t* dev = (ad4115_dev_t*)malloc(sizeof(ad4115_dev_t));
if (!dev) {
return NULL;
}
memset(dev, 0, sizeof(ad4115_dev_t));
dev->spi_fd = open(spi_device, O_RDWR);
if (dev->spi_fd < 0) {
perror("Failed to open SPI device");
free(dev);
return NULL;
}
dev->speed_hz = speed_hz;
dev->mode = SPI_MODE_3; // AD4115 使用 SPI Mode 3
dev->bits_per_word = 8;
if (ioctl(dev->spi_fd, SPI_IOC_WR_MODE, &dev->mode) < 0) {
perror("Failed to set SPI mode");
close(dev->spi_fd);
free(dev);
return NULL;
}
if (ioctl(dev->spi_fd, SPI_IOC_WR_BITS_PER_WORD, &dev->bits_per_word) < 0) {
perror("Failed to set SPI bits per word");
close(dev->spi_fd);
free(dev);
return NULL;
}
if (ioctl(dev->spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &dev->speed_hz) < 0) {
perror("Failed to set SPI speed");
close(dev->spi_fd);
free(dev);
return NULL;
}
// ============ 设备复位(关键!)===========
printf("正在复位 AD4115...\n");
if (ad4115_reset(dev) < 0) {
printf("复位失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
// ============ 读取设备 ID ============
uint32_t id;
if (ad4115_read_register(dev, AD4115_REG_ID, 2, &id) < 0) {
printf("读取 ID 失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
dev->device_id = id & AD4115_ID_MASK;
printf("设备 ID: 0x%04X\n", dev->device_id);
if (dev->device_id != AD4115_ID) {
printf("ID 不匹配!期望 0x%04X, 实际 0x%04X\n", AD4115_ID, dev->device_id);
close(dev->spi_fd);
free(dev);
return NULL;
}
// ============ ADC 模式配置 ============
// Bit 15: REF_EN = 1 (启用内部参考)
// Bits 6-4: Mode = 000 (连续转换模式)
// Bits 3-2: CLOCKSEL = 00 (内部振荡器)
uint32_t adc_mode = (1 << 15) | // REF_EN
(0 << 6); // 连续转换模式
if (ad4115_write_register(dev, AD4115_REG_ADC_MODE, 2, adc_mode) < 0) {
printf("配置 ADC 模式失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
// ============ 接口模式配置(连续转换模式)===========
// Bit 6: DATA_STAT = 1 (读取数据时附加状态寄存器)
// Bit 7: CONTREAD = 0 (不使用连续读模式)
uint32_t if_mode = (1 << 6)|(0 << 7); // 只启用 DATA_STAT
if (ad4115_write_register(dev, AD4115_REG_INTERFACE_MODE, 2, if_mode) < 0) {
printf("配置接口模式失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
// ============ Setup 配置(关键修复!)===========
// Setup Configuration Register 0 (0x20)
// Bit 12: BI_UNIPOLAR = 1 (双极性)
// Bits 9-8: INBUF = 11 (启用输入缓冲器) ⚠️ 必须启用!
// Bits 5-4: REF_SEL = 10 (内部参考)
uint32_t setup_reg = (1 << 12) | // Bit 12: BI_UNIPOLAR = 1 (双极性)
(3 << 8) | // Bits 9-8: INBUF = 11 (输入缓冲器使能)
(2 << 4) | // Bits 5-4: REF_SEL = 10 (内部参考)
(1 << 5); // Bit 5: REFBUF0+ = 1 (参考缓冲使能)
for(uint8_t i=0;i<8;i++)
{
if (ad4115_write_register(dev, AD4115_REG_SETUP(i), 2, setup_reg) < 0) {
printf("配置 Setup 失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
}
// ============ 滤波器配置 ============
uint32_t filter_reg = (dev->data_rate_index & 0x1F);
for(uint8_t i=0;i<8;i++)
{
if (ad4115_write_register(dev, AD4115_REG_FILTER(i), 2, filter_reg) < 0) {
printf("配置滤波器失败!\n");
close(dev->spi_fd);
free(dev);
return NULL;
}
}
dev->num_channels = AD4115_MAX_CHANNELS;
printf("AD4115 初始化成功:SPI=%dHz, ID=0x%04X\n", speed_hz, dev->device_id);
return dev;
}
// ============ 设置数据速率 ============
ad4115_error_t ad4115_set_data_rate(ad4115_dev_t* dev, int rate_index) {
if (!dev) {
return AD4115_ERROR_INIT;
}
if (rate_index < 0 || rate_index >= AD4115_NUM_DATA_RATES) {
return AD4115_ERROR_CHANNEL;
}
uint32_t filter_reg = (rate_index & 0x1F);
for(uint8_t i=0;i<8;i++)
{
if (ad4115_write_register(dev, AD4115_REG_FILTER(i), 2, filter_reg) < 0) {
return AD4115_ERROR_SPI;
}
}
dev->data_rate_index = rate_index;
return AD4115_SUCCESS;
}
// ============ 设备反初始化 ============
void ad4115_deinit(ad4115_dev_t* dev) {
if (dev) {
if (dev->spi_fd >= 0) {
close(dev->spi_fd);
}
free(dev);
}
}
// ============ 读取传感器 ID ============
uint16_t ad4115_get_sensor_id(ad4115_dev_t* dev) {
if (!dev) return 0;
return dev->device_id;
}
// ============ 启用指定通道 ============
ad4115_error_t ad4115_enable_channel(ad4115_dev_t* dev, int channel) {
if (!dev || channel < 0 || channel >= AD4115_MAX_CHANNELS) {
return AD4115_ERROR_CHANNEL;
}
if (dev->channels_enabled[channel]) {
return AD4115_SUCCESS;
}
if (ad4115_configure_channel(dev, channel) < 0) {
return AD4115_ERROR_INIT;
}
return AD4115_SUCCESS;
}
// ============ 禁用指定通道 ============
ad4115_error_t ad4115_disable_channel(ad4115_dev_t* dev, int channel) {
if (!dev || channel < 0 || channel >= AD4115_MAX_CHANNELS) {
return AD4115_ERROR_CHANNEL;
}
if (!dev->channels_enabled[channel]) {
return AD4115_SUCCESS;
}
if (ad4115_write_register(dev, AD4115_REG_CH(channel), 2, 0) < 0) {
return AD4115_ERROR_SPI;
}
dev->channels_enabled[channel] = false;
return AD4115_SUCCESS;
}
// ============ 启用所有通道 ============
ad4115_error_t ad4115_enable_all_channels(ad4115_dev_t* dev) {
if (!dev) {
return AD4115_ERROR_INIT;
}
for (int channel = 0; channel < AD4115_MAX_CHANNELS; channel++) {
ad4115_error_t ret = ad4115_enable_channel(dev, channel);
if (ret != AD4115_SUCCESS) {
return ret;
}
}
return AD4115_SUCCESS;
}
// ============ 禁用所有通道 ============
ad4115_error_t ad4115_disable_all_channels(ad4115_dev_t* dev) {
if (!dev) {
return AD4115_ERROR_INIT;
}
for (int channel = 0; channel < AD4115_MAX_CHANNELS; channel++) {
ad4115_error_t ret = ad4115_disable_channel(dev, channel);
if (ret != AD4115_SUCCESS) {
return ret;
}
}
return AD4115_SUCCESS;
}
// ============ 获取当前数据速率 ============
unsigned int ad4115_get_data_rate(ad4115_dev_t* dev) {
if (!dev || dev->data_rate_index < 0 || dev->data_rate_index >= AD4115_NUM_DATA_RATES) {
return 0;
}
// 多通道模式下使用每通道速率
return ad4115_data_rates[dev->data_rate_index].rate_sps / 8;
}
// ============ 读取所有通道数据(严格按你的要求重写 + 调试日志)===========
ad4115_error_t ad4115_read_all_channels(ad4115_dev_t* dev, ad4115_sample_t* sample) {
if (!dev || !sample) {
return AD4115_ERROR_INIT;
}
int valid_channels = 0;
// 循环读取每个通道的数据
for (int i = 0; i < AD4115_MAX_CHANNELS; i++) {
// ==========================================
// 1. 手动轮询状态寄存器 (0x00),获取 RDY 和通道号
// ==========================================
uint8_t tx_stat[1] = {0x40}; // 0x40 | 0x00 (读状态寄存器命令)
uint8_t rx_stat[2] = {0}; // 1字节命令响应 + 1字节状态值
uint8_t channel_id = 0;
int is_ready = 0;
int poll_cnt = 0;
const int max_polls = 1000; // 超时保护 (~50ms)
while (!is_ready && poll_cnt < max_polls) {
if (spi_transfer(dev, tx_stat, rx_stat, 2) == 2) {
uint8_t status = rx_stat[1];
if ((status & 0x80) == 0) { // RDY Bit 7 = 0 表示转换完成
is_ready = 1;
channel_id = status & 0x0F; // Bits[3:0] 为当前通道号
}
}
poll_cnt++;
}
if (!is_ready) {
#if AD4115_DEBUG == 1
printf("[DBG] ✗ Loop %d: TIMEOUT after %d polls, skipping\n", i, poll_cnt);
#endif
continue; // 超时跳过本次,继续读下一个
}
// ==========================================
// 2. 读取数据寄存器 (0x04)
// ==========================================
#if AD4115_DEBUG == 1
printf("[DBG] Loop %d: Reading DATA register (ch_id=%d)...\n", i, channel_id);
#endif
// 注意:因 IFMODE 中 DATA_STAT=1,DOUT 会先输出 8位状态,再输出 24位数据
// 共 4 字节有效载荷。SPI 总传输长度 = 1(命令) + 4(载荷) = 5
uint8_t tx_data[1] = {0x44}; // 读数据寄存器命令
uint8_t rx_data[5] = {0}; // 接收缓冲区
if (spi_transfer(dev, tx_data, rx_data, 5) != 5) {
printf("[DBG] ✗ Loop %d: SPI transfer failed!\n", i);
continue; // SPI 传输失败,跳过
}
// 调试:打印原始接收数据
#if AD4115_DEBUG == 1
printf("[DBG] rx_data raw: [%02X][%02X][%02X][%02X][%02X]\n",
rx_data[0], rx_data[1], rx_data[2], rx_data[3], rx_data[4]);
#endif
// ==========================================
// 3. 解析 24 位 ADC 数据
// ==========================================
// rx_data[0]: 命令发送期间的返回字节(无效)
// rx_data[1]: 状态寄存器(与步骤1一致,此处忽略)
// rx_data[2]: 数据高8位 (D23-D16)
// rx_data[3]: 数据中8位 (D15-D8)
// rx_data[4]: 数据低8位 (D7-D0)
int32_t raw_value = ((int32_t)rx_data[2] << 16) |
((int32_t)rx_data[3] << 8) |
((int32_t)rx_data[4]);
// 24位有符号数符号扩展至32位
if (raw_value & 0x800000) {
raw_value |= 0xFF000000;
}
// ==========================================
// 4. 存入结构体
// ==========================================
#if AD4115_DEBUG == 1
printf("[DBG] Storing to sample->channels[%d]: valid=true\n", channel_id);
#endif
sample->raw_data[channel_id] = raw_value;
sample->valid[channel_id] = true;
valid_channels++;
}
return (valid_channels > 0) ? AD4115_SUCCESS : AD4115_ERROR_READ;
}
// ============ 转储所有寄存器(调试用)===========
ad4115_error_t ad4115_dump_all_registers(ad4115_dev_t* dev) {
if (!dev) {
return AD4115_ERROR_INIT;
}
printf("\n========== AD4115 寄存器转储 ==========\n");
printf("时间:%ld\n", time(NULL));
printf("------------------------------------------\n");
// 定义寄存器信息:地址、名称、字节数
struct {
uint8_t addr;
const char* name;
uint8_t size;
} reg_info[] = {
{0x00, "STATUS", 1},
{0x01, "ADCMODE", 2},
{0x02, "IFMODE", 2},
{0x03, "REGCHECK", 3},
{0x04, "DATA", 3},
{0x06, "GPIOCON", 2},
{0x07, "ID", 2},
// Channel Registers 0-15
{0x10, "CH0", 2}, {0x11, "CH1", 2}, {0x12, "CH2", 2}, {0x13, "CH3", 2},
{0x14, "CH4", 2}, {0x15, "CH5", 2}, {0x16, "CH6", 2}, {0x17, "CH7", 2},
{0x18, "CH8", 2}, {0x19, "CH9", 2}, {0x1A, "CH10", 2}, {0x1B, "CH11", 2},
{0x1C, "CH12", 2}, {0x1D, "CH13", 2}, {0x1E, "CH14", 2}, {0x1F, "CH15", 2},
// Setup Configuration Registers 0-7
{0x20, "SETUPCON0", 2}, {0x21, "SETUPCON1", 2}, {0x22, "SETUPCON2", 2}, {0x23, "SETUPCON3", 2},
{0x24, "SETUPCON4", 2}, {0x25, "SETUPCON5", 2}, {0x26, "SETUPCON6", 2}, {0x27, "SETUPCON7", 2},
// Filter Configuration Registers 0-7
{0x28, "FILTCON0", 2}, {0x29, "FILTCON1", 2}, {0x2A, "FILTCON2", 2}, {0x2B, "FILTCON3", 2},
{0x2C, "FILTCON4", 2}, {0x2D, "FILTCON5", 2}, {0x2E, "FILTCON6", 2}, {0x2F, "FILTCON7", 2},
// Offset Registers 0-7
{0x30, "OFFSET0", 3}, {0x31, "OFFSET1", 3}, {0x32, "OFFSET2", 3}, {0x33, "OFFSET3", 3},
{0x34, "OFFSET4", 3}, {0x35, "OFFSET5", 3}, {0x36, "OFFSET6", 3}, {0x37, "OFFSET7", 3},
// Gain Registers 0-7
{0x38, "GAIN0", 3}, {0x39, "GAIN1", 3}, {0x3A, "GAIN2", 3}, {0x3B, "GAIN3", 3},
{0x3C, "GAIN4", 3}, {0x3D, "GAIN5", 3}, {0x3E, "GAIN6", 3}, {0x3F, "GAIN7", 3},
};
int total_regs = sizeof(reg_info) / sizeof(reg_info[0]);
int success_count = 0;
int fail_count = 0;
for (int i = 0; i < total_regs; i++) {
uint32_t value = 0;
int ret = ad4115_read_register(dev, reg_info[i].addr, reg_info[i].size, &value);
if (ret == 0) {
success_count++;
// 根据寄存器大小格式化输出
if (reg_info[i].size == 1) {
printf("0x%02X %-12s: 0x%02X\n", reg_info[i].addr, reg_info[i].name, value);
} else if (reg_info[i].size == 2) {
printf("0x%02X %-12s: 0x%04X\n", reg_info[i].addr, reg_info[i].name, value);
} else {
printf("0x%02X %-12s: 0x%06X\n", reg_info[i].addr, reg_info[i].name, value);
}
} else {
fail_count++;
printf("0x%02X %-12s: READ FAILED\n", reg_info[i].addr, reg_info[i].name);
}
}
printf("------------------------------------------\n");
printf("总计:%d 个寄存器,成功:%d, 失败:%d\n", total_regs, success_count, fail_count);
printf("==========================================\n\n");
return (fail_count > 0) ? AD4115_ERROR_READ : AD4115_SUCCESS;
}
ad4115_driver.h
#ifndef AD4115_DRIVER_H
#define AD4115_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define AD4115_MAX_CHANNELS 8
#define AD4115_SPI_SPEED_HZ 10000000 // 10MHz SPI
#define AD4115_NUM_DATA_RATES 23
#define AD4115_DEFAULT_DATA_RATE 7 // 10kSPS 总速率 = 1.25kSPS/通道
#define AD4115_DEBUG 0
// 所有通道数据
typedef struct {
int32_t raw_data[AD4115_MAX_CHANNELS];
bool valid[AD4115_MAX_CHANNELS];
} ad4115_sample_t;
// 设备句柄
typedef struct {
int spi_fd;
uint32_t speed_hz;
uint8_t mode;
uint8_t bits_per_word;
uint16_t device_id;
int num_channels;
int data_rate_index;
bool channels_enabled[AD4115_MAX_CHANNELS];
} ad4115_dev_t;
// 错误码
typedef enum {
AD4115_SUCCESS = 0,
AD4115_ERROR_INIT = -1,
AD4115_ERROR_SPI = -2,
AD4115_ERROR_CHANNEL = -3,
AD4115_ERROR_READ = -4,
AD4115_ERROR_TIMEOUT = -5
} ad4115_error_t;
// 数据速率信息结构
typedef struct {
int index;
unsigned int rate_sps;
const char* description;
} ad4115_data_rate_t;
#ifdef __cplusplus
extern "C" {
#endif
ad4115_dev_t* ad4115_init(const char* spi_device, uint32_t speed_hz);
void ad4115_deinit(ad4115_dev_t* dev);
ad4115_error_t ad4115_enable_channel(ad4115_dev_t* dev, int channel);
ad4115_error_t ad4115_disable_channel(ad4115_dev_t* dev, int channel);
ad4115_error_t ad4115_enable_all_channels(ad4115_dev_t* dev);
ad4115_error_t ad4115_disable_all_channels(ad4115_dev_t* dev);
ad4115_error_t ad4115_set_data_rate(ad4115_dev_t* dev, int rate_index);
unsigned int ad4115_get_data_rate(ad4115_dev_t* dev);
ad4115_error_t ad4115_read_all_channels(ad4115_dev_t* dev, ad4115_sample_t* sample);
uint16_t ad4115_get_sensor_id(ad4115_dev_t* dev);
ad4115_error_t ad4115_dump_all_registers(ad4115_dev_t* dev) ;
#ifdef __cplusplus
}
#endif
#endif
2.驱动验证
提供一个测试代码,用于验证驱动是否正常
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include "ad4115_driver.h"
volatile sig_atomic_t keep_running = 1;
void signal_handler(int sig) {
if (sig == SIGINT) {
keep_running = 0;
}
}
int main() {
printf("=== AD4115 差分通道高速采样程序 ===\n");
printf("输出:ADC 原始数据(24 位有符号)\n");
printf("停止:按 Ctrl+C\n");
signal(SIGINT, signal_handler);
// 初始化设备
ad4115_dev_t* adc = ad4115_init("/dev/spidev0.0", AD4115_SPI_SPEED_HZ);
if (!adc) {
printf("错误:无法初始化 AD4115!\n");
return -1;
}
// 启用所有通道
if (ad4115_enable_all_channels(adc) != AD4115_SUCCESS) {
printf("错误:启用通道失败\n");
ad4115_deinit(adc);
return -1;
}
// 设置数据速率
if (ad4115_set_data_rate(adc, AD4115_DEFAULT_DATA_RATE) != AD4115_SUCCESS) {
printf("错误:设置数据速率失败\n");
ad4115_deinit(adc);
return -1;
}
printf("开始高速采样...\n");
printf("------------------------------------------------\n");
unsigned long sample_count = 0;
int error_count = 0;
struct timespec start_time, current_time;
clock_gettime(CLOCK_MONOTONIC, &start_time);
int print_every = 1000; // 每 1000 次打印一次
while (keep_running) {
ad4115_sample_t sample;
if (ad4115_read_all_channels(adc, &sample) == AD4115_SUCCESS) {
sample_count++;
// 减少打印频率
if (sample_count % print_every == 0) {
printf("Sample %lu: ", sample_count);
for (int ch = 0; ch < AD4115_MAX_CHANNELS; ch++) {
printf("CH%d:%11d ", ch, sample.raw_data[ch]);
}
printf("\n");
}
} else {
error_count++;
if (error_count % 10 == 0) {
printf("采样失败!错误计数:%d\n", error_count);
}
}
}
// 最终统计
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
double total_elapsed = (current_time.tv_sec - start_time.tv_sec) +
(current_time.tv_nsec - start_time.tv_nsec) / 1000000000.0;
double total_sample_rate = sample_count / total_elapsed;
printf("\n=== 采样结束 ===\n");
printf("总采样数:%lu\n", sample_count);
printf("总耗时:%.3f 秒\n", total_elapsed);
printf("平均总采样率:%.1f SPS\n", total_sample_rate * 8);
printf("平均每通道采样率:%.1f Hz\n", total_sample_rate);
printf("错误数:%d\n", error_count);
// 打印配置信息
printf("\n=== 配置信息 ===\n");
printf("传感器 ID: 0x%04X\n", ad4115_get_sensor_id(adc));
printf("SPI 速度:%u Hz\n", AD4115_SPI_SPEED_HZ);
printf("数据速率索引:%d\n", AD4115_DEFAULT_DATA_RATE);
printf("通道映射:\n");
for (int i = 0; i < 8; i++) {
printf(" CH%d: AIN%d+/AIN%d-\n", i, i*2, i*2+1);
}
printf("\n>>> 初始化完成,转储寄存器配置 <<<\n");
ad4115_dump_all_registers(adc);
ad4115_deinit(adc);
printf("程序结束。\n");
return 0;
}
效果如下
=== AD4115 差分通道高速采样程序 ===
输出:ADC 原始数据(24 位有符号)
停止:按 Ctrl+C
正在复位 AD4115...
设备 ID: 0x38D0
AD4115 初始化成功:SPI=10000000Hz, ID=0x38D0
开始高速采样...
------------------------------------------------
Sample 1000: CH0: -119296 CH1: -163327 CH2: -236798 CH3: 1064195 CH4: -243708 CH5: -61179 CH6: -128506 CH7: -145401
Sample 2000: CH0: -116736 CH1: -172543 CH2: -236030 CH3: 1022467 CH4: -241404 CH5: -61691 CH6: -126202 CH7: -138489
Sample 3000: CH0: -122880 CH1: -163839 CH2: -242686 CH3: 1056259 CH4: -241404 CH5: -73723 CH6: -121850 CH7: -136185
Sample 4000: CH0: -113664 CH1: -162815 CH2: -254206 CH3: 1044995 CH4: -231420 CH5: -66811 CH6: -116730 CH7: -147449
Sample 5000: CH0: -123648 CH1: -173055 CH2: -255998 CH3: 1012483 CH4: -240124 CH5: -63227 CH6: -132346 CH7: -147961
Sample 6000: CH0: -132352 CH1: -179711 CH2: -240894 CH3: 1031939 CH4: -239868 CH5: -71931 CH6: -153850 CH7: -139001
=== 采样结束 ===
总采样数:6611
总耗时:5.123 秒
平均总采样率:10324.3 SPS
平均每通道采样率:1290.5 Hz
错误数:0
=== 配置信息 ===
传感器 ID: 0x38D0
SPI 速度:10000000 Hz
数据速率索引:7
通道映射:
CH0: AIN0+/AIN1-
CH1: AIN2+/AIN3-
CH2: AIN4+/AIN5-
CH3: AIN6+/AIN7-
CH4: AIN8+/AIN9-
CH5: AIN10+/AIN11-
CH6: AIN12+/AIN13-
CH7: AIN14+/AIN15-
>>> 初始化完成,转储寄存器配置 <<<
========== AD4115 寄存器转储 ==========
时间:1777216333
------------------------------------------
0x00 STATUS : 0x07
0x01 ADCMODE : 0x8000
0x02 IFMODE : 0x0040
0x03 REGCHECK : 0x000000
0x04 DATA : 0x7FFBED
0x06 GPIOCON : 0x0800
0x07 ID : 0x38DE
0x10 CH0 : 0x8001
0x11 CH1 : 0x8043
0x12 CH2 : 0x8085
0x13 CH3 : 0x80C7
0x14 CH4 : 0x8109
0x15 CH5 : 0x814B
0x16 CH6 : 0x818D
0x17 CH7 : 0x81CF
0x18 CH8 : 0x0001
0x19 CH9 : 0x0001
0x1A CH10 : 0x0001
0x1B CH11 : 0x0001
0x1C CH12 : 0x0001
0x1D CH13 : 0x0001
0x1E CH14 : 0x0001
0x1F CH15 : 0x0001
0x20 SETUPCON0 : 0x1320
0x21 SETUPCON1 : 0x1320
0x22 SETUPCON2 : 0x1320
0x23 SETUPCON3 : 0x1320
0x24 SETUPCON4 : 0x1320
0x25 SETUPCON5 : 0x1320
0x26 SETUPCON6 : 0x1320
0x27 SETUPCON7 : 0x1320
0x28 FILTCON0 : 0x0007
0x29 FILTCON1 : 0x0007
0x2A FILTCON2 : 0x0007
0x2B FILTCON3 : 0x0007
0x2C FILTCON4 : 0x0007
0x2D FILTCON5 : 0x0007
0x2E FILTCON6 : 0x0007
0x2F FILTCON7 : 0x0007
0x30 OFFSET0 : 0x800000
0x31 OFFSET1 : 0x800000
0x32 OFFSET2 : 0x800000
0x33 OFFSET3 : 0x800000
0x34 OFFSET4 : 0x800000
0x35 OFFSET5 : 0x800000
0x36 OFFSET6 : 0x800000
0x37 OFFSET7 : 0x800000
0x38 GAIN0 : 0x554BF0
0x39 GAIN1 : 0x554BF0
0x3A GAIN2 : 0x554BF0
0x3B GAIN3 : 0x554BF0
0x3C GAIN4 : 0x554BF0
0x3D GAIN5 : 0x554BF0
0x3E GAIN6 : 0x554BF0
0x3F GAIN7 : 0x554BF0
------------------------------------------
总计:55 个寄存器,成功:55, 失败:0
==========================================
3.通过MQTT进行网络传输
时域效果

频域效果(嗯,家里的电源该换了~~)
