Home | Projects | Notes > MCU Peripheral Drivers > SPI Application 1: Master Only Tx (Blocking) (spi_01_master_only_tx_blocking.c
)
spi_01_master_only_tx_blocking.c
)
Test the SPI_TxBlocking)
API to send the string "Hello world" with the following configurations:
SPI2 - Master mode
SCLK - Max possible
DFF = 0, and DFF = 1
For this application, only MOSI and SCLK pins will be used. (No slave, so MISO, NSS pins are not necessary.) Find out the GPIO pins over which SPI2 can communicate! Look up the "Alternate function mapping" table in the datasheet.
SPI2_SCK
SPI2_MOSI
SPI2_MISO
SPI2_NSS
To analyze the communication with the logic analyzer, connect the channels as follows:
CH0 - SCLK
CH1 - MOSI
spi_01_master_only_tx_blocking.c
Path: Project/Src/
xxxxxxxxxx
1381/*******************************************************************************
2 * File : spi_01_master_only_tx_blocking.c
3 * Brief : Program to test SPI master's Tx (blocking) functionality
4 * (without slave)
5 * Author : Kyungjae Lee
6 * Date : May 27, 2023
7 ******************************************************************************/
8
9/**
10 * Pin selection for SPI communication
11 *
12 * SPI2_SCK - PB13 (AF5)
13 * SPI2_MOSI - PB15 (AF5)
14 * SPI2_MISO - PB14 (AF5)
15 * SPI2_NSS - PB12 (AF5)
16 */
17
18/* strlen() */
19
20
21/**
22 * SPI2_PinsInit()
23 * Brief : Initializes and configures GPIO pins to be used as SPI2 pins
24 * Param : None
25 * Retval : None
26 * Note : N/A
27 */
28void SPI2_PinsInit(void)
29{
30 GPIO_Handle_TypeDef SPI2Pins;
31
32 /* Zero-out all the fields in the structures (Very important! SPI2Pins
33 * is a local variables whose members may be filled with garbage values before
34 * initialization. These garbage values may set (corrupt) the bit fields that
35 * you did not touch assuming that they will be 0 by default. Do NOT make this
36 * mistake!
37 */
38 memset(&SPI2Pins, 0, sizeof(SPI2Pins));
39
40 SPI2Pins.pGPIOx = GPIOB;
41 SPI2Pins.GPIO_PinConfig.GPIO_PinMode = GPIO_PIN_MODE_ALTFCN;
42 SPI2Pins.GPIO_PinConfig.GPIO_PinAltFcnMode = 5;
43 SPI2Pins.GPIO_PinConfig.GPIO_PinOutType = GPIO_PIN_OUT_TYPE_PP;
44 /* I2C - Open-drain only!, SPI - Push-pull okay! */
45 SPI2Pins.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_PIN_NO_PUPD; /* Optional */
46 SPI2Pins.GPIO_PinConfig.GPIO_PinSpeed = GPIO_PIN_OUT_SPEED_HIGH; /* Medium or slow ok as well */
47
48 /* SCLK */
49 SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_13;
50 GPIO_Init(&SPI2Pins);
51
52 /* MOSI */
53 SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_15;
54 GPIO_Init(&SPI2Pins);
55
56 /* MISO (Not required for this application, save it for other use) */
57 //SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_14;
58 //GPIO_Init(&SPI2Pins);
59
60 /* NSS (Not required for this application, save it for other use) */
61 //SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_12;
62 //GPIO_Init(&SPI2Pins);
63} /* End of SPI2_PinsInit */
64
65/**
66 * SPI2_Init()
67 * Brief : Creates an SPI2Handle and initializes SPI2 peripheral parameters
68 * Param : None
69 * Retval : None
70 * Note : N/A
71 */
72void SPI2_Init(void)
73{
74 SPI_Handle_TypeDef SPI2Handle;
75
76 /* Zero-out all the fields in the structures (Very important! SPI2Handle
77 * is a local variables whose members may be filled with garbage values before
78 * initialization. These garbage values may set (corrupt) the bit fields that
79 * you did not touch assuming that they will be 0 by default. Do NOT make this
80 * mistake!
81 */
82 memset(&SPI2Handle, 0, sizeof(SPI2Handle));
83
84 SPI2Handle.pSPIx = SPI2;
85 SPI2Handle.SPI_Config.SPI_BusConfig = SPI_BUS_CONFIG_FULL_DUPLEX;
86 SPI2Handle.SPI_Config.SPI_DeviceMode = SPI_DEVICE_MODE_MASTER;
87 SPI2Handle.SPI_Config.SPI_SCLKSpeed = SPI_SCLK_SPEED_PRESCALAR_2; /* Generates 8MHz SCLK */
88 /* Min prescalar -> maximum clk speed */
89 SPI2Handle.SPI_Config.SPI_DFF = SPI_DFF_8BITS;
90 SPI2Handle.SPI_Config.SPI_CPOL = SPI_CPOL_LOW;
91 SPI2Handle.SPI_Config.SPI_CPHA = SPI_CPHA_LOW;
92 SPI2Handle.SPI_Config.SPI_SSM = SPI_SSM_EN; /* SW slave mgmt enabled for NSS pin since NSS is not used */
93
94 SPI_Init(&SPI2Handle);
95} /* End of SPI2_Init */
96
97
98int main(int argc, char *argv[])
99{
100 char msg[] = "Hello world"; /* Message to transnmit */
101
102 /* Initialize and configure GPIO pins to be used as SPI2 pins */
103 SPI2_PinsInit();
104
105 /* Initialize SPI2 peripheral parameters */
106 SPI2_Init();
107 /* At this point, all the required parameters are loaded into SPIx control registers.
108 * But, this does not mean that SPI2 peripheral is enabled.
109 *
110 * SPI configuration must be completed before it is enabled. When SPI is enabled, it
111 * will be busy communicating with other device(s) and will not allow modifying its
112 * control registers.
113 */
114
115 /* To make NSS signal pulled to high internally and avoid MODF error */
116 SPI_SSIConfig(SPI2, ENABLE);
117
118 /* Enable SPI2 peripheral (Set SPI_CR1 bit[6] SPE - Peripheral enabled) */
119 SPI_PeriControl(SPI2, ENABLE);
120
121 /* Send data */
122 SPI_TxBlocking(SPI2, (uint8_t *)msg, strlen(msg));
123
124 /* Wait until SPI no longer busy */
125 while (SPI2->SR & (0x1 << SPI_SR_BSY));
126 /* SPI_SR bit[7] - BSY (Busy flag)
127 * 0: SPI (or I2S) not busy
128 * 1: SPI (or I2S) is busy in communication or Tx buffer is not empty
129 * This flag is set and cleared by hardware.
130 */
131
132 /* Disable SPI2 peripheral (Terminate communication) */
133 SPI_PeriControl(SPI2, DISABLE);
134
135 while (1);
136
137 return 0;
138} /* End of main */
The following snapshots are taken using the Logic Analyzer.
The following snapshot shows "Hello world" being transferred through MOSI line.
Since CPOL = 0, SCLK begins LOW, and stays LOW during the idle state.
Since CPHA = 0, the data appears on the MOSI line during the 1st edge of the SCLK.
Try different combinations of CPOL and CPHA and monitor the digital waveform.
Here we used SSM (software Slave Management) is enabled. For master, the NSS signal should be tied to +VCC when not used to avoid MODF error which happens in multi-master situation. So, be sure to set SSI bit to pull NSS pin to +VCC internally.
Remember!
SSI bit influences NSS state when SSM = 1. By default, SSI = 0, so NSS will be pulled low which is not acceptable for master when working in non-multi-master situation.