首页 > 解决方案 > 在不在程序中的范围内接收到的数据是正确的

问题描述

我使用 ArduinoshiftIn指令从 MLX90316 接收数据。
它使用一根电线连接 MOSI 和 MISO。
数据由 4 个字节 (2+2) 组成,
前 2 个字节是角度值。第二个字节是角度的反转值(第一个补码)
前 2 个字节在范围和程序上是正确的(0x00 和 0x22)
第二个字节在范围上是正确的(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

标签: arduinospi

解决方案


我不知道您使用的是哪个 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但是由于您有可用的范围,您可以简单地检查该时间并在必要时编写自己的。

我认为这个“版本”应该适用于您的芯片(未经测试)

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;
}

推荐阅读