我在初步尝试在arduino内进行编程并使用该模块,目前通过串口我可以得到ID号,我想这说明目前的MCU和adc是可以正常进行SPI通信的。但我遇到的问题是,在我利用信号发生器产生一个±500mv的50hz正弦差分信号输入到ADC的通道1后,ADC的输出始终是一个恒定的值。通过示波器和status寄存器我发现drdy引脚时钟处于高电平状态未发生改变,请问这是什么原因。我已经附上了我的寄存器配置值供您查看。我已经验证过目前的寄存器值被正确写入,因为我通过读取寄存器得到了相应的值与我写入的值相符合。同时我还附上了我的arduino编程代码和相应的库文件,很希望得到您的帮助,十分感激。
.ino
#include <SPI.h>
#include "ADS131M04.h"
#include "registerDefinitions.h"
#define CS_PIN WB_SPI_CS // 你的 CS 引脚
#define DRDY_PIN WB_IO1 // 你把 DRDY 接到哪,就填哪
// SPI 命令定义(参考 ADS131M0x 手册)
#define CMD_RESET 0x11
#define CMD_START 0x33
#define CMD_STOP 0x0A
ADS131M04 adc(CS_PIN, -1, &SPI);
int8_t channelIds[2] = {0, 1};
void sendCommand(uint16_t cmd) {
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
digitalWrite(CS_PIN, LOW);
SPI.transfer16(cmd);
digitalWrite(CS_PIN, HIGH);
SPI.endTransaction();
}
void setup() {
Serial.begin(115200);
while (!Serial);
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
pinMode(DRDY_PIN, INPUT);
// 初始化 SPI
SPI.begin();
// 初始化 ADC(只做 SPI 设置,不会自动 START)
adc.begin();
Serial.println("ADC 初始化完成");
// 先 RESET 一下,确保回到默认状态
sendCommand(CMD_RESET);
delay(10);
//读一次 STATUS 寄存器
uint16_t status = adc.readReg(STATUS);
Serial.print("读取 STATUS 寄存器: 0x");
Serial.println(status, HEX);
//读一次 ID 寄存器
uint16_t tmp;
tmp = adc.readReg(ID);
Serial.print("ID = 0x"); Serial.println(tmp, HEX);
// 写寄存器配置
adc.writeReg(GAIN1, 0x0000); Serial.println("GAIN1 写入");
adc.writeReg(CFG, 0x0600); Serial.println("CFG 写入");
adc.writeReg(MODE, 0x0514); Serial.println("MODE 写入");
adc.writeReg(CLOCK, 0x010E); Serial.println("CLOCK 写入");
adc.writeReg(THRSHLD_MSB,0x0000); Serial.println("THRSHLD_MSB 写入");
adc.writeReg(THRSHLD_LSB,0x0000); Serial.println("THRSHLD_LSB 写入");
adc.writeReg(CH0_CFG, 0x0000); Serial.println("CH0_CFG 写入");
adc.writeReg(CH0_OCAL_MSB,0x0000); Serial.println("CH0_OCAL_MSB 写入");
adc.writeReg(CH0_OCAL_LSB,0x0000); Serial.println("CH0_OCAL_LSB 写入");
adc.writeReg(CH0_GCAL_MSB,0x0000); Serial.println("CH0_GCAL_MSB 写入");
adc.writeReg(CH0_GCAL_LSB,0x0000); Serial.println("CH0_GCAL_LSB 写入");
adc.writeReg(REGMAP_CRC, 0x0000); Serial.println("REGMAP_CRC 写入");
adc.writeReg(RESERVED, 0x0000); Serial.println("RESERVED 写入");
// 再次读寄存器验证
Serial.println("\n寄存器回读:");
#define RD(reg) \
tmp = adc.readReg(reg); \
Serial.print(#reg); Serial.print(" = 0x"); Serial.println(tmp, HEX);
RD(GAIN1); RD(CFG); RD(MODE); RD(CLOCK);
RD(THRSHLD_MSB); RD(THRSHLD_LSB);
RD(CH0_CFG); RD(CH0_OCAL_MSB); RD(CH0_OCAL_LSB);
RD(CH0_GCAL_MSB); RD(CH0_GCAL_LSB);
RD(REGMAP_CRC); RD(RESERVED);
#undef RD
// 最后发送 START 命令,开始连续转换
sendCommand(CMD_START);
delay(10);
Serial.println("发送 START,开始转换");
}
void loop() {
// 等待 DRDY 低电平(新数据准备好)
if (digitalRead(DRDY_PIN) == LOW) {
int32_t adcData[2] = {0};
adc.rawChannels(channelIds, 2, adcData);
Serial.print("ADC 数据:");
for (uint8_t i = 0; i < 2; i++) {
Serial.print("Ch"); Serial.print(channelIds[i]);
Serial.print(" = "); Serial.print(adcData[i]);
Serial.print(" ");
}
Serial.println();
}
// 如果想更精细地控制读取频率,可以在此加个小延时
delay(1000);
}
ADS131M04.h
/* This is a library for the ADS131M04 4-channel ADC
Product information:
https://www.ti.com/product/ADS131M04
Datasheet:
https://www.ti.com/lit/gpn/ads131m04
This library was made for Imperial College London Rocketry
Created by Daniele Valentino Bella
*/
#define CLKIN_SPD 8192000 // Clock speed for the CLKIN pin on the DAC
#define SCLK_SPD 4000000 // SPI frequency of DAC
#ifndef ADS131M04_H
#define ADS131M04_H
#include <Arduino.h>
#include <SPI.h>
#include "registerDefinitions.h"
class ADS131M04 {
public:
ADS131M04(int8_t _csPin, int8_t _clkoutPin, SPIClass* _spi, int8_t _clockCh = 1);
void begin(void);
void rawChannels(int8_t * channelArrPtr, int8_t channelArrLen, int32_t * outputArrPtr);
int32_t rawChannelSingle(int8_t channel);
uint16_t readReg(uint8_t reg);
bool writeReg(uint8_t reg, uint16_t data);
bool setGain(uint8_t log2Gain0 = 0, uint8_t log2Gain1 = 0, uint8_t log2Gain2 = 0, uint8_t log2Gain3 = 0);
bool globalChop(bool enabled = false, uint8_t log2delay = 4);
private:
int8_t csPin, clkoutPin, clockCh;
SPIClass* spi;
bool initialised;
void spiCommFrame(uint32_t * outputArray, uint16_t command = 0x0000);
uint32_t spiTransferWord(uint16_t inputData = 0x0000);
int32_t twoCompDeco(uint32_t data);
};
#endif
ADS131M04.cpp
/* This is a library for the ADS131M04 4-channel ADC
Product information:
https://www.ti.com/product/ADS131M04
Datasheet:
https://www.ti.com/lit/gpn/ads131m04
This library was made for Imperial College London Rocketry
Created by Daniele Valentino Bella & Iris Clercq-Roques
*/
#include <Arduino.h>
#include <SPI.h>
#include "registerDefinitions.h"
#include "ADS131M04.h"
ADS131M04::ADS131M04(int8_t _csPin, int8_t _clkoutPin, SPIClass* _spi, int8_t _clockCh) {
csPin = _csPin;
clkoutPin = _clkoutPin;
spi = _spi;
clockCh = _clockCh;
initialised = false;
}
void ADS131M04::begin(void) {
pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH);
spi->begin();
// // Set CLKOUT on the ESP32 to give the correct frequency for CLKIN on the DAC
// ledcSetup(clockCh, CLKIN_SPD, 2);
// ledcAttachPin(clkoutPin, clockCh);
// ledcWrite(clockCh, 2);
initialised=true;
}
void ADS131M04::rawChannels(int8_t * channelArrPtr, int8_t channelArrLen, int32_t * outputArrPtr) {
/* Writes data from the channels specified in channelArr, to outputArr,
in the correct order.
channelArr should have values from 0-3, and channelArrLen should be the
length of that array, starting from 1.
*/
uint32_t rawDataArr[6];
// Get data
spiCommFrame(&rawDataArr[0]);
// Save the decoded data for each of the channels
for (int8_t i = 0; i<channelArrLen; i++) {
*outputArrPtr = twoCompDeco(rawDataArr[*channelArrPtr+1]);
outputArrPtr++;
channelArrPtr++;
}
}
int32_t ADS131M04::rawChannelSingle(int8_t channel) {
/* Returns raw value from a single channel
channel input from 0-3
*/
int32_t outputArr[1];
int8_t channelArr[1] = {channel};
rawChannels(&channelArr[0], 1, &outputArr[0]);
return outputArr[0];
}
bool ADS131M04::globalChop(bool enabled, uint8_t log2delay) {
/* Function to configure global chop mode for the ADS131M04.
INPUTS:
enabled - Whether to enable global-chop mode.
log2delay - Base 2 log of the desired delay in modulator clocks periods
before measurment begins
Possible values are between and including 1 and 16, to give delays
between 2 and 65536 clock periods respectively
For more information, refer to the datasheet.
Returns true if settings were written succesfully.
*/
uint8_t delayRegData = log2delay - 1;
// Get current settings for current detect mode from the CFG register
uint16_t currentDetSett = (readReg(CFG) << 8) >>8;
uint16_t newRegData = (delayRegData << 12) + (enabled << 8) + currentDetSett;
return writeReg(CFG, newRegData);
}
bool ADS131M04::writeReg(uint8_t reg, uint16_t data) {
/* Writes the content of data to the register reg
Returns true if successful
*/
uint8_t commandPref = 0x06;
// Make command word using syntax found in data sheet
uint16_t commandWord = (commandPref<<12) + (reg<<7);
digitalWrite(csPin, LOW);
spi->beginTransaction(SPISettings(SCLK_SPD, MSBFIRST, SPI_MODE1));
spiTransferWord(commandWord);
spiTransferWord(data);
// Send 4 empty words
for (uint8_t i=0; i<4; i++) {
spiTransferWord();
}
spi->endTransaction();
digitalWrite(csPin, HIGH);
// Get response
uint32_t responseArr[6];
spiCommFrame(&responseArr[0]);
if ( ( (0x04<<12) + (reg<<7) ) == responseArr[0]) {
return true;
} else {
return false;
}
}
bool ADS131M04::setGain(uint8_t log2Gain0, uint8_t log2gainCommand, uint8_t log2Gain2, uint8_t log2Gain3) {
/* Function to set the gain of the four channels of the ADC
Inputs are the log base 2 of the desired gain to be applied to each
channel.
Returns true if gain was succesfully set.
Function written by Iris Clercq-Roques
*/
uint16_t gainCommand=log2Gain3<<4;
gainCommand+=log2Gain2;
gainCommand<<=8;
gainCommand+=(log2gainCommand<<4);
gainCommand+=log2Gain0;
return writeReg(GAIN1, gainCommand);
}
uint16_t ADS131M04::readReg(uint8_t reg) {
/* Reads the content of single register found at address reg
Returns register value
*/
uint8_t commandPref = 0x0A;
// Make command word using syntax found in data sheet
uint16_t commandWord = (commandPref << 12) + (reg << 7);
uint32_t responseArr[6];
// Use first frame to send command
spiCommFrame(&responseArr[0], commandWord);
// Read response
spiCommFrame(&responseArr[0]);
return responseArr[0] >> 16;
}
uint32_t ADS131M04::spiTransferWord(uint16_t inputData) {
/* Transfer a 24 bit word
Data returned is MSB aligned
*/
uint32_t data = spi->transfer(inputData >> 8);
data <<= 8;
data |= spi->transfer((inputData<<8) >> 8);
data <<= 8;
data |= spi->transfer(0x00);
return data << 8;
}
void ADS131M04::spiCommFrame(uint32_t * outPtr, uint16_t command) {
// Saves all the data of a communication frame to an array with pointer outPtr
digitalWrite(csPin, LOW);
spi->beginTransaction(SPISettings(SCLK_SPD, MSBFIRST, SPI_MODE1));
// Send the command in the first word
*outPtr = spiTransferWord(command);
// For the next 4 words, just read the data
for (uint8_t i=1; i < 3; i++) {
outPtr++;
*outPtr = spiTransferWord() >> 8;
}
// Save CRC bits
// outPtr++;
// *outPtr = spiTransferWord();
spi->endTransaction();
digitalWrite(csPin, HIGH);
}
int32_t ADS131M04::twoCompDeco(uint32_t data) {
// Take the two's complement of the data
data <<= 8;
int32_t dataInt = (int)data;
return dataInt/pow(2,8);
}