5. Simple GPIO

5.1. Purpose

This activity introduces two methods for interfacing with digital input and output pins within a MSP432 program.

5.2. Hardware and Tools

  • [USB Test Device]: ADALM2000, Analog Discovery, or a multimeter (multimeter available in classroom)

  • MSP-EXP432P401R Launchpad Development Board, OR TI-RSLK Robotic Car

  • Breadboard

  • Components (provided):

    • 2x Pushbuttons

    • 1x Slide Switch

    • 1x LEDs

    • 1x BiColor LED (BiLED)

    • Various Resistors (1x 330Ω, 1x 510Ω, 3x 1kΩ)

  • Wire (available in classroom)

5.3. Description

The bridging of the physical world and a microcontroller’s program is completed through what are known as Registers. In a simplistic sense, registers are memory locations within the microcontroller, accessed through what looks like variables, that are tied to operational aspects of the various subsystems of the microcontroller. This includes but is not limited to: clock system configuration, entry/exit of low power modes, timers, and general purpose input and output (GPIO) configuration and interfacing.

The MSP432P401R has the GPIO pins grouped in sets of 8 pins, called Ports. There are 11 total ports on the device: Ports 1-10 and Port J. The pins within the ports are labelled with numbers 0-7. This allows the notation of Pn to refer to a port, where n is the port number; for example, Port 3 is P3. Further, to refer to a pin within the port, we can use the notation Pn.m, where m is the pin number; for example, P3.6 is referring to Port 3 Pin 6.

There are many registers that are associated with each port. The ones we are concerned with in this activity are[1]:

  • PnIN: Read the input value of input pins.

  • PnOUT: Set the output value of output pins.

  • PnDIR: Configure pins for either input (0) or output (1).

where n is the port number. For each of these registers, the bit number of the register is associated with the pin number. For example, P2.5 may be configured as input by changing bit 5 within P2DIR and then its value can be read from bit 5 of P2IN. This process requires bitmasking. For example:

uint8_t val;
P2DIR &= ~0x20; // Set only bit 5 to 0 to make P2.5 an input
val = (P2IN & 0x20) > 0; // Check the value of P2.5 and get either True or False
    // Code first isolates bit 5 of the register P2IN (sets other bits to 0 in a temporary variable)
    // If bit 5 is 1 the number will be >0 (True,0x01). If bit 5 is 0 the number is 0 (False,0x00)

The above can be done in many ways, and what is shown is just one instance. However, in most cases, this process is cumbersome for working with individual pins. Thankfully, there are more intuitive functions provided from the manufacturer (Texas Instruments) that we can use to make it simpler. These functions are part of what is known as the TI DriverLib. The DriverLib, known as a Hardware Abstraction Layer, or HAL, by other manufacturers, allows for the interfacing to the GPIO (and other components) without having to understand the registers thoroughly. Several DriverLib functions that operate on the registers listed above are[2]:

  • uint8_t GPIO_getInputPinValue(uint8_t port,uint8_t pins): Read the value of a pin within the selected port. Returns 0x01 if the input is High and 0x00 if the input is Low.

  • void GPIO_setOutputLowOnPin(uint8_t port,uint8_t pins): Set one or multiple pins on a port to output Low if configured as outputs.

  • void GPIO_setOutputHighOnPin(uint8_t port,uint8_t pins): Set one or multiple pins on a port to output High if configured as outputs.

  • void GPIO_toggleOutputOnPin(uint8_t port,uint8_t pins): Invert the output level of one or multiple pins on a port if configured as outputs.

  • void GPIO_setAsInputPin(uint8_t port,uint8_t pins): Configure one or multiple pins on a port to be inputs.

  • void GPIO_setAsOutputPin(uint8_t port,uint8_t pins): Configure one or multiple pins on a port to be outputs.

For each of the functions listed above, the value for the first argument, uint8_t port, may simply be the port number (1-10, 11 for port J), or the predefined symbols GPIO_PORT_Pn can be used, where n again is the port number. The second argument, uint8_t pins, should use the predefined symbols GPIO_PINm, where m is the pin number. These functions will not work correctly if the pin number is directly given to the function.

For all the functions listed above except GPIO_getInputPinValue, multiple pins can be modified at once. To do this, all desired pin symbols should be ‘bitwise or’ed together. For example, to set P4.1 and P4.6 to outputs, with the first Low and the second High, the following code can be used:

GPIO_setAsOutputPin( GPIO_PORT_P4, GPIO_PIN1 | GPIO_PIN6 ); // Set both pins as outputs
GPIO_setOutputLowOnPin( GPIO_PORT_P4, GPIO_PIN1 ); // Set P4.1 to low
GPIO_setOutputHighOnPin( GPIO_PORT_P4, GPIO_PIN6 ); // Set P4.6 to high

5.4. Instructions

5.4.1. Build and Verify Hardware

This activity will use the Input and Output schematic as explored in the previous activity:

../_images/final_uC.png

Warning

!!!READ THIS!!! A grade of 0 for the assignment will be assessed if the instructions in this warning block are not adhered to. It is imperative to follow this warning to avoid destroying laboratory hardware.

There are no 5V connections within the schematic above, only 3.3V! This is because the microcontroller pins are only 3.3V tolerant and will likely fail if 5V is applied to them. Ensure that you never use 5V when connecting to this microcontroller!

All power for circuits must be provided from the Launchpad Board or RSLK when using these devices. Do not, we repeat: !!DO NOT!!, use the power supplies from the ADALM2000 or Analog Discovery as they may damage the MSP432P401R, especially if set to a voltage greater than 3.3V. You may access the Launchpad Board or RSLK 3.3V supply and GND from the locations marked with blue rectangles in the figure below. Make sure to avoid the 5V pins.

../_images/devboard_power.svg
  1. To start, assemble the circuit as shown on your personal protoboard (not the RSLK) such that the components are wired to the Launchpad Board as specified in the table below. Do not plug the Launchpad Board into your computer at this time. The 3.3V and GND connections are provided from the Launchpad Board.

    Component

    Pin(s)

    SS1

    P3.5

    PB1

    P5.6

    PB2

    P5.7

    BiLED1

    P6.0,P6.1

    LED1

    P5.1

    Note

    Several of the laboratory Launchpad Board or RSLK components have had the hardware pin connections cut off or plugged. This has been done to indicate that the MSP432P401R pin that the hardware pin is connected to has been burnt out by not following the warning block as above. Ask your instructor if the instructions specify that you must use a pin that has been cut. We will likely ask you to use an alternative pin (specified by us). See FAQ.

  2. With the circuit complete, plug the Launchpad Board into your computer. This will power the 3.3V supply on the Launchpad Board. When modifying any circuitry, always disable the power supply (unplug the devboard, turn off RSLK) to avoid unintended connections, such as when a wire is being moved, from breaking components.

  3. Use the USB Test Device or a multimeter to verify the circuitry is built correctly. Make sure to connect the GND of the USB Test Device to GND of the Launchpad Board. It is suggested to check these points:

    • Check that the 3.3V supply on the Launchpad Board is active, either by checking the voltage directly on the Launchpad Board or from a point on the breadboard.

    • Check that each pushbutton produces an output change where the Launchpad Board pin is connected.

    • The LEDs cannot be tested with the USB Test Device or a multimeter. Do not use the power supply/waveform generators to test the LEDs. See the warning box above.

5.4.2. Register Level

  1. We will first complete a program that interfaces with the hardware through registers. Start by downloading and importing the activity_gpio.zip.

  2. Create three global variables prior to the main function, one for each input: pb1, pb2, and ss1. These can all be uint8_t types and will be used to store the current value of the inputs. Note: looks like these might already exist in the template? Woops.

  3. We need to complete the configuration of the inputs and outputs within the function definition for GPIOInit() (initially line 64, below the main function). As we will complete this task with bitmasking, there is no need to know the final value for either P3DIR, P5DIR, or P6DIR; simply bitmask the appropriate bits high and low.

    • Remember that the command &= can only set bits low, while |= can only set bits high.

  4. Finish the code to get the values for each input within the function definition for GetInputs() (initially line 70).

  5. With the initialization and input code completed, it is good idea to test the system at this point prior to implementing any logic. A printf() statement is included for this within the while(1). Run the program to see if it is successful.

  6. We can also test the outputs at this stage: uncomment the output test code within the while(1) and modify the bitmasking as requested. If the outputs are assembled and configured properly, the BiLED1 should blink GREEN-OFF-RED-OFF, with LED1 lighting for half that cycle. If the LEDs are not operating as specified, use the USB Test Device to check how the associated pins are behaving.

  7. Once this testing is completed, comment out all test code within the while(1) and uncomment the function call to RegisterLogic().

  8. Within RegisterLogic(), the logic to produce the logic table from the previous activity is mostly complete. Fix the issues noted in the comments marked // **ACTIVITY** using registers.

  9. Test the code.

    • Reiterated requirements of the operation from the truth table (shortened):
      • Slideswitch ON, PB1 pressed: BiLED1 RED (or GREEN), LED1 OFF

      • Slideswitch ON, PB2 pressed: BiLED2 GREEN (or RED), LED1 ON

      • Slideswitch ON, PB1 and PB2 pressed: BiLED2 OFF, LED1 ON

      • All other cases: BiLED2 OFF, LED1 OFF.

5.4.3. DriverLib

  1. Now, we’ll modify the program to use the DriverLib. First, comment out the register operations in GPIOInit() and replace with void GPIO_setAsInputPin() and void GPIO_setAsOutputPin(). You’ll need 4 statements at a minimum[3]. To test these changes, run the program and verify that it still operates appropriately.

  2. Next, modify the code within GetInputs() to use the DriverLib and test again.

  3. Now comment out the call to RegisterLogic() within the while(1) and uncomment the call to DriverLibLogic().

  4. Within DriverLibLogic(), the same logic structure from RegisterLogic() is copied with the same omissions; however, the register operations have been changed to equivalent DriverLib implementations. Fix the omissions again but instead use the DriverLib functions.

  5. Test the code again to ensure proper operation.

  6. Submit a photo of your test circuit and your final code to the Gradescope assignment.

Footnotes