You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Arduino中通过SPI读取MAX35101的16位寄存器?

MAX35101 TDC芯片0xB8寄存器读取返回0xFF问题排查

问题描述

读取MAX35101的0xB8寄存器(默认值应为0x1311)时,返回值始终为0xFF,读写操作返回布尔值1,需排查代码逻辑问题。

完整代码

#define SS 10                        // D14 = MCP23S08 GPIO SPI select pin
#define SCLK 13                     // D18 SPI SCLK 
#define MISO 12                     // D19 SPI MISO
#define MOSI 11                     // D23 SPI MOSI
#define RESET 0X04 //


#include <SPI.h>

bool MAX35101_Send_Opcode(char opcode);
bool MAX35101_Write_Register(char address, uint16_t DatatoWrite);
void MAX35101_Read_Register(char address, uint16_t* results);


void setup() {
  Serial.begin(115200);
  SPI.begin();
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH); 
}

bool MAX35101_Send_Opcode(char Opcode)
{ 
  bool success;
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
  digitalWrite(SS, LOW);
  success = SPI.transfer(Opcode);
  Serial.println(success);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

bool MAX35101_Write_Register(char address, uint16_t DatatoWrite)// one word register only, Modulates CS# line, Sends address, reads data
{
    bool success;
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);                  //Modulate CS#
    success |= SPI.transfer(address);   //Transmit the 8 bits over the SPI Bus //OPcode address
    success |= SPI.transfer((char) (DatatoWrite >> 8)); //Transmit the 8 bits over the SPI Bus // MSB
    success |= SPI.transfer((char) (DatatoWrite & 0x00FF)); //Transmit the 8 bits over the / Bus //LSB
    digitalWrite(SS, HIGH); 
    SPI.endTransaction();                  //Modulate CS#
    //Serial.println('The write status is ' + success + '.');
    Serial.println(success);
}

void MAX35101_Read_Register(char address, uint16_t* results)//Read one word register only, Modulates CS# line, Sends address, reads data
{
    uint16_t success;
    uint16_t success_data;
    address |= 0x80;    //Read Opcodes Always have MSB of Opcode (address) Set
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);
    delayMicroseconds(1);
    success = SPI.transfer(address);   //Transmit the 8 bits over the SPI Bus
    success |= SPI.transfer(results);
    digitalWrite(SS, HIGH); 
    SPI.endTransaction();
    Serial.println(success);
    //Serial.println(results);
}

unsigned long readRegister(uint8_t registerAddress) //Function for READING a selected register
{
    int registerValueR;
    registerAddress |= 0x80; 
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);
    delayMicroseconds(1); 
    SPI.transfer(registerAddress);
    SPI.transfer(0x00);
    delayMicroseconds(1);
    registerValueR = SPI.transfer(0xFF);
    delayMicroseconds(1);
    digitalWrite(SS, HIGH);
    SPI.endTransaction(); 
    Serial.println(registerValueR);
}

void loop()
{
  //uint16_t readData = 0;
  delay(5000);
  //MAX35101_Write_Register(0x38, 1311);
  readRegister(0xB8);
  delay(60*60*1000);
}

已尝试方案

  • 单独读取1字节
  • 通过或运算合并两个变量读取2字节
  • 观察到串口打印的是读取寄存器时发送的虚拟字节值

代码问题分析与修复

核心问题(readRegister函数)

当前调用的readRegister函数存在严重时序错误,无法正确读取16位寄存器:

  1. 读取位数不足:0xB8是16位寄存器,函数仅读取了1字节。
  2. SPI时序错误:SPI为全双工通信,读寄存器需在发送地址后,连续发送两个dummy字节以接收寄存器的MSB和LSB;当前代码的字节发送/接收顺序完全不符合MAX35101的SPI协议。
  3. 返回类型冗余:寄存器为16位,无需使用unsigned long类型。

修复后的readRegister函数

unsigned int readRegister(uint8_t registerAddress) 
{
    uint16_t registerValue = 0;
    registerAddress |= 0x80; // 设置读操作标志位(最高位为1)
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);
    delayMicroseconds(1); 
    
    // 发送寄存器地址,忽略返回的dummy数据
    SPI.transfer(registerAddress);
    // 接收MSB并左移8位
    registerValue = (uint16_t)SPI.transfer(0x00) << 8;
    // 接收LSB并合并到结果
    registerValue |= SPI.transfer(0x00);
    
    delayMicroseconds(1);
    digitalWrite(SS, HIGH);
    SPI.endTransaction(); 
    
    Serial.print("寄存器0x");
    Serial.print(registerAddress & 0x7F, HEX);
    Serial.print("读取值:0x");
    Serial.println(registerValue, HEX);
    return registerValue;
}

其他函数问题修复

  1. MAX35101_Send_Opcode:MAX35101无需单独发送Opcode,读写操作通过地址+数据完成,该函数无意义,可删除。
  2. MAX35101_Write_Register:错误地将SPI传输返回的字节作为成功标志,实际MAX35101写操作无应答字节,应修正为:
void MAX35101_Write_Register(char address, uint16_t DatatoWrite)
{
    address &= 0x7F; // 写操作地址最高位为0
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);                  
    SPI.transfer(address);   // 发送寄存器地址
    SPI.transfer((char)(DatatoWrite >> 8)); // 发送MSB
    SPI.transfer((char)(DatatoWrite & 0x00FF)); // 发送LSB
    digitalWrite(SS, HIGH); 
    SPI.endTransaction();
}
  1. MAX35101_Read_Register:错误地传递指针给SPI.transfer,应修正为:
void MAX35101_Read_Register(char address, uint16_t* results)
{
    address |= 0x80;    // 设置读操作标志位
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
    digitalWrite(SS, LOW);
    delayMicroseconds(1);
    
    SPI.transfer(address); // 发送地址
    *results = (uint16_t)SPI.transfer(0x00) << 8; // 读取MSB
    *results |= SPI.transfer(0x00); // 读取LSB
    
    digitalWrite(SS, HIGH); 
    SPI.endTransaction();
    
    Serial.print("寄存器0x");
    Serial.print(address & 0x7F, HEX);
    Serial.print("读取值:0x");
    Serial.println(*results, HEX);
}

额外硬件检查建议

  • 确认SS引脚正确连接到MAX35101的CS#引脚
  • 检查SPI总线(SCLK、MOSI、MISO)的接线对应关系
  • 初始化RESET引脚:拉低至少10μs再拉高,完成芯片复位
void setup() {
  Serial.begin(115200);
  SPI.begin();
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH); 
  // 复位芯片
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, LOW);
  delayMicroseconds(10);
  digitalWrite(RESET, HIGH);
  delay(100);
}

内容的提问来源于stack exchange,提问作者Veeramani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:15:49