Polling

该示例通过使用 SPI3W 的轮询方式读取鼠标传感器 ID 信息。

通过 SPI3W 与鼠标传感器进行通信,通过读取指定地址下的数据来读取指定信息。

用户可以通过不同的宏配置改变示例中 SPI3W 的引脚配置信息等,具体宏配置详见 配置选项

环境需求

该示例的环境需求,可参考 环境需求

硬件连线

EVB 外接 PWM3610DM-SUDU 鼠标,连接 P2_2 和 CLK,P2_3 和 SDIO,P2_4 和 CS#,同时连接 GND 和 VDD。

硬件介绍

PWM3610DM-SUDU 为激光鼠标传感器模块。PMW3610DM-SUDU 寄存器可通过串行端口访问。寄存器用于读取运动数据和状态,以及设备配置等信息。 在此示例中,使用该模块用于演示与 SPI3W 的通信,用来读取该模块的 ID 信息。

配置选项

  1. 可配置如下宏修改引脚定义。

    #define SPI_3WIRE_CLK_PIN       P2_2
    #define SPI_3WIRE_DATA_PIN      P2_3
    #define SPI_3WIRE_CS_PIN        P2_4
    

编译和下载

该示例的编译和下载流程,可参考 编译和下载

测试验证

  1. EVB 启动后,SPI3W 开始与鼠标传感器进行通信。通信结束后,打印获取到的 ID 信息。若 ID 为 0x3e 和 0x01(仅代表 PWM3610DM-SUDU 鼠标),代表测试成功。

    id[0] = 0x3e, id[1] = 0x01
    SPI3W test pass!
    

代码介绍

该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。

源码路径

工程文件和源码路径如下:

  • 工程路径: sdk\samples\peripheral\spi3wire\polling\proj

  • 源码路径: sdk\samples\peripheral\spi3wire\polling\src

初始化

外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。

  1. 调用 Pad_Config()Pinmux_Config(),配置对应引脚的 PAD 和 PINMUX。

    void board_spi3wire_init(void)
    {
        Pad_Config(SPI_3WIRE_CLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
        Pad_Config(SPI_3WIRE_DATA_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
        Pad_Config(SPI_3WIRE_CS_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    
        Pinmux_Config(SPI_3WIRE_CLK_PIN, SPI2W_CLK);
        Pinmux_Config(SPI_3WIRE_DATA_PIN, SPI2W_DATA);
        Pinmux_Config(SPI_3WIRE_CS_PIN, SPI2W_CS);
    }
    
  2. 调用 RCC_PeriphClockCmd(),开启 SPI3W 时钟。

  3. 对 SPI3W 外设进行初始化:

    1. 定义 SPI3W_InitTypeDef 类型 SPI3W_InitStruct ,调用 SPI3W_StructInit()SPI3W_InitStruct 预填默认值。

    2. 根据需求修改 SPI3W_InitStruct 参数,SPI3W 的初始化参数配置如下表。

    3. 调用 SPI3W_Init(),初始化 SPI3W 外设。

SPI3W 初始化参数

SPI3W Hardware Parameters

Setting in the SPI3W_InitStruct

SPI3W

SPI3W Source Clock

SPI3W_InitTypeDef::SPI3W_SysClock

20000000

SPI3W Clock

SPI3W_InitTypeDef::SPI3W_Speed

800000

SPI3W Mode (3-Wire or 2-Wire)

SPI3W_InitTypeDef::SPI3W_Mode

SPI3W_3WIRE_MODE

Read Delay Cycle

SPI3W_InitTypeDef::SPI3W_ReadDelay

0x3

功能实现

SPI3W 以轮询模式读取数据的流程如图所示:

这里应该是 SPI polling read flow

SPI3W 轮询模式读取数据流程图

  1. 在读取数据之前执行信号同步的流程。设置 resync 时间,发送 resync 信号,等待 resync 信号输出完毕后失能 resync 信号。随后调用 SPI3W_Cmd() 函数,使能三线 SPI 功能。

    SPI3W_SetResyncTime(2);
    SPI3W_ResyncSignalCmd(ENABLE);
    while (SPI3W_GetFlagStatus(SPI3W_FLAG_RESYNC_BUSY) == SET);
    SPI3W_ResyncSignalCmd(DISABLE);
    SPI3W_Cmd(ENABLE);
    
  2. 调用 spi3wire_readbyte 函数,传入地址参数,读取鼠标 ID 信息。

    1. 等待 busy 状态标志位消除。

    2. 调用 SPI3W_ClearRxDataLen(),清除 SPI3W 的接收的数据长度。

    3. 调用 SPI3W_StartRead(),传入地址信息和需要读取的数据长度,开始读取该地址下的数据。等待 busy 状态标志位消除。

    4. 循环判断是否接收到数据。如果接收到数据,调用 SPI3W_ReadBuf() 读取 SPI3W 接收 FIFO 中数据。

    5. 返回读取的数据并打印。

    uint8_t spi3wire_readbyte(uint8_t address)
    {
        uint8_t reg_value = 0;
        uint32_t timeout = 0;
    
        /* Check spi busy or not */
        while (SPI3W_GetFlagStatus(SPI3W_FLAG_BUSY) == SET)
        {
            timeout++;
            if (timeout > 0x1ffff)
            {
                break;
            }
        }
    
        /* Clear Receive data length */
        SPI3W_ClearRxDataLen();
    
        SPI3W_StartRead(address, 1);
    
        timeout = 0;
        while (SPI3W_GetFlagStatus(SPI3W_FLAG_BUSY) == SET)
        {
            timeout++;
            if (timeout > 0x1ffff)
            {
                break;
            }
        }
    
        /* Get the length of received data */
        while (SPI3W_GetRxDataLen() == 0);
        /* Read data */
        SPI3W_ReadBuf(&reg_value, 1);
    
        return reg_value;
    }