我在初步尝试在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); }