接收到的数据在范围内是正确的,而不是在程序中

Received data are correct on scope not in program

我使用 Arduino shiftIn 指令从 MLX90316 接收数据。
它使用一根电线用于 MOSI 和 MISO。
数据由 4 个字节组成 (2+2)
前 2 个字节是角度值。第二个2字节是角度的反转值(第一个补码)
前 2 个字节在范围和程序上是正确的(0x00 和 0x22)
第二个 2 字节在范围(0xFF 和 0XDD)上是正确的,但在程序中经常(不总是)错误(0xFF 和 0xDC 或 0xFF 和 0xCC...)

事实上,当我打印它时,有时只有最后一个字节是错误的。

我尝试将串行速度更改为 9600 bps(结果相同)
我试图在最后一个 shiftIn 之前更改 delayMicroseconds 值(相同的结果)

/* MLX90316 Rotary Position Sensor */

int readAngle();

int pinSS = 10;  // Green Wire
int pinDATA = 11; // Yellow Wire
int pinSCK = 13; // Grey Wire

unsigned int r1=0;
unsigned int r2=0;
unsigned int r3=0;
unsigned int r4=0;

int angle;

void setup(){
  delayMicroseconds(16000);  // 16ms slave start-up
  pinMode(pinSS,OUTPUT);  // Pin Slave Select
  pinMode(pinSCK, OUTPUT); // Pin Clock
  digitalWrite(pinSS, HIGH); // de-select chip
  Serial.begin(115200);
  Serial.println("MLX90316 Rotary Position Sensor");
}

void loop() {
  angle = readAngle();
  Serial.println("");
  Serial.print("r1=");Serial.println(r1,HEX);
  Serial.print("r2=");Serial.println(r2,HEX);
  Serial.print("r3=");Serial.println(r3,HEX);
  Serial.print("r4=");Serial.println(r4,HEX);

  delay(10000);
}

int readAngle() {
  // Start with clock LOW
  digitalWrite(pinSCK, LOW);

  // Data pin in write mode
  pinMode(pinDATA, OUTPUT);

  // take the SS pin low to select the chip:
  digitalWrite(pinSS, LOW);
  delayMicroseconds(30);

  // Send START bytes
  shiftOut(pinDATA, pinSCK, MSBFIRST, 0xAA);
  delayMicroseconds(25);
  shiftOut(pinDATA, pinSCK, MSBFIRST, 0xFF);
  delayMicroseconds(30);  // 30 us between START bytes and DATA

  // Data pin in read mode
  pinMode(pinDATA, INPUT_PULLUP);

  // Receive data
  r1 = shiftIn(pinDATA, pinSCK, MSBFIRST);
  delayMicroseconds(25);
  r2 = shiftIn(pinDATA, pinSCK, MSBFIRST);
  delayMicroseconds(25);
  r3 = shiftIn(pinDATA, pinSCK, MSBFIRST);
  delayMicroseconds(30);
  r4 = shiftIn(pinDATA, pinSCK, MSBFIRST);

  // take the SS pin high to de-select the chip:
  delayMicroseconds(5);
  digitalWrite(pinSS, HIGH);
}

我期望输出 0x00 0x22 0xFF 0xDD

我不知道你用的是哪个Arduino,但是进出功能是非常简单的软件实现。

uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for (i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        if (bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
    }
    return value;
}

MLX90316 只允许 145kHz 的时钟速度,因此这种直接端口访问可能太快了,当您读取数据时数据还没有准备好。 但是由于您有一个可用的范围,您可以简单地检查该时间并在必要时编写您自己的 shiftIn

我认为这个 "version" 应该适用于您的芯片(未经测试)

uint8_t shiftIn2(uint8_t dataPin, uint8_t clockPin) {
    uint8_t value = 0;
    uint8_t i;

    for (i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(4);
        digitalWrite(clockPin, LOW);
        value |= digitalRead(dataPin) << (7 - i);
        delayMicroseconds(4);           
    }
    return value;
}