Polling
This example reads the mouse ID information using the SPI3W polling method.
Communication with the mouse is done via SPI3W, and the specified information is read by accessing data at a designated address.
Requirements
The sample supports the following development kits:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
For more requirements, please refer to Quick Start.
Wiring
EVB connects PWM3610DM-SUDU mouse, connects P2_2 to CLK, P2_3 to SDIO, P2_4 to CS#, and also connects GND and VDD.
Hardware Introduction
PWM3610DM-SUDU is a laser mouse sensor module. The PMW3610DM-SUDU registers can be accessed through the serial port. The registers are used for reading motion data and status, as well as setting device configurations. In this example, it is used to demonstrate communication with SPI3W.
Building and Downloading
This sample can be found in the SDK folder:
Project file: board\evb\io_sample\SPI3WIRE\Polling\mdk
Project file: board\evb\io_sample\SPI3WIRE\Polling\gcc
Please follow these steps to build and run the example:
Open sample project file.
To build the target, follow the steps listed on the Generating App Image in Quick Start.
After a successful compilation, the app bin
app_MP_xxx.bin
will be generated in the directorymdk\bin
orgcc\bin
.To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.
Press reset button on EVB board and it will start running.
Experimental Verification
After starting the EVB, print the obtained ID information. If the ID is 0x3e and 0x01 (representing only the PWM3610DM-SUDU mouse), it indicates a successful test.
id[0] = 0x3e, id[1] = 0x01 SPI3W test pass!
Code Overview
This chapter will be introduced according to the following several parts:
Peripheral initialization will be introduced in chapter Initialization.
Functional implementation after initialization will be introduced in chapter Function Implementation.
Source Code Directory
Project directory:
sdk\board\evb\io_sample\SPI3WIRE\Polling
Source code directory:
sdk\src\sample\io_sample\SPI3WIRE\Polling
Source files are currently categorized into several groups as below.
└── Project: Polling
└── secure_only_app
└── include
├── app_define.h
└── rom_uuid.h
├── cmsis includes CMSIS header files and startup files
├── overlay_mgr.c
├── system_rtl876x.c
└── startup_rtl876x.s
├── lib includes all binary symbol files that user application is built on
├── rtl8752h_sdk.lib
├── gap_utils.lib
└── ROM.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl876x_rcc.c
├── rtl876x_pinmux.c
├── rtl876x_nvic.c
└── rtl876x_3wire_spi.c
├── profile
└── app includes the ble_peripheral user application implementation
└── main_ns.c
Initialization
When the EVB reset, the main()
function will be called, executing the following process:
int main(void)
{
extern uint32_t random_seed_value;
srand(random_seed_value);
spi3wire_demo();
while (1)
{
}
}
In spi3wire_demo
, it includes PAD/PINMUX settings, SPI3W peripheral initialization, and processes such as reading the sensor ID. The initialization process related to the peripheral is as follows:
board_3wire_spi_init
is the PAD/PINMUX settings, includes the following process:Configure PAD: Set the pin, PINMUX mode, PowerOn, internal pull-none, output high.
Configure PINMUX: Configure pin P2_2 as SPI2W_CLK function, P2_3 as SPI2W_DATA function, P2_4 as SPI2W_CS function.
void board_3wire_spi_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); }
driver_3wire_spi_init
is the initialization for the SPI3W peripheral, which includes the following steps:Enable the RCC clock.
Set the SPI3W output clock.
Set the operating mode to 3-wire mode.
Set the delay time for reading data.
Set the output to no delay.
Set the SPI3W to normal mode.
void driver_3wire_spi_init(void) { /* Enable SPI3WIRE clock */ RCC_PeriphClockCmd(APBPeriph_SPI2W, APBPeriph_SPI2W_CLOCK, ENABLE); /* Initialize SPI3WIRE */ SPI3WIRE_InitTypeDef SPI3WIRE_InitStruct; SPI3WIRE_StructInit(&SPI3WIRE_InitStruct); SPI3WIRE_InitStruct.SPI3WIRE_SysClock = 20000000; SPI3WIRE_InitStruct.SPI3WIRE_Speed = 800000; SPI3WIRE_InitStruct.SPI3WIRE_Mode = SPI3WIRE_3WIRE_MODE; /** The delay time from the end of address phase to the start of read data phase. * delay time = (SPI3WIRE_ReadDelay +1)/(2*SPI3WIRE_Speed). * delay time = (0x03 + 1)/(2 * speed) = 2.5us */ SPI3WIRE_InitStruct.SPI3WIRE_ReadDelay = 0x3; SPI3WIRE_InitStruct.SPI3WIRE_OutputDelay = SPI3WIRE_OE_DELAY_NONE; SPI3WIRE_InitStruct.SPI3WIRE_ExtMode = SPI3WIRE_NORMAL_MODE; SPI3WIRE_Init(&SPI3WIRE_InitStruct); }
Functional Implementation
After initialization is complete, perform signal synchronization for the SPI3W. Set the resync time, send the resync signal, and disable the resync signal after the resync signal output is complete.
void spi3wire_demo(void) { ... /** Send resync time. Resync signal time = 2*1/(2*SPI3WIRE_Speed) = 1.25us * This parameter can be only be the following value: 0x0 to 0xf. */ SPI3WIRE_SetResyncTime(2); SPI3WIRE_ResyncSignalCmd(ENABLE); while (SPI3WIRE_GetFlagStatus(SPI3WIRE_FLAG_RESYNC_BUSY) == SET); SPI3WIRE_ResyncSignalCmd(DISABLE); ... }
Execute
SPI3W_Cmd
function to enable the SPI3W function.Execute
spi3wire_readbyte
function to read the mouse ID.Wait for the busy status flag to clear.
Clear the data in the SPI3W receive FIFO.
Execute
SPI3WIRE_StartRead()
to read one data from the address.Execute
SPI3WIRE_ReadBuf()
to read the data in the SPI3W receive FIFO.Return the read data and print it.
uint8_t spi3wire_readbyte(uint8_t address) { uint8_t reg_value = 0; uint32_t timeout = 0; /* Check spi busy or not */ while (SPI3WIRE_GetFlagStatus(SPI3WIRE_FLAG_BUSY) == SET) { timeout++; if (timeout > 0x1ffff) { break; } } /* Clear Receive data length */ SPI3WIRE_ClearRxDataLen(); SPI3WIRE_StartRead(address, 1); timeout = 0; while (SPI3WIRE_GetFlagStatus(SPI3WIRE_FLAG_BUSY) == SET) { timeout++; if (timeout > 0x1ffff) { break; } } /* Get the length of received data */ while (SPI3WIRE_GetRxDataLen() == 0); /* Read data */ SPI3WIRE_ReadBuf(®_value, 1); return reg_value; }