This time we will use the information about schematics and oscilloscopes that we covered last time, to configure the SPI bus to suit an accelerometer. Our example development board, the ST STM32F407G-DISC1, comes with a three axis accelerometer, the ST LIS3DSH, attached to the SPI bus.
To communicate with this accelerometer, we have to read through the data sheets and schematics to figure out which device, pins, and parameters to use, then we will use CubeMX to help us get the processor started.
So, what is necessary to get the SPI bus working? From the schematic on page 36 of the User Manual for our dev board, the labels on pins 4, 6, and 7, show that the device is hooked up to SPI1, and pin 8 is the chip select line. The ports and pins used are:
- SPI Clock PA5
- SPI MOSI PA7
- SPI MISO PA6
- Chip Select (CS) PE3
This accelerometer, even though it is produced by the same company that makes the processor, uses a different set of names for the SPI pins:
- Chip Select is CS
- SPI Clock is SPC
- MOSI is SDI (“Master out, slave in” becomes “Slave data in”)
- MISO is SDO (“Slave data out”)
The diagram above, from the data sheet of the accelerometer, shows that the select pin (CS) is active low, so this pin should really be called select* or CS*, but for now remember that CS is high when the chip is not being used (deselected) and goes low when you want to talk to this chip (selected).
Next, if you look at the state of clock (SPC) when the chip is not selected (CS high), we can determine the clock polarity (CPOL) parameter. CPOL is the parameter that determines the level of the clock line when the clock is idle. So we want to configure CPOL to have the clock idle high.
This diagram also shows that SDI and SDO are stable on the rising edge of the clock. How? I'll explain that in a bit. We have to set the clock phase (CPHA) parameter to have the SPI bus sample SDI and SDO on the rising edge.
Again from the accelerometer data sheet, we need to figure out how fast we can run the chip. The clock frequency comes from this table: 10MHz is the maximum.
To The Cube
Rather than poking values into the configuration registers to set up the SPI master, we are going to use CubeMX to do the dirty work for us. If you insist on shifting your own registers, take a look at the code generated by CubeMX to see if you missed anything.
Since we are dealing with SPI port 1, in the Pinout tab, select SPI1.
Initially SPI1 is set to Disable. The processor can act as either an SPI master or slave, and are going to set it up to act as a master. Masters control the bus and get data from slaves.
Half or full duplex? Full duplex means that data will be sent and receive simultaneously in normal SPI fashion using MOSI and MISO. Half duplex is an odd version of SPI where one wire is used for both MOSI and MISO in a time division multiplexing way, first being an output, then an input.
Receive only is used when data will only be received from the slave. As a master, this would be used if you had something like an ADC that couldn’t be configured, and sent data when selected and clocked. As a slave, we would be receiving commands from the master and responding without sending any information back.
Transmit only is used if you had an output device like a DAC or an LCD display. You don’t expect a response back.
As we want to send commands and receive data, we will choose Full-Duplex Master.
Next, the Hardware NSS Signal (not slave select), this is a weird one. This processor provides a select pin, but ST decided to use it for an extremely uncommon situation where you have more than one master on the bus. I’ve never run into a system that does this. Set this parameter to Disable.
Set up your clocks to use the external 8MHz crystal (enable it in the RCC section of the Pinout tab), then set up your clocks in the Clock Configuration tab, using the high speed external crystal (HSE) in the PLL source mux, and set HCLK to 168MHz.
Next, in the Configuration tab, select SPI1.
In the clock parameters, we need to set a prescaler to get the clock down from 84MHz (APB2 clock in the clock tab) down to 10MHz or less (from the accelerometer data sheet). A prescaler of /8 would give 10.5MHz, which might work but unless you are asking for someone to give you a dope slap when it doesn’t work on a hot summer day, don’t do it. A prescaler of /16 would give 5.25MHz, that works.
The Clock Polarity (CPOL) is the idle state of the clock. We need this to be high.
Next, the clock phasing. We have a choice of 1 edge or 2? What???
The above image is from my oscilloscope, capturing the clock signal and a request coming from the master. Take a look at the bottom trace, this is the clock signal. At point 1, this is with the chip deselected, the clock idles high (CPOL = high). Point 2 is the bottom of a falling edge. Point 3 is the top of a rising edge. I’ve marked all of the rising edges with an asterisk for convenience.
This chip assumes that MOSI and MISO will change levels, when necessary, on falling clock edges. Also, MOSI and MISO will be finished changing and valid on rising edges. In the diagram above, you can see how the top line changes between high and low on the falling edges and is stable on the rising edges (the points with the asterisks).
When reading the timing diagrams in the data sheets, they show the data lines much like you would see on an oscilloscope. In the diagram above, the stable data is either high or low, so they show a trace that looks like it is high and low at the same time. You are to understand that it can be one or the other at this point in time. When the data is changing it is shown as the lines crossing. This is their way of showing that is transitioning from high to low and vice versa.
How ST Names This Stuff
This diagram is from the processor data sheet. We need to figure out which set of traces match the diagram in the accelerometer data sheet.
Since we have the clock idling high, we can look at the traces marked CPOL=1 in the charts above. We need to figure out which set has a clock that idles high and a rising clock edge when the data is stable. That is the top set of traces, CPHA=1.
CubeMX has a completely different way of expressing the phase parameter. To figure out the clock phasing parameter we need to count how many edges have gone by, from clock idle until the data lines are valid.
The first edge from our high idle will be a falling edge. The second edge will be a rising edge. It is at this point that the data is valid. We want edge 2. Confusingly, what the manual calls CPHA=1, Cube calls 2 Edge. (I’ve sent a message to ST asking for the Cube team to coordinate this parameter with the manual.)
Back in the pinout tab, we set the Hardware NSS Signal to disable, and in the configuration panel the parameter NSS Signal type will show as Software.
The board was not laid out to use the hardware select function. Instead, the select pin of the accelerometer is hooked to port PE3. We will just use the HAL GPIO functions to turn that bit on and off at the appropriate time.
In the Pin Configuration panel for GPIO, choose PE3, the chip select pin. The only alteration here is the GPIO output level being high. This is the initial state of the chip select pin when the system first starts up. We deselect the accelerometer as quickly as possible.
All Together Now
Now we have the configuration parameters filled in and we can generate some code and get our project to compile. See this post for a reminder of how to generate code.
Let’s review the critical parameters:
- We know which pins are connected to the slave
- MOSI and MISO as a full duplex set
- Clock speed at 5.25MHz, less than the accelerometer max of 10MHz
- Clock polarity as CPOL high and phase as 2 Edge
- Chip select is active low, and we will have to control it manually.
CubeMX has generated the startup code we need, and next time we will use the HAL to get some data flowing.
This post is part of a series. Please see the other posts here.
Music to work by: Alpha Boys School Radio streaming Reggae, Ska, and Jazz, 24 hours a day, from the Alpha Boy's School in Kingston, Jamaica.