Arduino for PKE8720DF-C13-F10——使用SPI向两个slave的其中一个发送数据

目录

        PKE8720DF-C13-F10开发板SPI功能简介

        Arduino IDE——SPI向两个slave的其中一个发送数据

1)所需材料

2)电路连接

3)代码解析

4)烧录image

5)实验结果 


PKE8720DF-C13-F10开发板SPI功能简介

PKE8720DF-C13-F10 支持摩托罗拉 SPI 串行接口操作,支持主机或从机的操作模式。提供了两个 SPI 端口:

  • SPI0(高速):配置为主机或从机,最大波特率 50MHz
  • SPI1(正常速度):配置为主机,最大波特率 25MHz

SPI 一共有 4 根线,分别是 MOSI(PB18 / PA12)、MISO(PB19 / PA13)、SCLK(PB20 / PA14)和 CS/SS(PB21 / PA15):

  • MOSI (Master Output Slave Input):master 数据输出,slave 数据输入
  • MISO (Master Input Slave Output):master 数据输入,slave 数据输出
  • SCLK (Serial Clock):时钟信号,由 master 产生
  • CS/SS (Chip Select / Slave Select):片选信号,由 master 控制。当一个 master 连接多个 slave 时,CS/SS是 slave 是否被 master 选中的控制信号

下图是一个 master 连接两个 slave 的示意图:

Figure 1. 一个 master 连接两个 slave 示意图

Arduino IDE——SPI向两个slave的其中一个发送数据

Arduino IDE 配置方法以及 PIN 脚对应关系已经在之前的文章中进行了详细的介绍:使用PKE8720DF-C13-F10实现Arduino example——Button_deer_vickey的博客-CSDN博客

1)所需材料

  • 3 × PKE8720DF-C13-F10开发板
  • 3 × USB转type-C数据线
  • 1 × 面包板
  • 11 × 杜邦线

2)电路连接

一块板子的 SPI1 作为 master,PB22 和 PB23 分别为 slave 1 和 slave 2 提供片选信号;另外两块板子的 SPI0 作为 slave:

  • Master board 的 SPI1_MOSI (PA12),SPI1_MISO (PA13),SPI1_SCLK (PA14) 都通过面包板,分别连接到两块 Slave board 的 SPI0_MOSI (PB18),SPI0_MISO (PB19),SPI0_SCLK (PB20)
  • Master board 的 CS0 (PB22) 连接到 Slave board 1 的 SPI0_SS (PB21)
  • Master board 的 CS1 (PB23) 连接到 Slave board 2 的 SPI0_SS (PB21)

3)代码解析

代码通过macro SPI_IS_AS_MASTER 来区分 master 和 slave,完整的源代码文件 SPI_MultiSlave.ino 可以在下面的链接下载:

https://download.csdn.net/download/deer_vickey/88189915?spm=1001.2014.3001.5503

include files 

SPI的接口定义在下面的头文件中,相关函数可以在ambd_arduino源代码中查询,github下载地址:GitHub - ambiot/ambd_arduino: AmebaD Arduino third-party package SDK 

  #include "device.h"
  #include "pinnames.h"
  #include "spi_api.h"
  #include "spi_ex_api.h"
  #include "gpio_api.h"

definitions and global variables

  • SPI_IS_AS_MASTER 用来区分 master 和 slave,1 表示 master,0 表示 slave
  • SCLK_FREQ 是时钟信号的频率
  • TestBuf[] 存放 master 发送以及 slave 接收的数据,数据长度为 64
  • TrDone 表示数据传送或者接收是否结束,1 表示结束
  • 另外还定义了 master 和 slave 的 SPI pins
  #define SPI_IS_AS_MASTER    1
  #define TEST_BUF_SIZE       64
  #define SCLK_FREQ           1000000

  char TestBuf[TEST_BUF_SIZE];
  volatile int TrDone;

  #define SPI_GPIO_CS0        PB_22
  #define SPI_GPIO_CS1        PB_23

  #if SPI_IS_AS_MASTER
  spi_t spi_master;
  //SPI1
  PinName SPIM_MOSI = PA_12;
  PinName SPIM_MISO = PA_13;
  PinName SPIM_SCLK = PA_14;
  PinName SPIM_CS = PA_15;
  #else
  spi_t spi_slave;
  //SPI0
  PinName SPIS_MOSI = PB_18;
  PinName SPIS_MISO = PB_19;
  PinName SPIS_SCLK = PB_20;
  PinName SPIS_CS = PB_21;
  #endif

setup() 

a. master: 

  • 初始化作为片选信号的 GPIO:SPI_GPIO_CS0 和 SPI_GPIO_CS1:
  gpio_init(&spi_cs0, SPI_GPIO_CS0);
  gpio_write(&spi_cs0, 1);          //Initialize GPIO Pin to high 
  gpio_dir(&spi_cs0, PIN_OUTPUT);   // Direction: Output
  gpio_mode(&spi_cs0, PullNone);    // No pull

  gpio_init(&spi_cs1, SPI_GPIO_CS1);
  gpio_write(&spi_cs1, 1);          //Initialize GPIO Pin to high 
  gpio_dir(&spi_cs1, PIN_OUTPUT);   // Direction: Output
  gpio_mode(&spi_cs1, PullNone);    // No pull
  • 初始化 SPI1 (master):
  spi_master.spi_idx = MBED_SPI1;
  spi_init(&spi_master, SPIM_MOSI, SPIM_MISO, SPIM_SCLK, SPIM_CS);
  spi_frequency(&spi_master, SCLK_FREQ);
  spi_format(&spi_master, 8, (SPI_SCLK_IDLE_LOW|SPI_SCLK_TOGGLE_START) , 0);
  • TestBuf[] 赋值,片选信号 SPI_GPIO_CS0 拉低,SPI_GPIO_CS1 拉高,即选择 slave 1:
  for (i=0;i<TEST_BUF_SIZE;i++)
  {
      TestBuf[i] = i;
  }
  gpio_write(&spi_cs0, 0);
  gpio_write(&spi_cs1, 1);
  // wait Slave ready
  delay(1000);
  •  调用 spi_master_write_stream 函数传送 data 之后,打印出 data 的内容:
  spi_irq_hook(&spi_master, (spi_irq_handler)master_tr_done_callback, (uint32_t)&spi_master);
  printf("SPI Master Write Test==>\r\n");
  TrDone = 0;

  spi_master_write_stream(&spi_master, TestBuf, TEST_BUF_SIZE);

  dump_data((const u8 *)TestBuf, TEST_BUF_SIZE, "SPI Master Write Data:");

 b. slave

  •  初始化 SPI0 (slave),并且将 TestBuf[] 内容清空:
  spi_slave.spi_idx = MBED_SPI0;
  spi_init(&spi_slave, SPIS_MOSI, SPIS_MISO, SPIS_SCLK, SPIS_CS);
  spi_format(&spi_slave, 8, (SPI_SCLK_IDLE_LOW|SPI_SCLK_TOGGLE_START) , 1);

  _memset(TestBuf, 0, TEST_BUF_SIZE);
  •  如果当前处于 busy 状态,会打印 “Wait SPI Bus Ready...”:
  while (spi_busy(&spi_slave))
  {
      printf("Wait SPI Bus Ready...\r\n");
      delay(4000);
  }
  • 调用 spi_slave_read_stream 函数接收数据,接收完成后打印出接收到的内容
  • 如果在 15 秒的时间内都没有接收完数据,会打印 “SPI Slave Wait Timeout” 的信息:
  printf("SPI Slave Read Test ==>\r\n");
  spi_irq_hook(&spi_slave, (spi_irq_handler)slave_tr_done_callback, (uint32_t)&spi_slave);
  TrDone = 0;
  spi_flush_rx_fifo(&spi_slave);

  spi_slave_read_stream(&spi_slave, TestBuf, TEST_BUF_SIZE);

  i=0;
  printf("SPI Slave Wait Read Done...\r\n");
  while(TrDone == 0) {
    delay(100);
    i++;
    if (i>150) {
      printf("SPI Slave Wait Timeout\r\n");
      break;
    }
  }
  dump_data((const u8 *)TestBuf, TEST_BUF_SIZE, "SPI Slave Read Data:");

4)烧录image

  • Master:“Tools” --> “Port” 中选择 Master 的 COM 口,SPI_IS_AS_MASTER 定义成 1,点击 “Sketch” --> “Upload” 把 image 烧录到板子中
  • Slave:“Tools” --> “Port” 中选择 Slave 的 COM 口,SPI_IS_AS_MASTER 定义成 0,点击 “Sketch” --> “Upload” 把 image 烧录到板子中

5)实验结果 

先分别按下两个 Slave 的 Reset 键,再按下 Master 的 Reset 键,可以看到下面的 output。

  • 第一张图的 COM31 是 Master,发送的数据为 00 01 02 03 04 ... 3d 3e 3f
  • 第二张图的 COM34 是 Slave 1,接收到的数据为 00 01 02 03 04 ... 3d 3e 3f
  • 第二张图的 COM36 是 Slave 2,打印出了 “SPI Slave Wait Timeout” 信息

因为把片选信号 SPI_GPIO_CS0 拉低,所以 master 选择的是 slave 1。 slave 1 成功接收到 master 发送的数据,slave 0 未接收到数据,实验结果符合预期。

  • master (COM31):

  •  slave 1 (COM34):

  • slave 2 (COM36): 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值