[part 1 part 2]
In this post the code I will present the code related to the simple project described in my previous post.
Basically this piece of code send some data through one of the SPI using DMA. This approach has two nice properties: the CPU does not have to wait until the transfer has finished; moreover, if the data at the 595s’ outputs need to be maintained for a certain period of time (e.g.: in order to communicate with some old slower logic) one can use the circular mode of the DMA to manage the timing, again without afflicting CPU performance.
So, first we want to configure the STM32 peripherals for our purpose. For this purpose, using the nice STM32CubeMX from STMicroelectronics is seems perfect.
The STM32CubeMX project can be downloaded from here, but mainly we:
- configure clocking (the external crystal is 8 MHz, this involves the RCC configuration)
- configure some GPIOs (the 4 LEDs and one line to control the RCLK input of the 595s)
- configure the SPI
- configure the DMA to use the SPI
- configure the SWD (Serial Wire Debugging)
- configure the USART (for debug)
The complete code, that can be downloaded from here, mainly performs the following tasks:
- Perform some initialization (mainly generated by the STM32CubeMX utility)
- Enter the main cycle in which:
- Prepare the data to be sent to the 595s
- Move the RCLK pin on PC3 (the setSTCP function)
- Start the DMA transfer
- Collaterally some LEDs on the discovery board are toggled and the time required by the DMA to perform the transfer is measured and sent through the serial port.
Of course, take a deep look at the code to understand what it exactly does before executing it on your device.
Happy coding 🙂
[part 1 part 2]
In this post I will describe a simple project. The idea is to use a bunch of daisy-chained serial-in/parallel-out shift registers (namely the 74HC595) to expand my STM32F4Discovery board.
First questions: the discovery board has a plenty of GPIOs, so why not using them directly? In other words: why using external circuitry to obtain something that can in principle be obtained simply using the GPIO configured as outputs?
- With only 3 wires on the controller side we can control multiple outputs; this simplifies circuit routing;
- the number of outputs can be increased simply by increasing the daisy-chain length (at the cost of slower update speed);
- using the SPI in DMA mode, the CPU is free to perform other tasks while the external outputs are updated; this can become a substantial performance improvement if the number of lines we want to control is greater than 16 (the size of the GPIOs per register);
- the ‘595 can produce 5V signals.
Of course this approach has also some cons:
- More devices are needed, one ‘595 per 8 lines, this has a cost and requires space on the PCB (but more signals do, too);
- more devices have to be powered;
- the update speed of the output lines is limited by the speed of the SPI channel and the ‘595 propagation time; and the more the output lines we want to control, the slower the maximum update speed.
The reference circuit that I’m considering contains four 74hc595 registers, allowing to control 32 output lines:
Of course, for practical applications the output of the ‘595s can be routed to a suitable connector instead of the LEDs.
If 3-state outputs are needed, the G input of the ‘595s can be controlled by (separately per chip or all together with a single line); in our case the ‘595s outputs are always active.
The 74HC595 contains two main items: one 8-bit shift register and an 8-lines latch. Simplifying, the working principle of the ‘595 is simple (pin names reported on datasheet from various manufacturers may vary, so I’ll refer to the names reported in the previous figure):
- At the rising edge of the clock input SRCLK, data present at SER input is loaded into the shift register;
- when a rising edge is detected at the RCLK, the data contained in the shift register are presented at the outputs QA..QH;
- ‘595s can be daisy-chained thanks to the shift register output, at /QH;
- a shift register clear input SRCLR is available, as well as an output enable input G.
The timing diagram of the 74HC595 is reported in the following figure, in which a single pulse is propagated in the shift register and presented at the output pins:
So, the basic (and far from being novel) idea is to write four bytes to one of the SPIs of the STM32F407 microcontroller of the discovery board to update the 32 output pins in a single operation using the DMA.
In the next post, the code for the STM32F4 microcontroller will be described.