This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] ADS131E04:Arduino 读取寄存器和数据时出现问题

Guru**** 2391115 points
Other Parts Discussed in Thread: ADS131E04, ADS131E08EVM-PDK

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/932244/ads131e04-problems-reading-the-registers-and-the-data-by-an-arduino-due

器件型号:ADS131E04
主题中讨论的其他器件: ADS131E08EVM-PDK

大家好、

我想通过 SPI 阅读具有 Arduino 的 ADS131E04。 遗憾的是、我以前没有什么经验、这是我第一个使用 SPI 通信的项目。

SPI 的电压电平为3.3V、应与 ADC 配合使用。 我将 SPI 通信的时钟速率设置为4MHz。 SPI 模式为1 (CPOL = 0、CPHA = 1)、我已设置"MSB 优先"。

您可以在下面看到我的代码。 如果我读出、例如循环中的 ID 寄存器、答案始终为0x00。 我也已经逐个读取了所有寄存器。 所有这些都返回值0x00。 我还记录了与逻辑分析仪的通信。 Arduino 正确发送命令。 我认为时机也合适。 到目前为止、信号在示波器上看起来良好。 电压电平和时序良好。

 

如果我连续读出采样数据、我还会返回稳定度更高或更低的测量值。 下面是使用逻辑分析仪测量的数据和记录的示例。 转换为电压可能不正确、因为我尚未考虑计算中的符号。 我很高兴收到有关这方面的提示。

对我来说、结论是 SPI 通信通常起作用、而 ADC 也能够发送 Arduino 理解的数据。 遗憾的是、ADC 不理解我发送它的命令、否则它将正确输出寄存器值。 因此、我认为写入寄存器将不起作用。 我已经与同事检查了几次接线、至今未发现任何错误。 我怀疑 ADC 的初始化可能尚未达到最佳状态、如果有人能在这里为我提供帮助、我会很高兴。 我遵循了数据表中的过程(第59页、图53)。 我测量的电压 VCAP1约为1.2V。 nDRDY 信号与 fclk/64的切换也可见。

 

您对我还可以查找的内容有什么提示吗? 或者您在我的代码中发现了错误吗?

提前感谢您!

 

曼迪

 

 

以下是头文件:

 

#define NUM_REGISTERS ((uint8_t) 21)// 12个寄存器可读且可写(00h 至0Ch 和12h 至14h)->在逐个读取所有寄存器时、不能跳过地址0Dh 至11h (数据表)。 PP 38)
#define Nch ((int) 4) // ADC:通道数

//寄存器地址
#define ID_REG_ADD ((uint8_t) 0x00)
#define CONFIG1_REG_ADD ((uint8_t) 0x01)
#define CONFIG2_REG_ADD ((uint8_t) 0x02)
#define CONFIG3_REG_ADD ((uint8_t) 0x03)
#define FAULT_REG_ADD ((uint8_t) 0x04)
#define CH1SET_REG_ADD ((uint8_t) 0x05)
#define CH2SET_REG_ADD ((uint8_t) 0x06)
#define CH3SET_REG_ADD ((uint8_t) 0x07)
#define CH4SET_REG_ADD (((uint8_t) 0x08)
#define FAULT_STATP_REG_ADD (((uint8_t) 0x12)
#define FAULT_STATn_REG_ADD (((uint8_t) 0x13)
#define GPIO_REG_ADD ((uint8_t) 0x14)

//寄存器默认值
#define ID_DEFAULT ((uint8_t) 0x00)//未知,只读
#define CONFIG1_DEFAULT ((uint8_t) 0x91)
#define CONFIG2_DEFAULT ((uint8_t) 0xE0)
#define CONFIG3_DEFAULT ((uint8_t) 0x40)
#define FAULT_DEFAULT ((uint8_t) 0x00)
#define CHnSET_DEFAULT ((uint8_t) 0x10)
#define CHnPWDN (((uint8_t) 0x90)
#define FAULT_STATP_DEFAULT ((uint8_t) 0x00)//只读
#define FAULT_STATn_DEFAULT (((uint8_t) 0x00)//只读
#define GPIO_DEFAULT ((uint8_t) 0x0F)
#define GPIO_OUTPUT ((uint8_t) 0x00)

// SPI 控制命令(ADC 数据表、第35页)
#define WAKEUP 0x02 //从待机模式唤醒
#define STANDBY 0x04 //进入待机模式
#define RESET 0x06 //重置器件
#define START 0x08 //开始或重新启动(同步)转换
#define 停止 0x0A //停止转换
#define OFFSETCAL 0x1A //通道偏移校准
#define RDATAC 0x10 //启用读取日期连续模式
#define SDATAC 0x11 //停止读取数据连续模式
#define RDATA 0x12 //通过命令
#define WREG 读取数据 0x40 //写入寄存
器#define RREG 0x20 //读取寄存

器//常数
#define max_23bit 8388607
#define max_15bit 32767
#define max_8bit 255
#define UREF_mV 2400
#define byte_status ((int) 3)
#define byte_data ((int) 2)


typedef 结构{
uint8_t Begin1100:4;
uint8_t FAULT_STATP:8;
uint8_t FAULT_STATN:8;
uint8_t GPIO:4;
}statusWord_t;

//函数原型
void initialize_pins (void);
void startADC (void);
void writeSingleRegister (uint8_t address、uint8_t data);
字节 readSingleRegister (uint8_t address);
void readAllRegisters ();
void readADC (byte status_reg[]、byte data[Nch][byte_data]);
float calcVoltage_mV (uint32_t ADCvalue);
float calcTestVoltage_mV (uint32_t value);
statusWord_t writeStatusWord (uint32_t ADC_status);

#define PRINTBIN (Num) for (uint32_t =(1UL<<(sizeof (Num)*8)-1);t;t;t >=1) Serial.write (Num & t? '1':'0');//打印一个带前导零的二进制数(自动处理)

 

 

 

这是主文件:

#include "TimeLib.h"
#include 
#include "ADS131E04.h"


无符号长整型;

//引脚
#define ADC_NCS_Pin 10
#define ADC_MasterClk_Select_Pin 11
#define ADC_nDRDY_Pin 12 //低电平有效
#define ADC_Start_Pin 7
#define ADC_nPWDN_Pin 9 //低电平有效
#define ADC_nSysReset_Pin 8 //低电平有效

// SPI
#define SPI_CLOCK_DIV ((int) 21)

//输出模式
布尔值 RDATA_MODE = true; //true - RDATA;false - RDATAC
布尔 CAPTURE_DATA_MODE = false;// true -读取 ADC;false -读取环路

中的寄存器#define pinport PIOB
#define pinmask (1<<25)// Arduino 引脚2是端口 B 引脚25 (请参阅 www.robgray.com/.../Due-pinout-WEB.png)

//串行输出标志
布尔打印_STATUS_WORD = true;
布尔打印数据= true;布尔数据= true;


// times
const int t_StartADC_us = 25; // 25 µs
const int t_measure_us = 1000000;// 100ms
const int t_delay_SPI_5_us = 5; // 5 µs
const int t_delay_spi_2_us = 2; // 2 µs

字节 ADC_Values_Nch[Nch][byte_data]; //每个通道
的3字节(24位)字节 RESPONSE_STATUS[BYTE_STATUS]; // 3状态寄存器
StatusWord_t StatusWord;
Int32_t ADC_TOTAL = 0;
UINT32_t ADC_STATUS=0;
int Test_VOLTAGE_LOW_78; // 0...255 -> 0...3、3V (78 =大约 1.0V)
int Test_voltage_high=150; // 0...255 -> 0...3、3V (50 =大约 1.5V)

//========================================================================
void setup(){
//将您的安装代码放在此处,运行一次:
Serial.begin(9600);

Serial.println ("=================================================================== ");
Serial.println (");
Serial.println ("初始化引脚");

initialize_pins ();


//启动 SPI 库:
serial.println ("启动 SPI");


SPI.begin(ADC_nCS_Pin);
SPI.setClockDivider(ADC_nCS_Pin,SPI_CLOCK_DIV);
SPI.setBitOrder(ADC_nCS_Pin,MSBFIRST); //最高有效位优先
SPI.setDataMode(ADC_nCS_Pin,SPI_MODE1); // SPI_MODE1 -时钟极性(CPOL):0 -时钟相位(CPHA):1 -输出边沿:上升-数据捕获:下降

startADC ();

writeSingleRegister (CONFIG3_REG_ADD、0b11000000);//使用内部基准缓冲器、Vref=2.4V
writeSingleRegister (config1_REG_ADD、0b10010100);//数据速率= 24位、4kSPS (数据表、第41页)-> 1001 writeSingleRegister
(config1_REG_PW2)



;writeCHnCH0100 (默认设置);nCHING_PW2AD_CC0100 (nCH_CH_CONFIG0_AD_CONFIGN);
writeSingleRegister (GPIO_REG_ADD、GPIO_OUTPUT);

//开始测试信号
Serial.println ("开始测试信号");
analogWrite (DAC0、Test_VOLTGE_LOW);
analogWrite (DAC1、Test_VOLTAGE);

if (RDATA_MODE=false){
digitalWrite (ADC_NCS_Pin、low);//启用器件
SPI.transfer (ADC_NCS_Pin、RDATAC);
digitalWrite (ADC_NCS_Pin、HIGH);//禁用器
件}


void loop(){
if (capture_data_mode=false){
Serial.print ("寄存器 ID reg:");
Serial.println (readSingleRegister (ID_REG_ADD)、hex);
//readAllRegisters ();
}
else{
时间=微秒();
if ((time %(t_measure_us))>= t_StartADC_us){//开始读取 ADC
serial.println ("开始转换");
digitalWrite (ADC_Start_Pin、HIGH);//开始转换

readADC (RESPONSE_STATUS、ADC_VALUES);


digitalWrite (ADC_NCS_Pin、HIGH);//启用器件

digitalWrite (ADC_Start_Pin、low);//停止转换


//打印状态字
if (print_status_word){
serial.print ("状态寄存器:");
对于(int i=0;i "="" ");="" }="" adc_status="0;" |="(response_status[0])<" statusword="writeStatusWord(ADC_status);" statusword:="" -="" begin=");
              Serial.print(StatusWord.Begin1100,BIN);
              Serial.print(" fault_statp=");
              Serial.print(StatusWord.FAULT_STATP,BIN);
              Serial.print(" fault_statn=");
              Serial.print(StatusWord.FAULT_STATN,BIN);
              Serial.print(" gpio=");
              Serial.print(StatusWord.GPIO,BIN);

              Serial.println();
          }

          if (print_data){
            // print channel data
            for (int i=0; i<<<",="" voltage:="" serial.print(calcvoltage_mv(adc_total),1);="" serial.println();="" test_voltage="random(0,255);" analogwrite(dac0,test_voltage);="" serial.print("test="" serial.println(calctestvoltage_mv(test_voltage),1);="" delaymicroseconds(20);="" void="" initialize_pins(void){="" initialize="" the="" data="" ready="" and="" chip="" select="" pins:="" pinmode(adc_ndrdy_pin,="" input);="" pinmode(adc_ncs_pin,="" output);="" pinmode(adc_start_pin,="" pinmode(adc_npwdn_pin,="" pinmode(adc_nsysreset_pin,="" digitalwrite(adc_nsysreset_pin,low);="" digitalwrite(adc_ncs_pin,high);="" disable="" device="" startadc(void){="" digitalwrite(adc_start_pin,high);="" delaymicroseconds(10);="" digitalwrite(adc_npwdn_pin,high);="" power="" down="" disabled="" delaymicroseconds(1);="" digitalwrite(adc_nsysreset_pin,high);="" system="" reset="" delay(150);="" spi.transfer(adc_ncs_pin,wakeup);="" delay(1);="" spi.transfer(adc_ncs_pin,sdatac);="" digitalwrite(adc_ncs_pin,low);="" enable="" digitalwrite(adc_start_pin,low);="" spi.transfer(adc_ncs_pin,reset);="" delaymicroseconds(5);="" spi.transfer(adc_ncs_pin,stop);="" delay(10);="" writesingleregister(uint8_t="" address,="" uint8_t="" data){="" spi.transfer(adc_ncs_pin,wreg|address,spi_continue);="" delaymicroseconds(t_delay_spi_5_us);="" spi.transfer(adc_ncs_pin,0x00,spi_continue);="" delaymicroseconds(t_delay_spi_2_us);="" spi.transfer(adc_ncs_pin,data);="" byte="" readsingleregister(uint8_t="" address){="" value;="" spi.transfer(adc_ncs_pin,rreg|address,spi_continue);="" value="(byte)" spi.transfer(adc_ncs_pin,0);="" return="" readallregisters(){="" val[num_registers];="" spi.transfer(adc_ncs_pin,rreg|0x00,spi_continue);="" spi.transfer(adc_ncs_pin,0x14,spi_continue);="" for="" (int="" i="0;i" val[i]="(byte)" spi.transfer(adc_ncs_pin,0,spi_continue);="" serial.print("register="" serial.print(i);="" serial.print(":="" serial.println(val[i],hex);="" readadc(byte="" status_reg[],="" data[nch][byte_data]){="" while="" (digitalread(adc_ndrdy_pin))="" {="" wait="" until="" ndrdy="" is="" 0="" to="" read="" (rdata_mode="=true){" spi.transfer(adc_ncs_pin,rdata,spi_continue);="" status="" word="" i

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    曼迪


    我看不到在您对 ADS131E04的通信写入中有什么特别的错误。 20h 00h 00h 的命令本来应该能够读取 ID 寄存器。

    我猜是 Arduino Due 的 MOSI 与 ADS131E04的 DIN 引脚之间的某处连接不良。 我会使用一些细针探头、测量从 Arduino 到 ADS131E04 DIN 引脚的电阻。 您无需检查 SCLK 或 DOUT、因为您似乎已经能够从器件中获取一些内容。 我还会检查 ADS131E04电路板的 DIN 焊料连接是否不良。

    我注意到您可以看到/DRDY 引脚输出、ADC 速率似乎是默认设置的32kSPS 速率。 这是您已经显示的逻辑分析仪输出:

    我要注意的是、您对数据的计时速度有点慢。 当您从器件中读取数据并且/DRDY 变为低电平时、您需要在下一个 ADC 数据输出之前读取所有通道。 否则、新数据将立即放入 DOUT、从而中断读取。 通常、我会说您应该发出 SDATAC 命令来停止数据更新 DOUT、并使用 RDATA 命令来读取数据。 但是、您目前无法向器件发送命令。

    我有一个意见是、我对代码的审核并不是很好。 但是、我不认为这是编码问题-您已经可以看到用于 MOSI 的 Arduino 输出的正确输出。


    吴约瑟

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Joseph、  

    感谢你的帮助!

    [引用用户="Joseph Wu"]

    我猜是 Arduino Due 的 MOSI 与 ADS131E04的 DIN 引脚之间的某处连接不良。 我会使用一些细针探头、测量从 Arduino 到 ADS131E04 DIN 引脚的电阻。 您无需检查 SCLK 或 DOUT、因为您似乎已经能够从器件中获取一些内容。 我还会检查 ADS131E04电路板的 DIN 焊料连接是否不良。

    [/报价]

    我刚刚测量了 ADC 的 DIN (引脚34)和 Arduino 的 MOSI 引脚之间的电阻-它为1.1欧姆。 我没有专业的设置、正如您在照片上看到的那样。 另一方面、通信工作正常、因此我认为电缆长度不应成为问题。  由于存在寄生电容、信号边沿的上升与电子函数相对应。 然而、在 SCKL 下降沿时、当 DIN 信号被接管时、相应的信号电平已经达到。  

    [引用用户="Joseph Wu"]

    我注意到您可以看到/DRDY 引脚输出、ADC 速率似乎是默认设置的32kSPS 速率。

    [/报价]

    是的、你是对的。 我也注意到了这一点。 从这个结论中、他也不理解我写寄存器的命令。

    我从您那里收到了两个 ADC 样本、并将它们焊接到 TQFP 封装的测试 PCB 上。 对于这两个芯片、同样的问题是在读取寄存器时只返回0x00。 因此、我认为我的代码中毕竟可能有一个错误。  ADC 的初始化是否正确? 我还可以在这里测试什么吗?

    我还查看了演示套件 ADS131E08EVM-PDK 的代码。 不幸的是、代码很难读取、因此我无法使用它来检查我的程序。

    此致、

    曼迪

    编辑:  

    我现在再次使用示波器进行测量、它突然工作了! 我可以读取 ID 寄存器。 我怀疑 DIN 引脚确实未正确接触。  在电阻测量过程中按下测量尖端、我可能会将其弯曲、以便现在连接。 图片显示了使用示波器进行的测量。 通道1至4是
    - NCS
    -MISO
    -MOSI
    - SCLK

    另一个问题:您是否有一个代码示例、说明我如何根据记录的数据计算有符号电压? 谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    曼迪


    我很高兴您能够让器件响应 DIN。 根据您描述的内容、似乎主要问题是不良的 DIN 连接。

    至于用于转换数据的代码示例、我不知道具体情况(正如我之前提到的、我最好查看代码)。 不过、我确实使用 Excel 进行了大量电压转换、这是我通常的工作方式、首先是 ADC 输出数据(我在这里将其称为 ADCcode)。

    首先将二进制补码转换为十进制:
    ADC 输出=if (HEX2DEC (ADCcode)<2^23、HEX2DEC (ADCcode)、HEX2DEC (ADCcode)-2^24)

    然后将十进制转换为输入电压:
    输入电压=(ADCcode/2^23)*(VREF/增益)


    吴约瑟