In this short video, I will explain how to interface a joystick on the STM32L4 discovery
kit by programming GPIO pins as digital input.
The STM32L4 reference manual and the schematic diagram of STM32L4 discovery kit are two very
helpful documents for this lecture.
While the reference manual is long, you do not have to read it chapter by chapter.
Embedded system engineers need to learn how to navigate the reference manual to quickly
identify the relevant information.
The STM32L4 discovery kit has a four-direction joystick.
The user may push in one of four directions at a time: up, down, left, and right.
The user may also press the center of the joystick.
The center is often used as a selector.
Here is the schematic diagram, which shows the connections between the processor pins
and the joystick.
GPIO pins PA 0, PA 1, PA 5, PA 2, PA 3 are connected to the center, left, down, right,
and up pin of the joystick, respectively.
Each pin is connected to the ground via a capacitor.
The purpose of these capacitors is to perform hardware debouncing.
When pressed, the switch within the joystick may bounce back and forth a few times before
settling down.
The bounces usually settle within 20 milliseconds.
A capacitor can filter out any quick changes in a signal.
Therefore, the capacitor can remove the bounces or glitches associated with switch transitions.
Here is the internal diagram of the joystick.
It has five switches.
The common terminal is connected to the positive 3 volt.
In this lecture, we will write a software program to detect whether the center of the
joystick is pressed.
When the user presses the center of the joystick, this center switch is then closed.
As result, pin PA 0 is then connected to the 3 volt.
Note that, the joystick center terminal is pulled down to ground via a 10K resistor.
Therefore, the default voltage on the joystick center terminal is zero.
However, the other four joystick terminals are not pulled down.
Most GPIO ports have 16 pins.
This diagram shows the standard structure of one GPIO pin.
It includes the basic structure for both digital input and digital output.
In this lecture, I will only focus on the digital input.
I have discussed the digital output in the previous lecture video.
Let's quickly review GPIO output.
There are four important registers related to output, including the output data register,
the mode register, the data output type register, and the pull-up pull-down register.
We can use the mode register to configure the function of the pin.
If the pin is used as GPIO output, the mode bits should be 01.
If the pin is used as GPIO input, the mode bits should be 00.
The output type register sets the output pin as either push-pull or open-drain.
The pull-up pull-down register specifies whether the pin is pulled up to a high voltage or
the pin is pulled down to the ground.
Again, here is the overall diagram of the GPIO module for one I/O pin.
In this lecture, we will only focus on GPIO input.
Except the GPIO mode register, there are two other registers, which are related to GPIO
input.
They are the input data register (IDR), and the pull-up pull-down register (PUPDR).
The input module includes one important electronic component, called Schmitt Trigger.
The Schmitt trigger circuit is a special voltage comparator.
It has two functions.
First, it reduces noises, and provides a cleaner and more reliable signal.
Second, it converts a slow signal edge into a clean edge with instantaneous transition.
Thus, it can increase the slew rate of signals.
Let me explain the motivations of the Schmitt trigger.
In practice, an analog signal often has electronic noise, introduced by various electronic components.
The noise makes the signal fluctuate frequently.
In addition, analog signal tends to rise or fall slowly, because of inherent parasitic
capacitance, resistance, or induction in electronic circuits.
Accordingly, analog signals tend to have small slew rates.
The slew rate describes how fast a voltage changes.
It is usually measured in volts per microsecond.
Let's see what will happen, if we use a simple comparator to convert the analog
input signal to a binary digital signal.
The simple comparator compares the input voltage with a pre-defined threshold.
If the input is larger than the threshold, then the comparator outputs high level.
Otherwise, the comparator outputs low level.
Here is the output of the simple comparator.
Different from the simple comparator, the Schmitt Trigger is a special circuit, which
switches the output, based on two different thresholds.
They are called the trigger high threshold, and the trigger low threshold.
The output of a Schmitt Trigger depends on the current input and the history of the input.
When the input voltage increases from zero, the output remains low until the input becomes
larger than the high threshold.
Similarly, when the voltage decreases gradually, the output remains high until the input becomes
smaller than the low threshold.
Any fluctuation in the range between the high and low thresholds is ignored by the Schmitt
trigger.
This figure compares the output of the Schmitt Trigger and the simple comparator.
When the input signal fluctuates slightly, the output of the Schmitt Trigger does not
switch its output level.
For example, at the beginning, the output of Schmitt Trigger is low.
When the input signal fluctuates, the output remains low as long as the input signal is
lower than the high threshold.
Similarly, if the current output is high, even though the input fluctuates, the output
remains high as long as the input is higher than the low threshold.
From this simple example, we can see that the Schmitt Trigger switches its output, much
less frequently than the simple comparator.
Accordingly, the Schmitt trigger helps eliminate noise in the input signal.
As introduced in the lecture GPIO output, the clock of most peripherals is turned off
in order to achieve the maximum energy efficiency.
The joystick terminals are connected to five different pins in GPIO port A.
First of all, we need to enable the clock of port A. The clock can be turned on or turned
off by configuring the reset and clock control module (RCC).
We need to set the GPIO A Enable Bit to 1.
When the GPIO A Enable bit is 1, the clock signal can pass through this AND gate to drive
the port A. On the other hand, if the GPIO A Enable bit is zero, the output of the logic
AND is always zero.
Accordingly, port A has no clock input.
Software can set the GPIO A Enable bit to 1 by using bitwise OR.
In order to make the code more readable, we use this macro to define this constant.
In fact, this macro has already been defined in the device header file.
Next, we need to program pin 0 of Port A, as digital input.
The function of each pin is determined by two bits in the mode register.
For example, bit 1 and bit 0 control the function of pin 0.
When these two bits are 00, the pin is set as digital input.
Here is the C statement, which clears bit 1 and bit 0.
This statement sets pin 0 of port A as digital input.
When a GPIO pin is used for digital input, the default state of a pin can be high voltage,
low voltage, or high impedance.
The high impedance state is also called floating or tri-stated.
Pull-up and pull-down are used to ensure the input pin has a valid input, either logic
1 or logic 0, when the external circuit does not drive the pin.
When a pin is configured as pull-down, the pin is then internally connected to the ground
via a resistor.
Similarly, when software configures a pin as pull-up, the pin is internally connected
to the power supply via a resistor.
When a pin is neither pulled up nor pulled down internally, then the pin has high impedance.
Note that the internal pull-up and pull-down resistors have large impedance, typically
large than 10K ohms.
When external circuit, connected to a GPIO pin, has a fair amount of capacitance, the
process of pulling the pin voltage to the level of logic high or logic low takes a
long time.
This is because the impedance of the internal pull-up and pull-down resistors is too large.
To meet the speed requirements, external pull-up or pull-down with small resistors are often
needed.
Here is the C code that sets pin 0 as no pull-up, no pull-down.
It clears bit 1 and bit 0 of the PUPDR register by bitwise AND.
Note that pin 0 has already been pulled down externally.
Therefore, we do not have to pull it down internally.
The digital input is sampled every APB cycle.
If the input is high, then the corresponding bit, in the input data register (IDR), is
set.
We can use a mask to read the read the individual bit of the input data register,
as shown in this C code.
For example, in order to read the input on pin 7, we first define a mask.
Then, we use bit-wise operation AND.
We compare the bit-wise result with the mask.
If they are the same, the input on pin 7 is 1.
Otherwise, the input is 0.
This slide summarizes the software code, which read the input of the center switch of the
joystick.
Note that the center terminal of the joystick is connected to pin 0 of port A. The software
involves four steps.
First, we turn on the clock to enable port A. Then, we set the mode of pin 0 as digital
input.
Next, we select no pull-up and no pull-down for pin 0.
Finally, we read bit 0 by using bit-wise AND.
If the bit-wise result is 0, then the center of the joystick is not pressed.
Otherwise, it is pressed.
Please visit the book website for more examples and tutorials.