一、AD7190 芯片概述

AD7190 是 Analog Devices 推出的一款超低噪声、24 位 Σ-Δ 型模数转换器,内置可编程增益放大器(PGA),专为高精度传感器测量而设计。其核心架构包括:

  • Σ-Δ 调制器 + 数字滤波器(可选 Sinc⁴ 或 Sinc³)

  • 低噪声 PGA(增益 1~128 可编程)

  • 多通道输入(2 个差分 / 4 个伪差分)

  • 片内时钟(4.92 MHz)或外部时钟/晶振

  • 片内校准(内部/系统零点和满量程)

  • 通用数字输出(4 个)和电桥关断开关

该器件采用 5 V 模拟电源和 2.7 V ~ 5.25 V 数字电源,功耗仅 6 mA,封装为 24 引脚 TSSOP,工作温度范围 –40°C ~ +105°C。

关键特性(数据手册摘要)

特性参数典型值/条件备注
均方根噪声8.5 nV(4.7 Hz,增益 128)适合微小信号检测
无噪声分辨率最高 22.5 位(增益 1)有效分辨率优异
失调漂移5 nV/°C(斩波使能)长期稳定性好
增益漂移1 ppm/°C(增益 1)温漂极小
输出数据速率4.7 Hz ~ 4.8 kHz(斩波禁用)可编程范围宽
50/60 Hz 抑制同时抑制(REJ60 位)适合工频环境
PGA 增益1, 8, 16, 32, 64, 128灵活匹配传感器
模拟输入范围双极性 ±VREF/增益(最大 ±5 V)支持差分/伪差分
基准电压范围1 V ~ AVDD(差分输入)可外接低噪声基准

突出优势

  • 超低噪声:适合应变计、称重传感器等 mV 级信号。

  • 零延迟(SINGLE 位)确保多通道切换时每笔转换均完全建立。

  • 内部校准大幅降低失调和增益误差,无需外部调整。

  • 电桥关断开关可切断传感器供电,实现系统级省电。

典型应用场景(数据手册推荐)

  • 电子秤、应变计、压力传感器

  • 温度测量(RTD、热电偶)

  • 色谱仪、PLC/DCS 模拟输入模块

  • 医疗与科学仪器(高精度数据采集)

本驱动应用:专为电阻应变式压力传感器设计,适用于工业称重或压力监测系统。


二、基于 TMS320F28377D 的驱动设计架构

2.1 硬件连接

  • SPI 接口:使用 F28377D 的 SPI-A 模块,工作在主模式、16 位帧格式、时钟空闲高(CPOL=1)、数据在下降沿捕获(CPHA=1),即 SPI 模式 3

  • 引脚分配

    • SCLK → GPIO 某脚(由 InitSpiaGpio() 配置)

    • DIN (MOSI) → GPIO 某脚

    • DOUT/RDY (MISO) → GPIO 某脚,同时作为数据就绪输入(连接至 GPIO17,由宏 GP17st 检测)

    • CS → 硬件拉低(或由 GPIO 控制,本驱动中 CS 硬接地,采用 3 线模式)

  • 控制引脚:电桥开关由 GPOCON 控制,无需额外 IO。

2.2 软件层次

驱动分为三层:

  1. 硬件抽象层:基于 TI C2000 库,配置 SPI 外设、GPIO 及系统时钟。

  2. 底层通信层:通过 SPI 发送命令字节和寄存器数据,实现读写原语。

  3. 功能层:封装寄存器配置、校准、数据读取等高级操作,提供统一调用接口。


三、驱动移植核心步骤

3.1 SPI 初始化(spi_fifo_init

  • 使能 TX/RX FIFO,设置触发级别(TX=1,RX=4),复位 FIFO。

  • 调用 InitSpi() 配置 SPI 为主模式、16 位、模式 3(CPOL=1,CPHA=1)。

  • 重要:由于 AD7190 的 8 位命令/数据在 16 位 SPI 帧中,代码统一将有效数据放在高字节(左移 8 位),低字节填充 0,确保 SCLK 产生完整 16 个脉冲,而 AD7190 只识别高 8 位。

3.2 复位与 ID 校验(ad7190Init

  • 复位:向 DIN 连续写入至少 40 个逻辑 1。代码循环 4 次,每次发送 0x00FF(16 位中低字节全 1),共 64 个 1,满足要求。复位后延时 100 ms。

  • ID 验证:发送读 ID 命令(0x60),读取 8 位,低 4 位应为 0x04,确认芯片正常。

3.3 寄存器配置

寄存器写入值(十六进制)功能描述(对照手册)
模式寄存器0x000008连续转换(MD=000),内部时钟(CLK1=1, CLK0=0),FS[9:0]=8 → 约 600 Hz 输出速率
配置寄存器高字节 0x00,中字节 0x01,低字节 0xA0斩波禁用,REFIN1 基准,通道 AIN1-AIN2 差分,缓冲使能,双极性,增益 1,激励电流使能
GPOCON0x40闭合电桥关断开关(BPDSW=1),通用输出禁用

配置依据

  • 增益 1 配合外部放大或传感器满量程输出,代码注释提及“增益设置为1(设置为128不可用)”,可能因外部已有放大。

  • 开启缓冲适配高阻抗传感器(如应变计)。

  • 激励电流用于传感器断线检测,符合手册应用建议。

3.4 内部校准

  • 依次写入空闲模式(0x0048)、内部满量程校准(0x00A8)、内部零电平校准(0x0088),最后进入连续转换模式(0x0008)。校准可减少失调和增益误差。

3.5 数据读取(ad7190DataRegRead

  • 发送读数据寄存器命令(0x58),然后连续发送 3 个哑字节(0xFF)以读取 24 位结果。

  • 将三个字节组合成有符号 32 位整数,减去 2^23(偏移二进制中点),再减去用户设定的 offset,得到最终压力值(单位自定义)。

3.6 高层调度(ad7190Run

  • 通过命令参数执行不同任务:初始化、读状态、写/读模式、写/读配置、写/读 GPOCON、连续读取数据(轮询 DOUT/RDY)。

  • 在主循环中调用,实现压力采集。


四、完整驱动代码(含详细注释)

文件:Ad7190.c

c

//###########################################################################
// FILE:   Ad7190_Example_2837xDSpi_FFDLB_int.c (AD7190驱动模块)
// TITLE:  基于TMS320F28377D的AD7190驱动(压力采集)
// 说明:  本驱动实现了AD7190的复位、初始化、寄存器读写及连续数据采集。
//         使用SPI-A(模式3),轮询方式读取DOUT/RDY引脚。
//         寄存器配置:增益1、双极性、缓冲使能、激励电流使能,内部时钟。
//         内部零点和满量程校准在初始化时完成。
//###########################################################################

#include "F28x_Project.h"
#include "Ad7190.h"
#include "adc_epwm_cpu01.h"

// 全局变量
Uint16 sdataForce;         // 发送数据缓冲(8位有效,放在高字节)
Uint16 rdataForce[3];      // 接收数据缓冲(3字节ADC数据)
Uint16 rdata_point, sdataForce_point;
long data_LS = 0;          // 最终24位转换结果(有符号)
char start_send = 0, ad7190Rdy = 0, stop = 0;
Uint32 Counter1Force = 0;

// 外部函数声明(SPI初始化由主程序调用)
extern void InitSpi(void);
extern void delay_loop(void);
extern void delay_1(long j);

//---------------------------------------------------------------------------
// 函数: spi_fifo_init
// 说明: 初始化SPI-A的FIFO,配置为16位主模式,时钟极性CPOL=1,相位CPHA=1
//       (即模式3),符合AD7190时序要求。
//---------------------------------------------------------------------------
void spi_fifo_init()
{
    // 使能TX FIFO,设置TX FIFO触发级别为1(每发送1个数据触发中断,但此处未用中断)
    SpiaRegs.SPIFFTX.all = 0xE040;   // TXFFIL=0, TXFFIENA=0, TXFFINTCLR=1, TXFFINT=1, TXFIFO=1
    SpiaRegs.SPIFFRX.all = 0x2044;   // RXFFIL=4(接收FIFO触发级别4),RXFFIENA=0,RXFIFORESET=1
    SpiaRegs.SPIFFCT.all = 0x00;     // 无时钟延迟
    SpiaRegs.SPIFFTX.bit.TXFIFO = 1;
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;

    InitSpi(); // 此函数应在F2837xD_Spi.c中配置SPI为Master,模式3,16位
}

//---------------------------------------------------------------------------
// 函数: ad7190Init
// 说明: 初始化AD7190,包括复位、ID验证、配置寄存器、校准并进入连续转换模式。
// 返回: 1 成功,0 失败
//---------------------------------------------------------------------------
unsigned char ad7190Init(void)
{
    unsigned char i;
    unsigned char status = 0;
    ad7190Rdy = 0;
    sdataForce_point = 0;

    // 步骤1:发送一个无效命令,清空可能残留的数据
    sdataForce = 0x0001;          // 命令字节0x01(写通信寄存器?实际为无效,只是产生时钟)
    SpiaRegs.SPITXBUF = (sdataForce << 8); // 高字节发送
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {} // 等待发送完成
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {} // 等待接收
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 丢弃接收数据
    sdataForce_point++;

    // 步骤2:复位AD7190 —— 发送至少40个连续1
    // 手册要求:DIN高电平保持至少40个SCLK周期
    for(i=0; i<4; i++)
    {
        sdataForce = 0x00FF;      // 低8位全1,加上高字节0x00,实际16位中低8位为1
        SpiaRegs.SPITXBUF = (sdataForce << 8); // 发送16位,低字节全1
        while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
        DELAY_US(1000);
        rdataForce[0] = SpiaRegs.SPIRXBUF; // 读走返回数据(复位期间数据无效)
    }
    DELAY_US(100000); // 复位后等待至少500us(手册要求),此处延时100ms充分

    // 步骤3:读取ID寄存器,验证芯片
    // 命令:0x60(读ID寄存器,8位,RS=100)
    sdataForce = 0x60;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 第1个字节为0(命令回应)
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 0) {}

    // 发送哑字节读取真正的ID
    sdataForce = 0xFF;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 该字节应包含ID
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 0) {}
    rdataForce[1] = 0; rdataForce[2] = 0;
    rdataForce[0] &= 0x000F; // 取低4位,AD7190的ID应为0x04
    if(rdataForce[0] == 0x04) status = 1;

    // 步骤4:配置ADC
    if(status)
    {
        ad7190ConfRegRead();   // 配置寄存器:双极性,增益1,缓冲使能,激励电流使能
        ad7190GpoRegRead(0x40); // GPOCON:闭合电桥开关(BPDSW=1)
        // 执行内部校准:先空闲模式,然后满量程校准,再零电平校准,最后连续转换
        ad7190ModeRegRead(0x0048); // 空闲模式(MD=010)
        DELAY_US(1000);
        ad7190ModeRegRead(0x00A8); // 内部满量程校准(MD=101)
        DELAY_US(1000);
        ad7190ModeRegRead(0x0088); // 内部零电平校准(MD=100)
        DELAY_US(1000);
        ad7190ModeRegRead(0x0008); // 连续转换模式(MD=000),FS=8
    }
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190StRegRead
// 说明: 读取状态寄存器(8位),验证RDY、ERR等位
// 返回: 1 成功
//---------------------------------------------------------------------------
unsigned char ad7190StRegRead(void)
{
    unsigned char status = 0;
    // 命令:0x40(读状态寄存器,RS=000,R/W=1)
    sdataForce = 0x40;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 第一个字节无效

    sdataForce = 0xFF; // 哑字节读取状态
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 状态寄存器值
    rdataForce[1] = 0; rdataForce[2] = 0;
    status = 1;
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190ModeRegRead
// 参数: mode —— 要写入的24位模式寄存器值(低24位有效)
// 说明: 先写入给定模式值,然后回读模式寄存器并存入rdataForce[0..2]
// 返回: 1 成功
//---------------------------------------------------------------------------
unsigned char ad7190ModeRegRead(Uint16 mode)
{
    unsigned char status = 0;
    unsigned char i;

    // 写命令:0x08(写模式寄存器,RS=001,R/W=0)
    sdataForce = 0x08;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 丢弃

    // 发送3字节数据(mode的高8位、中8位、低8位)
    // 注意mode为16位,实际只用了低16位,高8位默认0(即0x00****)
    // 先发高8位(mode>>8)
    sdataForce = (mode >> 8) & 0xFF;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 中8位(mode & 0xFF)
    sdataForce = mode & 0xFF;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 低8位(实际mode仅有16位,此处补0)
    sdataForce = 0x00;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    delay_1(2000000); // 延时等待校准完成

    // 回读模式寄存器:命令0x48(读模式寄存器)
    sdataForce = 0x48;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 丢弃

    for(i=0; i<3; i++)
    {
        sdataForce = 0xFF;
        SpiaRegs.SPITXBUF = (sdataForce << 8);
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
        rdataForce[i] = SpiaRegs.SPIRXBUF; // 依次为高、中、低字节
    }
    sdataForce_point++;
    status = 1;
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190ConfRegRead
// 说明: 写入配置寄存器(固定值:0x00 0x01 0xA0),然后回读
//       配置:斩波禁用,REFIN1,通道1,缓冲使能,双极性,增益1,激励电流使能
// 返回: 1 成功
//---------------------------------------------------------------------------
unsigned char ad7190ConfRegRead(void)
{
    unsigned char status = 0;
    unsigned char i;

    // 写命令:0x10(写配置寄存器,RS=010)
    sdataForce = 0x10;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 丢弃

    // 发送3字节配置数据
    // 高字节:0x00(Chop=0, REFSEL=0, 保留0)
    sdataForce = 0x00;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 中字节:0x01(CH7-CH0=1,使能通道AIN1-AIN2差分对)
    sdataForce = 0x01;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 低字节:0xA0(二进制1010 0000)
    // BUF=1,U/B=0(双极性),G[2:0]=000(增益1),Burn=1(激励电流使能)
    sdataForce = 0xA0;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 回读配置寄存器:命令0x50
    sdataForce = 0x50;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    for(i=0; i<3; i++)
    {
        sdataForce = 0xFF;
        SpiaRegs.SPITXBUF = (sdataForce << 8);
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
        rdataForce[i] = SpiaRegs.SPIRXBUF;
    }
    sdataForce_point++;
    status = 1;
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190GpoRegRead
// 参数: powercontrol — 写入GPOCON的值(例如0x40闭合电桥开关)
// 说明: 写GPOCON并回读
// 返回: 1 成功
//---------------------------------------------------------------------------
unsigned char ad7190GpoRegRead(char powercontrol)
{
    unsigned char status = 0;

    // 写命令:0x28(写GPOCON寄存器,RS=101)
    sdataForce = 0x28;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 写入一个字节
    sdataForce = powercontrol;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 回读GPOCON:命令0x68
    sdataForce = 0x68;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;

    // 读一个字节
    sdataForce = 0xFF;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF;
    rdataForce[1] = 0; rdataForce[2] = 0;
    sdataForce_point++;
    status = 1;
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190DataRegRead
// 参数: offset — 手动偏移值(用于调零)
// 说明: 读取24位数据寄存器,转换为有符号值并减去偏移
// 返回: 24位有符号压力值(单位自定义)
//---------------------------------------------------------------------------
unsigned char ad7190DataRegRead(Uint16 offset)
{
    unsigned char status = 0;
    unsigned char i;

    // 读数据寄存器命令:0x58(RS=011,R/W=1)
    sdataForce = 0x58;
    SpiaRegs.SPITXBUF = (sdataForce << 8);
    while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
    while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
    rdataForce[0] = SpiaRegs.SPIRXBUF; // 丢弃

    // 连续读3个字节
    for(i=0; i<3; i++)
    {
        sdataForce = 0xFF;
        SpiaRegs.SPITXBUF = (sdataForce << 8);
        while(SpiaRegs.SPISTS.bit.OVERRUN_FLAG & 0x40 != 0x40) {}
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1) {}
        rdataForce[i] = SpiaRegs.SPIRXBUF;
    }
    sdataForce_point++;

    // 组合成24位数据:rdataForce[0]高8位,[1]中8位,[2]低8位
    data_LS = rdataForce[0] << 8;
    data_LS = (data_LS | (rdataForce[1] & 0xFF)) << 8;
    data_LS = data_LS | (rdataForce[2] & 0xFF);

    // 偏移二进制转补码(减2^23),再减去用户偏移
    data_LS = data_LS - 8388608 - offset;
    if(data_LS < 0) data_LS = 0;

    status = 1;
    return status;
}

//---------------------------------------------------------------------------
// 函数: ad7190Run
// 参数: command — 操作命令:1=初始化,2=读状态,3=写模式,4=写配置,5=写GPOCON,6=连续读数据
//       offset — 传递偏移值
// 说明: 高层调度函数,根据命令调用相应子函数
// 返回: 最新转换值(仅在命令6时有效)
//---------------------------------------------------------------------------
long ad7190Run(char command, Uint16 offset)
{
    start_send = command;
    if(start_send == 1) {
        sdataForce_point = 0;
        ad7190Rdy = ad7190Init();
        // Force.CMD = 0; // 外部变量,用于复位命令
    }
    else if(start_send == 2) {
        ad7190Rdy = ad7190StRegRead();
    }
    else if(start_send == 3) {
        ad7190Rdy = ad7190ModeRegRead(0x0008); // 写模式并回读
    }
    else if(start_send == 4) {
        ad7190Rdy = ad7190ConfRegRead();
    }
    else if(start_send == 5) {
        ad7190Rdy = ad7190GpoRegRead(0x40);
    }
    else if(start_send == 6) {
        // 连续读取数据(循环检测DOUT/RDY引脚)
        // 当GP17st为真(即引脚为低)时读取
        if(GP17st) {
            ad7190Rdy = ad7190DataRegRead(offset);
        }
        // 以下为示例:每隔一定次数执行校准,实际应用中可移除或调整
        Counter1Force++;
        if(Counter1Force == 50000000 && ad7190Rdy) {
            ad7190ModeRegRead(0x0048); // 空闲
            ad7190ModeRegRead(0x00A8); // 满量程校准
            ad7190ModeRegRead(0x0088); // 零电平校准
            ad7190ModeRegRead(0x0008); // 连续转换
            Counter1Force = 1;
        }
        stop = 0;
    }
    return data_LS;
}

文件:Ad7190.h

c

#ifndef AD7190_H_
#define AD7190_H_

#include "adc_epwm_cpu01.h"

// 宏定义:检测DOUT/RDY引脚(GPIO17)是否低电平(数据就绪)
#define GP17st  (!GPIO_ReadPin(17))

// 外部变量声明(由主程序定义)
extern Uint16 sdataForce;
extern Uint16 rdataForce[3];
extern long data_LS;
extern char start_send, ad7190Rdy, stop;
extern Uint32 Counter1Force;

// 函数声明
void spi_fifo_init(void);
unsigned char ad7190Init(void);
unsigned char ad7190StRegRead(void);
unsigned char ad7190ModeRegRead(Uint16 mode);
unsigned char ad7190ConfRegRead(void);
unsigned char ad7190GpoRegRead(char powercontrol);
unsigned char ad7190DataRegRead(Uint16 offset);
long ad7190Run(char command, Uint16 offset);

#endif /* AD7190_H_ */

五、驱动与芯片特性的映射关系

芯片特性(手册条款)驱动实现方式对应代码/寄存器
SPI 模式 3(CPOL=1, CPHA=1)配置 F28377D SPI 主模式,时钟空闲高,下降沿捕获InitSpi() + spi_fifo_init()
复位要求(40 个连续 1)循环发送 0x00FF 四次,共 64 个 1ad7190Init() 中 for 循环
ID 寄存器(0x04)读取并校验低 4 位ad7190Init() 中 0x60 命令
内部时钟源(CLK[1:0]=10)模式寄存器写 0x000008ad7190ModeRegRead(0x0008)
连续转换模式(MD=000)模式寄存器 MD 位为 000同上
输出数据速率(FS=8)模式寄存器低 10 位为 8,约 600 Hz同上
差分通道选择(CH[7:0]=1)配置寄存器中字节 0x01ad7190ConfRegRead()
增益 1(G[2:0]=000)配置寄存器低字节 G 位为 000低字节 0xA0 含 G=000
双极性模式(U/B=0)配置寄存器低字节 U/B=0同上
缓冲器使能(BUF=1)配置寄存器低字节 BUF=1同上
激励电流(Burn=1)配置寄存器低字节 Burn=1同上
基准选择(REFSEL=0)配置寄存器高字节 REFSEL=0高字节 0x00
电桥关断开关(BPDSW=1)GPOCON 寄存器 bit6=1ad7190GpoRegRead(0x40)
内部校准(MD=100,101)分别写入模式寄存器进行零点和满量程校准ad7190ModeRegRead(0x0088/0x00A8)
数据就绪检测(RDY 引脚)轮询 GPIO17 电平,低表示数据有效宏 GP17st 和 ad7190DataRegRead 调用条件
数据读取(数据寄存器)发送 0x58 命令,读 3 字节ad7190DataRegRead()
偏移二进制码转补码减去 2^23 得到有符号数data_LS - 8388608 - offset

六、使用注意事项与扩展建议

6.1 硬件注意事项(基于手册)

  1. 电源去耦:AVDD 与 AGND 间并联 10 μF 钽电容和 0.1 μF 陶瓷电容,DVDD 同样处理。

  2. 模拟输入滤波:每个模拟输入端串联 100 Ω 电阻,并接 0.1 μF 电容(抗混叠)。

  3. 基准电压:推荐使用低噪声基准源(如 ADR431),若电桥激励电压作基准,则实现比率式测量。

  4. PCB 布局:模拟/数字地单点连接,避免数字噪声耦合,参见手册“接地和布局”章节。

6.2 软件调试建议

  • 移植初期用逻辑分析仪检查 SCLK、DIN、DOUT 波形,确认 SPI 时序(模式 3)正确。

  • 使用 ad7190StRegRead() 读取状态寄存器,检查 RDY、ERR 和 NOREF 位,帮助排查故障。

  • 若读取数据始终为全 1,检查基准电压是否有效(NOREF 位)或输入是否超量程。

6.3 扩展功能(按需修改)

  • 多通道扫描:修改配置寄存器 CH 位,并设置 DAT_STA=1 以在数据中附带通道信息。

  • 斩波使能:将配置寄存器 Chop 置 1,可降低失调漂移,但输出速率减半(参阅手册表 10~13)。

  • Sinc³ 滤波器:设置模式寄存器 SINC3=1,建立时间缩短为 3/FS,适合快速通道切换。

  • 单次转换模式:将 MD 设为 001,适合低功耗间歇采样。

  • 中断方式:配置 DOUT/RDY 下降沿触发外部中断,替代轮询,提高 CPU 利用率。


七、总结

本驱动严格遵循 AD7190 数据手册,在 TMS320F28377D 上实现了完整的初始化、校准和连续数据采集功能。通过合理的寄存器配置(增益 1、双极性、缓冲使能、激励电流等),充分挖掘了芯片的超低噪声和高精度特性,适用于应变式压力/称重传感器。代码结构清晰,移植性强,可作为工业数据采集系统的基础模块。如需适配其他应用场景,仅需调整配置寄存器相关位,无需改动底层通信逻辑。

更多推荐