This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
Internal Peripheral Types
GPIO
General Purpose Input/Output
Most of the pins on your microcontroller can be used to do input or output under direct software control. The GPIO peripheral registers allow you to configure whether each pin is to be an input or ouput and whether it is to be under software control or the control of a peripheral.
When under software control, your code can directly read or change the state of a single pin or set of pins in a bank. While this is very flexible, it is often faster and more reliable to take advantage of the I/O peripherals to do complex protocol exchanges. Software-controlled GPIO is often used for scanning a key matrix, lighting a few individual LEDs, or other simple tasks that depend on direct I/O connections rather than a serial communication line to an external peripheral chip.
When you use software-controlled GPIO signals to implement a communication protocol instead of using a peripheral dedicated to that protocol, it is often called "bit-banging" that protocol.
Timer
Uses a clock to increment or decrement a register on every clock edge. Beyond that common principle, operation and uses can vary a lot!
A basic use for a timer is to create a periodic interrupt for the CPU. All Cortex M3 CPUs have a SysTick timer that can be used as a one-shot or periodic exception that occurs when the timer reaches 0.
Some timers can be used in capture mode, where the register counts continuously and the current value is copied to a capture register when an external (or sometimes internal from another peripheral) signal change occurs. This can be used to measure the rate that some external event occurs, for example.
Some timers can be used in compare mode, where the register counts continuously and causes some action to happen when the timer reaches the value stored on the compare register. There can be multiple compare registers, and different kinds of actions. A common case is for one compare register to toggle the state of a pin, and the other to switch the count direction from up to down. This has the effect of creating a pulse-width modulated signal on the pin.
A special kind of timer called a "watchdog" can be used for production systems to trigger a system reset if your code goes into a fault condition or otherwise becomes unresponsive. To keep this reset from happening, you must "feed" or "pet" the watchdog timer every cycle before it expires.
By arranging for a timer to send a signal to another peripheral instead of an external pin, you can schedule periodic sampling of an analog-to-digital converter, or periodic transfer of a buffer to a communication peripheral by a DMA peripheral.
Clever use of timers with peripherals can take a great deal of load and complexity out of your software and ensure that timing-critical tasks are carried out more precisely than software is easily capable of.
I2C
Inter-Integrated Circuit
Protocol overview: https://i2c.info/
This is a 2-wire synchronous serial bus protocol. The two signals are named:
-
SCL - Clock (Up to 100kHz in slow mode, up to 400kHz in fast mode)
-
SDA - Data (address and data multiplexed)
It is a multi-master bus protocol; the STM32F103 can function as master or slave. Devices on the bus use open-collector I/O, pulled-up externally to 3.3V. Each device has a unique address, either 7 or 10 bits depending on the mode, but we'll only worry about 7-bit mode for now. Data is sampled on the rising edge of the clock.
A master-mode device initiates a transaction by pulling the data line low for one bit period while leaving the clock line high; this is called the "start" signal.
It then clocks out 7 bits of address, followed by a 1 to indicate a write transaction or a 0 to indicate a read transaction.
After clocking out the 8th bit, it releases the bus and cycles the clock one more time. This is the "ack" cycle, and the receiver pulls the data line low during this clock cycle as an acknowledgment. This "ack" cycle is repeated after every byte of data is transmitted by either party, and the other is responsible for doing the acknowledgment.
If a write transaction was indicated, the master device can continue clocking out bytes, waiting for an "ack" after each one, until it is finished with the transaction. If a read transaction was indicated, the slave device takes over driving the data line while the master cycles the clock and acknowledges the slave bytes. The master can end the transaction by leaving the data line high during the "ack" cycle, which signals "nack".
At the end of a transaction, the master signals that the bus is free by letting the data line transition from low to high while the clock line is high. This makes the "stop" symbol.
Sometimes a devices will require the master to write a value to the slave, then immediately perform a read again. Rather than sending a "stop" followed by a "start", the master can just send "start"; this is known as "repeated start". It still has to follow with the slave address, this time indicating a write transaction. The write-followed-by-read pair is often used when a slave devices has multiple internal registers to read from. The write selects the register, and the read reads its value.
The I2C peripheral also supports the closely related SMBus protocol, which is used on PC motherboards for talking to memory sticks, batteries, temperature sensors, etc.
SPI
Serial Peripheral Interface
This is another synchronous serial bus protocol with the capability to be full-duplex. It is generally a single-master bus, and each slave requires a dedicated chip select signal. There are too many variations to go into; this is just the basic operation.
Common signals:
-
SCLK - Clock (as fast as both devices and the board layout can support)
-
MISO - Master In, Slave Out Data
-
MOSI - Master Out, Slave In Data
-
CS - Chip Select (one per slave, usually active-low)
The master is in charge of driving the clock. It may clock out one bit of data on MOSI every clock cycle and clock in one bit of data every clock cycle from MISO.
If a slave device's chip select is inactive, it will ignore all other signals. When active, it may clock out one bit of data for every clock cycle on MOSI and clock in one bit of data from MISO.
Depending on the master and slave, it is possible for both to stream bits out continuously on every clock cycle indefinitely without any start/stop bits, parity bits, etc. and without any particular byte or word divisions. In practice, however, both tend to work in chunks of at least 8 bits and have some sort of device-specific interaction protocol that you will have to read the slave device data sheet to determine.
Because of its ability to continuously shift out bits at a precise rate, the SPI peripheral is often put to off-brand use as an arbitrary digital signal generator on the MOSI line.
DMA
Direct Memory Access
A DMA peripheral is one of the few devices on a bus that can act as a bus master and initiate bus transactions. It is typically used to arrange for a transfer to occur from one bus address to another without the CPU having to be involved.
DMA operations are programmed separately into one of the available DMA channels. The channel gets a source address, destination address, and a transfer size. You can usually arrange for either or both of the addresses to increment by some value after a transfer completes, and sometimes you can arrange for addresses to wrap back to the starting value in order to implement circular buffer operations.
DMA transfers are initiated by a signal called a DMA request, which usually comes from a peripheral, although a control bit can be set by software to manually initiate one. The signal may come from a timer, a communication port, or an analog-to-digital converter; it is up to you to enable the correct signal linkage for the peripheral you want to use DMA with.
The DMA peripheral can signal to software via interrupt at different stages of its transfer operation, in case you need to take some action at those times to ensure that whatever process DMA is enabling continues to run smoothly.
ADC
Analog to Digital Conversion
This translates a voltage level between 0V and a reference voltage into a digital value, i.e. a number. It has 12 bits of precision, meaning that 4096 discrete values can be reported between 0V and the reference voltage. With a 3.3V reference, that means a measurement precision of under 1 millivolt. A conversion takes a minimum of 1 microsecond to complete, so there is a theoretical maximum sample rate of one million per second.
Conversion channels can be set to sample continuously (re-triggering upon completion) or they can be triggered periodically by a timer signal. Completion of conversion (on some channels, at least) can trigger a DMA transfer. These can be used to collect a circular buffer of captured samples in memory at a precise sample rate.
One of the ADC channels (16) is connected to an internal temperature sensor, and another (17) is connected to an internal voltage reference.
There are a wide variety of analog sensors that can be read with an ADC, and they can also be used for user interface devices. A common use is to adjust some parameter by reading the voltage from the wiper contact of a potentiometer, which can form the basis of a game paddle or joystick axis. You can also read a multi-button control strip by clever use of resistor voltage dividers that get switched in and out of circuit by pressing buttons.
USART
Universal Synchronous/Asynchronous Receiver/Transmitter
In asynchronous mode, this can be used as a familiar serial port that you can connect to your computer via a serial-to-USB adapter. You can't connect directly to an old RS232 serial port, however–although the signals follow the same pattern, RS232 uses different voltage levels and could damage your microcontroller!
The baud rate generator can run at up to 4.5Mbit/s, and you can select 8 or 9 bit word length (i.e. 0 or 1 parity bits) and 1 or 2 stop bits.
Additional serial protocols supported by this peripheral include LIN (an automotive bus), IrDA SIR (infrared remote control), and Smartcard emulation.
USB
Universal Serial Bus
The USB peripheral supports USB 2.0 Full Speed, which can operate at up to 12Mbit/s. It functions only as a device (rather than host or on-the-go modes) and supports up to 8 endpoints.
The protocol is too complex to go into much detail about, but Rust libraries exist to help you create HID (keyboards, mice, game controllers), serial, or MIDI endpoints.
CAN
Controller-Area Network
CAN is a serial bus networking protocol that supports a potentially large number of endpoints on a single twisted-pair differential bus. It has a priority-based bus arbitration scheme and networks can be engineered to meet communication latency and reliability goals.
Use of this automotive/industrial control protocol would require an external transceiver device, and it cannot be used concurrently with USB due to sharing a SRAM buffer, so we will not describe it further. But you may want to explore it if you are interested in how devices within your car communicate, or if you want to create a wired home automation network with numerous communicating sensors and control surfaces.