例程讲解-02-arduino_spi_slave 从设备

# Arduino 作为SPI主设备, OpenMV作为SPI从设备。

#
# 请把OpenMV和Arduino按照下面连线:
#
# OpenMV Cam Master Out Slave In (P0) - Arduino Uno MOSI (11)
# OpenMV Cam Master In Slave Out (P1) - Arduino Uno MISO (12)
# OpenMV Cam Serial Clock        (P2) - Arduino Uno SCK  (13)
# OpenMV Cam Slave Select        (P3) - Arduino Uno SS   (10)
# OpenMV Cam Ground                   - Arduino Ground

import pyb, ustruct

text = "Hello World!\n"
data = ustruct.pack("<bi%ds" % len(text), 85, len(text), text) # 85 is a sync char.

# 使用 "ustruct" 来生成需要发送的数据包
# "<" 把数据以小端序放进struct中
# "b" 把一个 signed char 放进数据流
# "i" 把一个 signed integer 放进数据流
# "%ds" 把字符串放进数据流,比如:"13s" 对应的 "Hello World!\n" (13 chars).
# 详见 https://docs.python.org/3/library/struct.html


# Zero pad data to a multiple of 4 bytes plus 4 bytes.
data += "\x00" * (4 + (len(data) % 4))

# READ ME!!!
#
# 请理解,当您的OpenMV摄像头不是SPI主设备,所以不管是使用中断回调,
# 还是下方的轮循,都可能会错过响应发送数据给主机。处于这点,
# 你必须设计你的通信协议,比如从设备(OpenMV)没有及时调用"spi.send()"回应,
# 那么SPI读取到的垃圾数据应该被丢弃。为了达到这个目的,我们使用一个85
# (二进制01010101)的同步字符,Arduino将把它看作是第一个读取的字节。
# 如果它没有看到这个,那么它会中止SPI事务,然后再试一次。 其次,
# 为了清除SPI外设状态,我们总是发送四个字节的倍数和一个额外的四个零字节,
# 以确保SPI外设不会保存可能为85的任何陈旧数据。注意,OpenMV可能会随机
# 错过调用 "spi.send()",因为中断服务程序。当你连接到电脑的时候,中断
# 可能会发生很多次。

# OpenMV上的硬件SPI总线都是2
# polarity = 0 -> clock 闲时为低
# phase = 0 -> 取样数据在clock上升沿,输出数据在下降沿。
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)
pin = pyb.Pin("P3", pyb.Pin.IN, pull=pyb.Pin.PULL_UP)
print("Waiting for Arduino...")

# 请注意,为了正常同步工作,OpenMV Cam必须 在Arduino轮询数据之前运行此脚本。
# 否则,I2C字节帧会变得乱七八糟。所以,保持Arduino在reset状态,
# 直到OpenMV显示“Waiting for Arduino...”。

while(True):
    while(pin.value()): pass
    try:
        spi.send(data, timeout=1000)
        # 如果同步第一帧失败,我们再一次同步
        print("Sent Data!") # 没有遇到错误时,会显示
    except OSError as err:
        pass # 不用担心遇到错误,会跳过
        # 请注意,有3个可能的错误。 超时错误(timeout error),
        # 通用错误(general purpose error)或繁忙错误
        #(busy error)。 “err.arg[0]”的错误代码分别
        # 为116,5,16。
    while(not pin.value()): pass
#include <SPI.h>
#define SS_PIN 10
#define BAUD_RATE 19200
#define CHAR_BUF 128

void setup() {
  pinMode(SS_PIN, OUTPUT);
  Serial.begin(BAUD_RATE);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPI.setDataMode(SPI_MODE0);
  delay(1000); // Give the OpenMV Cam time to bootup.
}

void loop() {
  int32_t temp = 0;
  char buff[CHAR_BUF] = {0};
  digitalWrite(SS_PIN, LOW);
  delay(1); // Give the OpenMV Cam some time to setup to send data.

  if (SPI.transfer(1) == 85) { // saw sync char?
    SPI.transfer(&temp, 4); // get length
    int zero_legnth = 4 + ((temp + 1) % 4);
    if (temp) {
      SPI.transfer(&buff, min(temp, CHAR_BUF));
      temp -= min(temp, CHAR_BUF);
    }
    while (temp--) SPI.transfer(0); // eat any remaining bytes
    while (zero_legnth--) SPI.transfer(0); // eat zeros.
  }

  digitalWrite(SS_PIN, HIGH);
  Serial.print(buff);
  delay(1); // Don't loop to quickly.
}

星瞳科技OpenMV官方中文文档函数讲解:

星瞳科技OpenMV官方中文文档函数讲解:

星瞳科技OpenMV官方中文文档函数讲解:

星瞳科技OpenMV官方中文文档函数讲解:

results matching ""

    No results matching ""