例程讲解-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, time

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


# 零填充数据为4字节加4字节的倍数。
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)

# NSS callback.
def nss_callback(line):
    global spi, data
    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。

# 在IRQ模式中配置NSS/CS,以便在主机请求时发送数据
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while(True):
    time.sleep_ms(1000)

###################################################################################################
# Arduino Code
###################################################################################################
#
#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); // 给OpenMV摄像头启动的时间
#
void loop() {
  int32_t len = 0;
  char buff[CHAR_BUF] = {0};
  digitalWrite(SS_PIN, LOW);
  delay(1); // 给OpenMV摄像头一些时间来设置发送数据
#
  if (SPI.transfer(1) == 85) { // saw sync char?
    SPI.transfer(&len, 4); // get length
    if (len) {
      SPI.transfer(&buff, min(len, CHAR_BUF));
      temp -= min(len, CHAR_BUF);
    }
    while (len--) SPI.transfer(0); // eat any remaining bytes
  }
#
  digitalWrite(SS_PIN, HIGH);
  Serial.print(buff);
  delay(1); // 延时一点时间,不要马上循环
}

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

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

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

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

results matching ""

    No results matching ""