AD7190 高精度 24 位 Σ-Δ ADC 在 TMS320F28377D 上的驱动设计与实现
一、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 软件层次
驱动分为三层:
-
硬件抽象层:基于 TI C2000 库,配置 SPI 外设、GPIO 及系统时钟。
-
底层通信层:通过 SPI 发送命令字节和寄存器数据,实现读写原语。
-
功能层:封装寄存器配置、校准、数据读取等高级操作,提供统一调用接口。
三、驱动移植核心步骤
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,激励电流使能 |
| GPOCON | 0x40 | 闭合电桥关断开关(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 个 1 | ad7190Init() 中 for 循环 |
| ID 寄存器(0x04) | 读取并校验低 4 位 | ad7190Init() 中 0x60 命令 |
| 内部时钟源(CLK[1:0]=10) | 模式寄存器写 0x000008 | ad7190ModeRegRead(0x0008) |
| 连续转换模式(MD=000) | 模式寄存器 MD 位为 000 | 同上 |
| 输出数据速率(FS=8) | 模式寄存器低 10 位为 8,约 600 Hz | 同上 |
| 差分通道选择(CH[7:0]=1) | 配置寄存器中字节 0x01 | ad7190ConfRegRead() |
| 增益 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=1 | ad7190GpoRegRead(0x40) |
| 内部校准(MD=100,101) | 分别写入模式寄存器进行零点和满量程校准 | ad7190ModeRegRead(0x0088/0x00A8) |
| 数据就绪检测(RDY 引脚) | 轮询 GPIO17 电平,低表示数据有效 | 宏 GP17st 和 ad7190DataRegRead 调用条件 |
| 数据读取(数据寄存器) | 发送 0x58 命令,读 3 字节 | ad7190DataRegRead() |
| 偏移二进制码转补码 | 减去 2^23 得到有符号数 | data_LS - 8388608 - offset |
六、使用注意事项与扩展建议
6.1 硬件注意事项(基于手册)
-
电源去耦:AVDD 与 AGND 间并联 10 μF 钽电容和 0.1 μF 陶瓷电容,DVDD 同样处理。
-
模拟输入滤波:每个模拟输入端串联 100 Ω 电阻,并接 0.1 μF 电容(抗混叠)。
-
基准电压:推荐使用低噪声基准源(如 ADR431),若电桥激励电压作基准,则实现比率式测量。
-
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、双极性、缓冲使能、激励电流等),充分挖掘了芯片的超低噪声和高精度特性,适用于应变式压力/称重传感器。代码结构清晰,移植性强,可作为工业数据采集系统的基础模块。如需适配其他应用场景,仅需调整配置寄存器相关位,无需改动底层通信逻辑。
更多推荐
所有评论(0)